@earendil-works/pi-env 1.4.0 → 1.5.0
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/CHANGELOG.md +11 -0
- package/bin/pi-env-android-arm64/pi-env +0 -0
- package/bin/pi-env-android-x64/pi-env +0 -0
- package/bin/pi-env-darwin-arm64/pi-env +0 -0
- package/bin/pi-env-darwin-x64/pi-env +0 -0
- package/bin/pi-env-linux-arm64/pi-env +0 -0
- package/bin/pi-env-linux-x64/pi-env +0 -0
- package/bin/pi-env-windows-arm64/pi-env.exe +0 -0
- package/bin/pi-env-windows-x64/pi-env.exe +0 -0
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +47 -5
- package/dist/connection.js.map +1 -1
- package/dist/remote-env.d.ts +2 -2
- package/dist/remote-env.d.ts.map +1 -1
- package/dist/remote-env.js +1 -1
- package/dist/remote-env.js.map +1 -1
- package/dist/watch.d.ts +3 -3
- package/dist/watch.d.ts.map +1 -1
- package/dist/watch.js +20 -17
- package/dist/watch.js.map +1 -1
- package/docs/protocol.md +5 -3
- package/package.json +5 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.5.0] - 2026-11-02
|
|
4
|
+
|
|
5
|
+
### Breaking Changes
|
|
6
|
+
|
|
7
|
+
- `RemoteWatcher` follows Durable's `FileWatcher`: `close(context)` is `stop(context)`, and its changes are tagged (`{ kind: "paths", paths }`, `{ kind: "overflow" }`, `{ kind: "failed", error }`). The daemon's `watch` protocol is unchanged. Migration: `await watcher.close(ctx)` becomes `await watcher.stop(ctx)`; test `change.kind` instead of `"overflow" in change` or `"error" in change`.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- `exec` and `pty` fail with `spawn_error` instead of hanging when the daemon cannot start a helper thread (for example at a cgroup task limit); the started command is killed and reaped ([#11433](https://github.com/earendil-works/pi/issues/11433)).
|
|
12
|
+
- `Connection.close()` on Unix no longer leaves running commands behind: the daemon used to die from the client's `SIGTERM` before killing its process groups. It now kills them on `SIGTERM`, `SIGINT` or `SIGHUP` before exiting.
|
|
13
|
+
|
|
3
14
|
## [1.4.0] - 2026-10-21
|
|
4
15
|
|
|
5
16
|
## [1.3.0] - 2026-10-15
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/connection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE3C,kEAAkE;AAClE,qBAAa,WAAY,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAEtB,YAAY,MAAM,EAAE,IAAI,EAMvB;CACD;AAED,qDAAqD;AACrD,MAAM,WAAW,UAAU;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,sGAAsG;IACtG,GAAG,EAAE,MAAM,CAAC;IACZ,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,gHAAgH;IAChH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAItG;AAED,MAAM,WAAW,iBAAiB;IACjC;;;;OAIG;IACH,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;IAChE,mEAAmE;IACnE,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,KAAK;IACrB,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,UAAU,CAAC;IACpB,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;CAChB;AAQD,MAAM,WAAW,cAAc;IAC9B,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IACpD,gDAAgD;IAChD,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAsBD,+FAA+F;AAC/F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAExD;AAoED;;;GAGG;AACH,qBAAa,UAAU;;IAQtB,YAAY,OAAO,EAAE,iBAAiB,EAErC;IAED,+EAA+E;IACzE,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,CAEhC;IAED,0DAA0D;IACpD,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAE/B;IAEK,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,KAAK,CAAC,CAUlF;IAED,uDAAuD;IACvD,KAAK,IAAI,IAAI,CAGZ;IAED,2CAA2C;IAC3C,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAGtC;CA6LD"}
|
package/dist/connection.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { randomBytes } from "node:crypto";
|
|
3
|
+
import { stripVTControlCharacters } from "node:util";
|
|
3
4
|
/** Frame types (docs/protocol.md). */
|
|
4
5
|
const REQUEST = 1;
|
|
5
6
|
const RESULT = 2;
|
|
@@ -13,6 +14,9 @@ const PING_INTERVAL_MS = 5000;
|
|
|
13
14
|
const SILENCE_LIMIT_MS = 30_000;
|
|
14
15
|
/** How long starting the daemon and its `hello` may take. */
|
|
15
16
|
const START_TIMEOUT_MS = 60_000;
|
|
17
|
+
/** How much stderr a startup error shows: short, because a tool error can reach the model. */
|
|
18
|
+
const STDERR_TAIL_CHARS = 2000;
|
|
19
|
+
const STDERR_TAIL_LINES = 20;
|
|
16
20
|
/** A failure reported by the daemon, with its Node-style code. */
|
|
17
21
|
export class RemoteError extends Error {
|
|
18
22
|
code;
|
|
@@ -61,6 +65,25 @@ export function isConnectionLost(error) {
|
|
|
61
65
|
function closed() {
|
|
62
66
|
return new RemoteError({ code: "unknown", message: "Connection closed" });
|
|
63
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* `message` plus the last lines of `stderr`. The remote machine wrote that text, so terminal escapes and control
|
|
70
|
+
* characters are removed.
|
|
71
|
+
*/
|
|
72
|
+
function withStderr(message, stderr) {
|
|
73
|
+
let text = "";
|
|
74
|
+
for (const char of stripVTControlCharacters(stderr.replace(/\r\n?/g, "\n"))) {
|
|
75
|
+
const code = char.charCodeAt(0);
|
|
76
|
+
if (char === "\n" || char === "\t" || (code >= 0x20 && (code < 0x7f || code > 0x9f)))
|
|
77
|
+
text += char;
|
|
78
|
+
}
|
|
79
|
+
const lines = text
|
|
80
|
+
.split("\n")
|
|
81
|
+
.map((line) => line.trimEnd())
|
|
82
|
+
.filter((line) => line !== "");
|
|
83
|
+
if (lines.length === 0)
|
|
84
|
+
return message;
|
|
85
|
+
return `${message}\nremote stderr:\n${lines.slice(-STDERR_TAIL_LINES).join("\n")}`;
|
|
86
|
+
}
|
|
64
87
|
/** One running daemon. */
|
|
65
88
|
class Session {
|
|
66
89
|
id;
|
|
@@ -74,6 +97,7 @@ class Session {
|
|
|
74
97
|
lastSeen = Date.now();
|
|
75
98
|
timer;
|
|
76
99
|
live = true;
|
|
100
|
+
stderrTail = "";
|
|
77
101
|
constructor(id, child, token) {
|
|
78
102
|
this.id = id;
|
|
79
103
|
this.child = child;
|
|
@@ -208,17 +232,27 @@ export class Connection {
|
|
|
208
232
|
const child = spawn(program, [...args, "serve", "--token", token], { stdio: ["pipe", "pipe", "pipe"] });
|
|
209
233
|
const session = new Session(++this.#sessions, child, token);
|
|
210
234
|
this.#session = session;
|
|
235
|
+
let ready = false;
|
|
211
236
|
let startTimer;
|
|
212
237
|
const failed = new Promise((_resolve, reject) => {
|
|
213
238
|
startTimer = setTimeout(() => reject(lost(`pi-env did not answer within ${START_TIMEOUT_MS / 1000} s`)), START_TIMEOUT_MS);
|
|
214
239
|
child.once("error", (error) => reject(new RemoteError({ code: "spawn_error", message: error.message, lost: true })));
|
|
215
|
-
child.once("
|
|
240
|
+
child.once("close", (code) => reject(lost(`pi-env exited with code ${code} before it was ready`)));
|
|
216
241
|
});
|
|
217
242
|
failed.catch(() => { });
|
|
218
243
|
child.stdout.on("data", (chunk) => this.#onData(session, chunk));
|
|
219
|
-
child.stderr.on("data", (
|
|
244
|
+
child.stderr.setEncoding("utf8").on("data", (text) => {
|
|
245
|
+
if (!ready)
|
|
246
|
+
session.stderrTail = (session.stderrTail + text).slice(-STDERR_TAIL_CHARS);
|
|
247
|
+
this.#options.onLog?.(text);
|
|
248
|
+
});
|
|
220
249
|
child.on("error", () => this.#teardown(session, lost("pi-env connection lost")));
|
|
221
|
-
|
|
250
|
+
// A ready session fails as soon as the daemon exits, even while a process it started keeps a pipe open.
|
|
251
|
+
child.on("exit", () => {
|
|
252
|
+
if (ready)
|
|
253
|
+
this.#teardown(session, lost("pi-env connection lost"));
|
|
254
|
+
});
|
|
255
|
+
child.on("close", () => this.#teardown(session, lost("pi-env connection lost")));
|
|
222
256
|
child.stdin.on("error", () => { });
|
|
223
257
|
session.timer = setInterval(() => {
|
|
224
258
|
this.#write(session, frame(PING, 0, {}));
|
|
@@ -231,11 +265,19 @@ export class Connection {
|
|
|
231
265
|
const { json } = await Promise.race([this.#send(session, "hello", { protocol: 1 }, {}), failed]);
|
|
232
266
|
if (json.protocol !== 1)
|
|
233
267
|
throw lost(`Unsupported protocol ${json.protocol}`);
|
|
268
|
+
ready = true;
|
|
269
|
+
session.stderrTail = "";
|
|
234
270
|
return { info: json, session };
|
|
235
271
|
}
|
|
236
272
|
catch (error) {
|
|
237
|
-
|
|
238
|
-
|
|
273
|
+
// Add the captured stderr to whatever ended the start; only a pre-ready exit waits for it to drain.
|
|
274
|
+
const failure = error instanceof RemoteError
|
|
275
|
+
? new RemoteError({ ...error.fields, message: withStderr(error.message, session.stderrTail) })
|
|
276
|
+
: error instanceof Error
|
|
277
|
+
? error
|
|
278
|
+
: lost(String(error));
|
|
279
|
+
this.#teardown(session, failure);
|
|
280
|
+
throw failure;
|
|
239
281
|
}
|
|
240
282
|
finally {
|
|
241
283
|
clearTimeout(startTimer);
|
package/dist/connection.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcessWithoutNullStreams, spawn } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\n\n/** Frame types (docs/protocol.md). */\nconst REQUEST = 1;\nconst RESULT = 2;\nconst ERROR = 3;\nconst EVENT = 4;\nconst CANCEL = 5;\nconst PING = 6;\n\nconst MAX_FRAME = 16 * 1024 * 1024;\nconst PING_INTERVAL_MS = 5000;\n/** The daemon pings every five seconds; this much silence means the connection is gone. */\nconst SILENCE_LIMIT_MS = 30_000;\n/** How long starting the daemon and its `hello` may take. */\nconst START_TIMEOUT_MS = 60_000;\n\nexport type Json = Record<string, unknown>;\n\n/** A failure reported by the daemon, with its Node-style code. */\nexport class RemoteError extends Error {\n\treadonly code: string;\n\treadonly path?: string;\n\treadonly fields: Json;\n\n\tconstructor(fields: Json) {\n\t\tsuper(typeof fields.message === \"string\" ? fields.message : \"Remote operation failed\");\n\t\tthis.name = \"RemoteError\";\n\t\tthis.code = typeof fields.code === \"string\" ? fields.code : \"unknown\";\n\t\tif (typeof fields.path === \"string\") this.path = fields.path;\n\t\tthis.fields = fields;\n\t}\n}\n\n/** What `hello` reports about the remote machine. */\nexport interface RemoteInfo {\n\tprotocol: number;\n\tversion: string;\n\tos: string;\n\tarch: string;\n\thome: string;\n\ttmpdir: string;\n\t/** Path separator: `/`, or `\\\\` on Windows. */\n\tseparator: string;\n\t/** The daemon's working directory, where Node's `path.resolve` would fall back to `process.cwd()`. */\n\tcwd: string;\n\t/** Windows: per-drive working directories (`C:` → `C:\\\\work`) of the `=C:` variables. */\n\tdriveCwds: Record<string, string>;\n\tpid: number;\n\t/** Operations added to protocol 1 that this daemon supports, such as `listFiles`; absent from older daemons. */\n\tfeatures?: string[];\n}\n\n/**\n * Node's names for the daemon's system and architecture, which `hello` reports in Rust's spelling: `windows` is\n * `win32`, `macos` is `darwin`, `x86_64` is `x64`, `aarch64` is `arm64`, so they compare with `process.platform` and\n * `process.arch`. Other names are kept.\n */\nexport function nodePlatform(info: Pick<RemoteInfo, \"os\" | \"arch\">): { platform: string; arch: string } {\n\tconst platforms: Record<string, string> = { windows: \"win32\", macos: \"darwin\" };\n\tconst archs: Record<string, string> = { x86_64: \"x64\", aarch64: \"arm64\", x86: \"ia32\" };\n\treturn { platform: platforms[info.os] ?? info.os, arch: archs[info.arch] ?? info.arch };\n}\n\nexport interface ConnectionOptions {\n\t/**\n\t * Command that starts the daemon, before its `serve --token <hex>` arguments, e.g. `[\"ssh\", \"-T\", \"--\", \"host\",\n\t * \"~/.pi/mobile/tools/pi-env\"]`. A function computes it at each start (detecting and deploying first, for example);\n\t * its failure fails that start, and the next request tries again.\n\t */\n\tcommand: readonly string[] | (() => Promise<readonly string[]>);\n\t/** Receives the daemon's and the transport's diagnostic output. */\n\tonLog?: (text: string) => void;\n}\n\nexport interface Reply {\n\tjson: Json;\n\tpayload: Uint8Array;\n\t/** The daemon session that answered; handles from it are only valid while it lives. */\n\tsession: number;\n}\n\ntype Pending = {\n\tresolve: (value: Reply) => void;\n\treject: (error: Error) => void;\n\tonEvent?: (json: Json, payload: Uint8Array) => void;\n};\n\nexport interface RequestOptions {\n\tpayload?: Uint8Array;\n\t/** Aborting sends `cancel`; the request still settles with the daemon's result or error. */\n\tsignal?: AbortSignal;\n\t/** Progress events of the request, such as `exec` output. */\n\tonEvent?: (json: Json, payload: Uint8Array) => void;\n\t/** The request's id and session, for `kill`. */\n\tonStart?: (id: number, session: number) => void;\n\t/**\n\t * Only run in this daemon session, for requests on handles it opened. After the connection was lost and started\n\t * again, such requests fail instead of reaching a daemon that never opened the handle.\n\t */\n\tsession?: number;\n}\n\n/** Lone surrogates become U+FFFD, as Node encodes strings for system calls. */\nfunction wellFormed(_key: string, value: unknown): unknown {\n\treturn typeof value === \"string\" ? value.toWellFormed() : value;\n}\n\nfunction frame(type: number, id: number, json: Json, payload: Uint8Array = new Uint8Array(0)): Buffer {\n\tconst body = Buffer.from(JSON.stringify(json, wellFormed), \"utf8\");\n\tconst header = Buffer.alloc(13);\n\theader.writeUInt32BE(9 + body.length + payload.length, 0);\n\theader.writeUInt8(type, 4);\n\theader.writeUInt32BE(id, 5);\n\theader.writeUInt32BE(body.length, 9);\n\treturn Buffer.concat([header, body, payload]);\n}\n\n/** The connection failed or ended; a request may succeed once it is started again. */\nfunction lost(message: string): RemoteError {\n\treturn new RemoteError({ code: \"unknown\", message, lost: true });\n}\n\n/** Whether an error means the connection was lost, not that the daemon refused the request. */\nexport function isConnectionLost(error: unknown): boolean {\n\treturn error instanceof RemoteError && error.fields.lost === true;\n}\n\nfunction closed(): RemoteError {\n\treturn new RemoteError({ code: \"unknown\", message: \"Connection closed\" });\n}\n\n/** One running daemon. */\nclass Session {\n\treadonly id: number;\n\treadonly child: ChildProcessWithoutNullStreams;\n\treadonly token: string;\n\treadonly pending = new Map<number, Pending>();\n\t/** Received bytes not yet parsed, without concatenating on every chunk. */\n\tchunks: Buffer[] = [];\n\tbuffered = 0;\n\tsynced = false;\n\tlastSeen = Date.now();\n\ttimer: ReturnType<typeof setInterval> | undefined;\n\tlive = true;\n\n\tconstructor(id: number, child: ChildProcessWithoutNullStreams, token: string) {\n\t\tthis.id = id;\n\t\tthis.child = child;\n\t\tthis.token = token;\n\t}\n\n\t/** The first `length` buffered bytes as one buffer, without consuming them. */\n\tpeek(length: number): Buffer {\n\t\tif (this.chunks[0]!.length < length) {\n\t\t\tthis.chunks = [Buffer.concat(this.chunks)];\n\t\t}\n\t\treturn this.chunks[0]!.subarray(0, length);\n\t}\n\n\tconsume(length: number): void {\n\t\tthis.buffered -= length;\n\t\twhile (length > 0) {\n\t\t\tconst first = this.chunks[0]!;\n\t\t\tif (first.length <= length) {\n\t\t\t\tthis.chunks.shift();\n\t\t\t\tlength -= first.length;\n\t\t\t} else {\n\t\t\t\tthis.chunks[0] = first.subarray(length);\n\t\t\t\tlength = 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * One connection to a pi-env daemon: started lazily on the first request and started again after it is lost. Requests\n * in flight when it is lost fail with code `unknown`; for mutations their outcome is then unknown.\n */\nexport class Connection {\n\treadonly #options: ConnectionOptions;\n\t#session: Session | undefined;\n\t#ready: Promise<{ info: RemoteInfo; session: Session }> | undefined;\n\t#sessions = 0;\n\t#nextId = 1;\n\t#closed = false;\n\n\tconstructor(options: ConnectionOptions) {\n\t\tthis.#options = options;\n\t}\n\n\t/** Connect if needed and return what the daemon reported about its machine. */\n\tasync info(): Promise<RemoteInfo> {\n\t\treturn (await this.#connect()).info;\n\t}\n\n\t/** Connect if needed and return the live session's id. */\n\tasync session(): Promise<number> {\n\t\treturn (await this.#connect()).session.id;\n\t}\n\n\tasync request(op: string, json: Json, options: RequestOptions = {}): Promise<Reply> {\n\t\tif (options.session !== undefined) {\n\t\t\tconst current = this.#session;\n\t\t\tif (current === undefined || current.id !== options.session || !current.live) {\n\t\t\t\tthrow lost(\"pi-env connection lost\");\n\t\t\t}\n\t\t\treturn this.#send(current, op, json, options);\n\t\t}\n\t\tconst { session } = await this.#connect();\n\t\treturn this.#send(session, op, json, options);\n\t}\n\n\t/** Stop the daemon; it kills everything it started. */\n\tclose(): void {\n\t\tthis.#closed = true;\n\t\tif (this.#session) this.#teardown(this.#session, closed());\n\t}\n\n\t/** Kill one `exec` without aborting it. */\n\tkill(id: number, session: number): void {\n\t\tconst current = this.#session;\n\t\tif (current?.id === session && current.live) this.#write(current, frame(CANCEL, id, { mode: \"kill\" }));\n\t}\n\n\t#connect(): Promise<{ info: RemoteInfo; session: Session }> {\n\t\tif (this.#closed) return Promise.reject(closed());\n\t\tif (this.#ready === undefined) {\n\t\t\tconst ready = this.#start();\n\t\t\tthis.#ready = ready;\n\t\t\t// A failed start is not remembered: the next request tries again.\n\t\t\tready.catch(() => {\n\t\t\t\tif (this.#ready === ready) this.#ready = undefined;\n\t\t\t});\n\t\t}\n\t\treturn this.#ready;\n\t}\n\n\t#send(session: Session, op: string, json: Json, options: RequestOptions): Promise<Reply> {\n\t\tif (!session.live) return Promise.reject(lost(\"pi-env connection lost\"));\n\t\tconst id = this.#nextId++;\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst onAbort = () => this.#write(session, frame(CANCEL, id, {}));\n\t\t\tconst done = () => options.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\tsession.pending.set(id, {\n\t\t\t\tresolve: (value) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tresolve(value);\n\t\t\t\t},\n\t\t\t\treject: (error) => {\n\t\t\t\t\tdone();\n\t\t\t\t\treject(error);\n\t\t\t\t},\n\t\t\t\t...(options.onEvent ? { onEvent: options.onEvent } : {}),\n\t\t\t});\n\t\t\toptions.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\toptions.onStart?.(id, session.id);\n\t\t\tthis.#write(session, frame(REQUEST, id, { ...json, op }, options.payload));\n\t\t\tif (options.signal?.aborted) onAbort();\n\t\t});\n\t}\n\n\t#write(session: Session, data: Buffer): void {\n\t\tif (session.live) session.child.stdin.write(data);\n\t}\n\n\tasync #start(): Promise<{ info: RemoteInfo; session: Session }> {\n\t\tlet command: readonly string[];\n\t\ttry {\n\t\t\tconst option = this.#options.command;\n\t\t\tcommand = typeof option === \"function\" ? await option() : option;\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new RemoteError({ code: \"spawn_error\", message, lost: true });\n\t\t}\n\t\tif (this.#closed) throw closed();\n\t\tconst [program, ...args] = command;\n\t\tif (program === undefined) throw new RemoteError({ code: \"spawn_error\", message: \"No daemon command\" });\n\t\tconst token = randomBytes(16).toString(\"hex\");\n\t\tconst child = spawn(program, [...args, \"serve\", \"--token\", token], { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n\t\tconst session = new Session(++this.#sessions, child, token);\n\t\tthis.#session = session;\n\t\tlet startTimer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst failed = new Promise<never>((_resolve, reject) => {\n\t\t\tstartTimer = setTimeout(\n\t\t\t\t() => reject(lost(`pi-env did not answer within ${START_TIMEOUT_MS / 1000} s`)),\n\t\t\t\tSTART_TIMEOUT_MS,\n\t\t\t);\n\t\t\tchild.once(\"error\", (error) =>\n\t\t\t\treject(new RemoteError({ code: \"spawn_error\", message: error.message, lost: true })),\n\t\t\t);\n\t\t\tchild.once(\"exit\", (code) => reject(lost(`pi-env exited with code ${code} before it was ready`)));\n\t\t});\n\t\tfailed.catch(() => {});\n\t\tchild.stdout.on(\"data\", (chunk: Buffer) => this.#onData(session, chunk));\n\t\tchild.stderr.on(\"data\", (chunk: Buffer) => this.#options.onLog?.(chunk.toString(\"utf8\")));\n\t\tchild.on(\"error\", () => this.#teardown(session, lost(\"pi-env connection lost\")));\n\t\tchild.on(\"exit\", () => this.#teardown(session, lost(\"pi-env connection lost\")));\n\t\tchild.stdin.on(\"error\", () => {});\n\t\tsession.timer = setInterval(() => {\n\t\t\tthis.#write(session, frame(PING, 0, {}));\n\t\t\tif (Date.now() - session.lastSeen > SILENCE_LIMIT_MS) {\n\t\t\t\tthis.#teardown(session, lost(\"pi-env connection timed out\"));\n\t\t\t}\n\t\t}, PING_INTERVAL_MS);\n\t\tsession.timer.unref();\n\t\ttry {\n\t\t\tconst { json } = await Promise.race([this.#send(session, \"hello\", { protocol: 1 }, {}), failed]);\n\t\t\tif (json.protocol !== 1) throw lost(`Unsupported protocol ${json.protocol}`);\n\t\t\treturn { info: json as unknown as RemoteInfo, session };\n\t\t} catch (error) {\n\t\t\tthis.#teardown(session, error instanceof Error ? error : lost(String(error)));\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tclearTimeout(startTimer);\n\t\t}\n\t}\n\n\t#teardown(session: Session, error: Error): void {\n\t\tif (!session.live) return;\n\t\tsession.live = false;\n\t\tclearInterval(session.timer);\n\t\tif (this.#session === session) {\n\t\t\tthis.#session = undefined;\n\t\t\tthis.#ready = undefined;\n\t\t}\n\t\tsession.child.stdin.end();\n\t\tsession.child.kill();\n\t\tconst pending = [...session.pending.values()];\n\t\tsession.pending.clear();\n\t\tfor (const request of pending) request.reject(error);\n\t}\n\n\t#onData(session: Session, chunk: Buffer): void {\n\t\tif (!session.live) return;\n\t\tsession.lastSeen = Date.now();\n\t\tsession.chunks.push(chunk);\n\t\tsession.buffered += chunk.length;\n\t\tif (!session.synced) {\n\t\t\t// Shell startup files may print before the daemon runs; skip everything before its sync line.\n\t\t\tconst marker = Buffer.from(`PI-ENV ${session.token}\\n`, \"utf8\");\n\t\t\tconst all = session.peek(session.buffered);\n\t\t\tconst index = all.indexOf(marker);\n\t\t\tif (index === -1) {\n\t\t\t\tif (session.buffered > 1024 * 1024) {\n\t\t\t\t\tsession.consume(session.buffered - marker.length);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst noise = all.subarray(0, index).toString(\"utf8\").trim();\n\t\t\tif (noise !== \"\") this.#options.onLog?.(noise);\n\t\t\tsession.consume(index + marker.length);\n\t\t\tsession.synced = true;\n\t\t}\n\t\twhile (session.live && session.buffered >= 4) {\n\t\t\tconst length = session.peek(4).readUInt32BE(0);\n\t\t\tif (length < 9 || length > MAX_FRAME) {\n\t\t\t\tthis.#teardown(session, lost(\"Corrupt frame from pi-env\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (session.buffered < 4 + length) return;\n\t\t\tconst body = session.peek(4 + length).subarray(4);\n\t\t\tconst type = body.readUInt8(0);\n\t\t\tconst id = body.readUInt32BE(1);\n\t\t\tconst jsonLength = body.readUInt32BE(5);\n\t\t\tlet json: Json;\n\t\t\ttry {\n\t\t\t\tif (9 + jsonLength > length) throw new Error(\"JSON length out of range\");\n\t\t\t\tconst parsed: unknown = JSON.parse(body.subarray(9, 9 + jsonLength).toString(\"utf8\"));\n\t\t\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed))\n\t\t\t\t\tthrow new Error(\"not an object\");\n\t\t\t\tjson = parsed as Json;\n\t\t\t} catch {\n\t\t\t\tthis.#teardown(session, lost(\"Corrupt frame from pi-env\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// A plain Uint8Array copy, like `NodeExecutionEnv`'s reader results, not a view of the receive buffer.\n\t\t\tconst payload = new Uint8Array(body.subarray(9 + jsonLength));\n\t\t\tsession.consume(4 + length);\n\t\t\tthis.#dispatch(session, type, id, json, payload);\n\t\t}\n\t}\n\n\t#dispatch(session: Session, type: number, id: number, json: Json, payload: Uint8Array): void {\n\t\tconst pending = session.pending.get(id);\n\t\tif (type === EVENT) {\n\t\t\tpending?.onEvent?.(json, payload);\n\t\t\treturn;\n\t\t}\n\t\tif (type !== RESULT && type !== ERROR) return;\n\t\tif (pending === undefined) return;\n\t\tsession.pending.delete(id);\n\t\tif (type === RESULT) pending.resolve({ json, payload, session: session.id });\n\t\telse pending.reject(new RemoteError(json));\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcessWithoutNullStreams, spawn } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport { stripVTControlCharacters } from \"node:util\";\n\n/** Frame types (docs/protocol.md). */\nconst REQUEST = 1;\nconst RESULT = 2;\nconst ERROR = 3;\nconst EVENT = 4;\nconst CANCEL = 5;\nconst PING = 6;\n\nconst MAX_FRAME = 16 * 1024 * 1024;\nconst PING_INTERVAL_MS = 5000;\n/** The daemon pings every five seconds; this much silence means the connection is gone. */\nconst SILENCE_LIMIT_MS = 30_000;\n/** How long starting the daemon and its `hello` may take. */\nconst START_TIMEOUT_MS = 60_000;\n/** How much stderr a startup error shows: short, because a tool error can reach the model. */\nconst STDERR_TAIL_CHARS = 2000;\nconst STDERR_TAIL_LINES = 20;\n\nexport type Json = Record<string, unknown>;\n\n/** A failure reported by the daemon, with its Node-style code. */\nexport class RemoteError extends Error {\n\treadonly code: string;\n\treadonly path?: string;\n\treadonly fields: Json;\n\n\tconstructor(fields: Json) {\n\t\tsuper(typeof fields.message === \"string\" ? fields.message : \"Remote operation failed\");\n\t\tthis.name = \"RemoteError\";\n\t\tthis.code = typeof fields.code === \"string\" ? fields.code : \"unknown\";\n\t\tif (typeof fields.path === \"string\") this.path = fields.path;\n\t\tthis.fields = fields;\n\t}\n}\n\n/** What `hello` reports about the remote machine. */\nexport interface RemoteInfo {\n\tprotocol: number;\n\tversion: string;\n\tos: string;\n\tarch: string;\n\thome: string;\n\ttmpdir: string;\n\t/** Path separator: `/`, or `\\\\` on Windows. */\n\tseparator: string;\n\t/** The daemon's working directory, where Node's `path.resolve` would fall back to `process.cwd()`. */\n\tcwd: string;\n\t/** Windows: per-drive working directories (`C:` → `C:\\\\work`) of the `=C:` variables. */\n\tdriveCwds: Record<string, string>;\n\tpid: number;\n\t/** Operations added to protocol 1 that this daemon supports, such as `listFiles`; absent from older daemons. */\n\tfeatures?: string[];\n}\n\n/**\n * Node's names for the daemon's system and architecture, which `hello` reports in Rust's spelling: `windows` is\n * `win32`, `macos` is `darwin`, `x86_64` is `x64`, `aarch64` is `arm64`, so they compare with `process.platform` and\n * `process.arch`. Other names are kept.\n */\nexport function nodePlatform(info: Pick<RemoteInfo, \"os\" | \"arch\">): { platform: string; arch: string } {\n\tconst platforms: Record<string, string> = { windows: \"win32\", macos: \"darwin\" };\n\tconst archs: Record<string, string> = { x86_64: \"x64\", aarch64: \"arm64\", x86: \"ia32\" };\n\treturn { platform: platforms[info.os] ?? info.os, arch: archs[info.arch] ?? info.arch };\n}\n\nexport interface ConnectionOptions {\n\t/**\n\t * Command that starts the daemon, before its `serve --token <hex>` arguments, e.g. `[\"ssh\", \"-T\", \"--\", \"host\",\n\t * \"~/.pi/mobile/tools/pi-env\"]`. A function computes it at each start (detecting and deploying first, for example);\n\t * its failure fails that start, and the next request tries again.\n\t */\n\tcommand: readonly string[] | (() => Promise<readonly string[]>);\n\t/** Receives the daemon's and the transport's diagnostic output. */\n\tonLog?: (text: string) => void;\n}\n\nexport interface Reply {\n\tjson: Json;\n\tpayload: Uint8Array;\n\t/** The daemon session that answered; handles from it are only valid while it lives. */\n\tsession: number;\n}\n\ntype Pending = {\n\tresolve: (value: Reply) => void;\n\treject: (error: Error) => void;\n\tonEvent?: (json: Json, payload: Uint8Array) => void;\n};\n\nexport interface RequestOptions {\n\tpayload?: Uint8Array;\n\t/** Aborting sends `cancel`; the request still settles with the daemon's result or error. */\n\tsignal?: AbortSignal;\n\t/** Progress events of the request, such as `exec` output. */\n\tonEvent?: (json: Json, payload: Uint8Array) => void;\n\t/** The request's id and session, for `kill`. */\n\tonStart?: (id: number, session: number) => void;\n\t/**\n\t * Only run in this daemon session, for requests on handles it opened. After the connection was lost and started\n\t * again, such requests fail instead of reaching a daemon that never opened the handle.\n\t */\n\tsession?: number;\n}\n\n/** Lone surrogates become U+FFFD, as Node encodes strings for system calls. */\nfunction wellFormed(_key: string, value: unknown): unknown {\n\treturn typeof value === \"string\" ? value.toWellFormed() : value;\n}\n\nfunction frame(type: number, id: number, json: Json, payload: Uint8Array = new Uint8Array(0)): Buffer {\n\tconst body = Buffer.from(JSON.stringify(json, wellFormed), \"utf8\");\n\tconst header = Buffer.alloc(13);\n\theader.writeUInt32BE(9 + body.length + payload.length, 0);\n\theader.writeUInt8(type, 4);\n\theader.writeUInt32BE(id, 5);\n\theader.writeUInt32BE(body.length, 9);\n\treturn Buffer.concat([header, body, payload]);\n}\n\n/** The connection failed or ended; a request may succeed once it is started again. */\nfunction lost(message: string): RemoteError {\n\treturn new RemoteError({ code: \"unknown\", message, lost: true });\n}\n\n/** Whether an error means the connection was lost, not that the daemon refused the request. */\nexport function isConnectionLost(error: unknown): boolean {\n\treturn error instanceof RemoteError && error.fields.lost === true;\n}\n\nfunction closed(): RemoteError {\n\treturn new RemoteError({ code: \"unknown\", message: \"Connection closed\" });\n}\n\n/**\n * `message` plus the last lines of `stderr`. The remote machine wrote that text, so terminal escapes and control\n * characters are removed.\n */\nfunction withStderr(message: string, stderr: string): string {\n\tlet text = \"\";\n\tfor (const char of stripVTControlCharacters(stderr.replace(/\\r\\n?/g, \"\\n\"))) {\n\t\tconst code = char.charCodeAt(0);\n\t\tif (char === \"\\n\" || char === \"\\t\" || (code >= 0x20 && (code < 0x7f || code > 0x9f))) text += char;\n\t}\n\tconst lines = text\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trimEnd())\n\t\t.filter((line) => line !== \"\");\n\tif (lines.length === 0) return message;\n\treturn `${message}\\nremote stderr:\\n${lines.slice(-STDERR_TAIL_LINES).join(\"\\n\")}`;\n}\n\n/** One running daemon. */\nclass Session {\n\treadonly id: number;\n\treadonly child: ChildProcessWithoutNullStreams;\n\treadonly token: string;\n\treadonly pending = new Map<number, Pending>();\n\t/** Received bytes not yet parsed, without concatenating on every chunk. */\n\tchunks: Buffer[] = [];\n\tbuffered = 0;\n\tsynced = false;\n\tlastSeen = Date.now();\n\ttimer: ReturnType<typeof setInterval> | undefined;\n\tlive = true;\n\tstderrTail = \"\";\n\n\tconstructor(id: number, child: ChildProcessWithoutNullStreams, token: string) {\n\t\tthis.id = id;\n\t\tthis.child = child;\n\t\tthis.token = token;\n\t}\n\n\t/** The first `length` buffered bytes as one buffer, without consuming them. */\n\tpeek(length: number): Buffer {\n\t\tif (this.chunks[0]!.length < length) {\n\t\t\tthis.chunks = [Buffer.concat(this.chunks)];\n\t\t}\n\t\treturn this.chunks[0]!.subarray(0, length);\n\t}\n\n\tconsume(length: number): void {\n\t\tthis.buffered -= length;\n\t\twhile (length > 0) {\n\t\t\tconst first = this.chunks[0]!;\n\t\t\tif (first.length <= length) {\n\t\t\t\tthis.chunks.shift();\n\t\t\t\tlength -= first.length;\n\t\t\t} else {\n\t\t\t\tthis.chunks[0] = first.subarray(length);\n\t\t\t\tlength = 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * One connection to a pi-env daemon: started lazily on the first request and started again after it is lost. Requests\n * in flight when it is lost fail with code `unknown`; for mutations their outcome is then unknown.\n */\nexport class Connection {\n\treadonly #options: ConnectionOptions;\n\t#session: Session | undefined;\n\t#ready: Promise<{ info: RemoteInfo; session: Session }> | undefined;\n\t#sessions = 0;\n\t#nextId = 1;\n\t#closed = false;\n\n\tconstructor(options: ConnectionOptions) {\n\t\tthis.#options = options;\n\t}\n\n\t/** Connect if needed and return what the daemon reported about its machine. */\n\tasync info(): Promise<RemoteInfo> {\n\t\treturn (await this.#connect()).info;\n\t}\n\n\t/** Connect if needed and return the live session's id. */\n\tasync session(): Promise<number> {\n\t\treturn (await this.#connect()).session.id;\n\t}\n\n\tasync request(op: string, json: Json, options: RequestOptions = {}): Promise<Reply> {\n\t\tif (options.session !== undefined) {\n\t\t\tconst current = this.#session;\n\t\t\tif (current === undefined || current.id !== options.session || !current.live) {\n\t\t\t\tthrow lost(\"pi-env connection lost\");\n\t\t\t}\n\t\t\treturn this.#send(current, op, json, options);\n\t\t}\n\t\tconst { session } = await this.#connect();\n\t\treturn this.#send(session, op, json, options);\n\t}\n\n\t/** Stop the daemon; it kills everything it started. */\n\tclose(): void {\n\t\tthis.#closed = true;\n\t\tif (this.#session) this.#teardown(this.#session, closed());\n\t}\n\n\t/** Kill one `exec` without aborting it. */\n\tkill(id: number, session: number): void {\n\t\tconst current = this.#session;\n\t\tif (current?.id === session && current.live) this.#write(current, frame(CANCEL, id, { mode: \"kill\" }));\n\t}\n\n\t#connect(): Promise<{ info: RemoteInfo; session: Session }> {\n\t\tif (this.#closed) return Promise.reject(closed());\n\t\tif (this.#ready === undefined) {\n\t\t\tconst ready = this.#start();\n\t\t\tthis.#ready = ready;\n\t\t\t// A failed start is not remembered: the next request tries again.\n\t\t\tready.catch(() => {\n\t\t\t\tif (this.#ready === ready) this.#ready = undefined;\n\t\t\t});\n\t\t}\n\t\treturn this.#ready;\n\t}\n\n\t#send(session: Session, op: string, json: Json, options: RequestOptions): Promise<Reply> {\n\t\tif (!session.live) return Promise.reject(lost(\"pi-env connection lost\"));\n\t\tconst id = this.#nextId++;\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst onAbort = () => this.#write(session, frame(CANCEL, id, {}));\n\t\t\tconst done = () => options.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\tsession.pending.set(id, {\n\t\t\t\tresolve: (value) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tresolve(value);\n\t\t\t\t},\n\t\t\t\treject: (error) => {\n\t\t\t\t\tdone();\n\t\t\t\t\treject(error);\n\t\t\t\t},\n\t\t\t\t...(options.onEvent ? { onEvent: options.onEvent } : {}),\n\t\t\t});\n\t\t\toptions.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\toptions.onStart?.(id, session.id);\n\t\t\tthis.#write(session, frame(REQUEST, id, { ...json, op }, options.payload));\n\t\t\tif (options.signal?.aborted) onAbort();\n\t\t});\n\t}\n\n\t#write(session: Session, data: Buffer): void {\n\t\tif (session.live) session.child.stdin.write(data);\n\t}\n\n\tasync #start(): Promise<{ info: RemoteInfo; session: Session }> {\n\t\tlet command: readonly string[];\n\t\ttry {\n\t\t\tconst option = this.#options.command;\n\t\t\tcommand = typeof option === \"function\" ? await option() : option;\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new RemoteError({ code: \"spawn_error\", message, lost: true });\n\t\t}\n\t\tif (this.#closed) throw closed();\n\t\tconst [program, ...args] = command;\n\t\tif (program === undefined) throw new RemoteError({ code: \"spawn_error\", message: \"No daemon command\" });\n\t\tconst token = randomBytes(16).toString(\"hex\");\n\t\tconst child = spawn(program, [...args, \"serve\", \"--token\", token], { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n\t\tconst session = new Session(++this.#sessions, child, token);\n\t\tthis.#session = session;\n\t\tlet ready = false;\n\t\tlet startTimer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst failed = new Promise<never>((_resolve, reject) => {\n\t\t\tstartTimer = setTimeout(\n\t\t\t\t() => reject(lost(`pi-env did not answer within ${START_TIMEOUT_MS / 1000} s`)),\n\t\t\t\tSTART_TIMEOUT_MS,\n\t\t\t);\n\t\t\tchild.once(\"error\", (error) =>\n\t\t\t\treject(new RemoteError({ code: \"spawn_error\", message: error.message, lost: true })),\n\t\t\t);\n\t\t\tchild.once(\"close\", (code) => reject(lost(`pi-env exited with code ${code} before it was ready`)));\n\t\t});\n\t\tfailed.catch(() => {});\n\t\tchild.stdout.on(\"data\", (chunk: Buffer) => this.#onData(session, chunk));\n\t\tchild.stderr.setEncoding(\"utf8\").on(\"data\", (text: string) => {\n\t\t\tif (!ready) session.stderrTail = (session.stderrTail + text).slice(-STDERR_TAIL_CHARS);\n\t\t\tthis.#options.onLog?.(text);\n\t\t});\n\t\tchild.on(\"error\", () => this.#teardown(session, lost(\"pi-env connection lost\")));\n\t\t// A ready session fails as soon as the daemon exits, even while a process it started keeps a pipe open.\n\t\tchild.on(\"exit\", () => {\n\t\t\tif (ready) this.#teardown(session, lost(\"pi-env connection lost\"));\n\t\t});\n\t\tchild.on(\"close\", () => this.#teardown(session, lost(\"pi-env connection lost\")));\n\t\tchild.stdin.on(\"error\", () => {});\n\t\tsession.timer = setInterval(() => {\n\t\t\tthis.#write(session, frame(PING, 0, {}));\n\t\t\tif (Date.now() - session.lastSeen > SILENCE_LIMIT_MS) {\n\t\t\t\tthis.#teardown(session, lost(\"pi-env connection timed out\"));\n\t\t\t}\n\t\t}, PING_INTERVAL_MS);\n\t\tsession.timer.unref();\n\t\ttry {\n\t\t\tconst { json } = await Promise.race([this.#send(session, \"hello\", { protocol: 1 }, {}), failed]);\n\t\t\tif (json.protocol !== 1) throw lost(`Unsupported protocol ${json.protocol}`);\n\t\t\tready = true;\n\t\t\tsession.stderrTail = \"\";\n\t\t\treturn { info: json as unknown as RemoteInfo, session };\n\t\t} catch (error) {\n\t\t\t// Add the captured stderr to whatever ended the start; only a pre-ready exit waits for it to drain.\n\t\t\tconst failure =\n\t\t\t\terror instanceof RemoteError\n\t\t\t\t\t? new RemoteError({ ...error.fields, message: withStderr(error.message, session.stderrTail) })\n\t\t\t\t\t: error instanceof Error\n\t\t\t\t\t\t? error\n\t\t\t\t\t\t: lost(String(error));\n\t\t\tthis.#teardown(session, failure);\n\t\t\tthrow failure;\n\t\t} finally {\n\t\t\tclearTimeout(startTimer);\n\t\t}\n\t}\n\n\t#teardown(session: Session, error: Error): void {\n\t\tif (!session.live) return;\n\t\tsession.live = false;\n\t\tclearInterval(session.timer);\n\t\tif (this.#session === session) {\n\t\t\tthis.#session = undefined;\n\t\t\tthis.#ready = undefined;\n\t\t}\n\t\tsession.child.stdin.end();\n\t\tsession.child.kill();\n\t\tconst pending = [...session.pending.values()];\n\t\tsession.pending.clear();\n\t\tfor (const request of pending) request.reject(error);\n\t}\n\n\t#onData(session: Session, chunk: Buffer): void {\n\t\tif (!session.live) return;\n\t\tsession.lastSeen = Date.now();\n\t\tsession.chunks.push(chunk);\n\t\tsession.buffered += chunk.length;\n\t\tif (!session.synced) {\n\t\t\t// Shell startup files may print before the daemon runs; skip everything before its sync line.\n\t\t\tconst marker = Buffer.from(`PI-ENV ${session.token}\\n`, \"utf8\");\n\t\t\tconst all = session.peek(session.buffered);\n\t\t\tconst index = all.indexOf(marker);\n\t\t\tif (index === -1) {\n\t\t\t\tif (session.buffered > 1024 * 1024) {\n\t\t\t\t\tsession.consume(session.buffered - marker.length);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst noise = all.subarray(0, index).toString(\"utf8\").trim();\n\t\t\tif (noise !== \"\") this.#options.onLog?.(noise);\n\t\t\tsession.consume(index + marker.length);\n\t\t\tsession.synced = true;\n\t\t}\n\t\twhile (session.live && session.buffered >= 4) {\n\t\t\tconst length = session.peek(4).readUInt32BE(0);\n\t\t\tif (length < 9 || length > MAX_FRAME) {\n\t\t\t\tthis.#teardown(session, lost(\"Corrupt frame from pi-env\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (session.buffered < 4 + length) return;\n\t\t\tconst body = session.peek(4 + length).subarray(4);\n\t\t\tconst type = body.readUInt8(0);\n\t\t\tconst id = body.readUInt32BE(1);\n\t\t\tconst jsonLength = body.readUInt32BE(5);\n\t\t\tlet json: Json;\n\t\t\ttry {\n\t\t\t\tif (9 + jsonLength > length) throw new Error(\"JSON length out of range\");\n\t\t\t\tconst parsed: unknown = JSON.parse(body.subarray(9, 9 + jsonLength).toString(\"utf8\"));\n\t\t\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed))\n\t\t\t\t\tthrow new Error(\"not an object\");\n\t\t\t\tjson = parsed as Json;\n\t\t\t} catch {\n\t\t\t\tthis.#teardown(session, lost(\"Corrupt frame from pi-env\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// A plain Uint8Array copy, like `NodeExecutionEnv`'s reader results, not a view of the receive buffer.\n\t\t\tconst payload = new Uint8Array(body.subarray(9 + jsonLength));\n\t\t\tsession.consume(4 + length);\n\t\t\tthis.#dispatch(session, type, id, json, payload);\n\t\t}\n\t}\n\n\t#dispatch(session: Session, type: number, id: number, json: Json, payload: Uint8Array): void {\n\t\tconst pending = session.pending.get(id);\n\t\tif (type === EVENT) {\n\t\t\tpending?.onEvent?.(json, payload);\n\t\t\treturn;\n\t\t}\n\t\tif (type !== RESULT && type !== ERROR) return;\n\t\tif (pending === undefined) return;\n\t\tsession.pending.delete(id);\n\t\tif (type === RESULT) pending.resolve({ json, payload, session: session.id });\n\t\telse pending.reject(new RemoteError(json));\n\t}\n}\n"]}
|
package/dist/remote-env.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type PlatformPath } from "node:path";
|
|
2
2
|
import type { Context } from "@earendil-works/chord";
|
|
3
|
-
import { type BinaryReader, type DirReader, type ExecutionEnv, ExecutionError, FileError, type FileInfo, type FileListing, type FileWatcher, type ListFilesOptions, type Result, type ShellExecOptions, type ShellExecResult, type TextLineReader, type
|
|
3
|
+
import { type BinaryReader, type DirReader, type ExecutionEnv, ExecutionError, type FileChange, FileError, type FileInfo, type FileListing, type FileWatcher, type ListFilesOptions, type Result, type ShellExecOptions, type ShellExecResult, type TextLineReader, type WatchTarget } from "@earendil-works/pi-durable/env";
|
|
4
4
|
import { type Connection, type RemoteInfo } from "./connection.ts";
|
|
5
5
|
import { type RemoteWatchOptions } from "./watch.ts";
|
|
6
6
|
export interface RemoteExecutionEnvOptions {
|
|
@@ -61,7 +61,7 @@ export declare class RemoteExecutionEnv implements ExecutionEnv {
|
|
|
61
61
|
prefix?: string;
|
|
62
62
|
suffix?: string;
|
|
63
63
|
} | undefined, context: Context): Promise<Result<string, FileError>>;
|
|
64
|
-
watch(targets: readonly WatchTarget[], onChange: (change:
|
|
64
|
+
watch(targets: readonly WatchTarget[], onChange: (change: FileChange) => void, context: Context): Promise<Result<FileWatcher, FileError>>;
|
|
65
65
|
exec(command: string | readonly string[], options: ShellExecOptions | undefined, context: Context): Promise<Result<ShellExecResult, ExecutionError>>;
|
|
66
66
|
cleanup(_context: Context): Promise<void>;
|
|
67
67
|
}
|
package/dist/remote-env.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-env.d.ts","sourceRoot":"","sources":["../src/remote-env.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAgB,MAAM,WAAW,CAAC;AAG5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,cAAc,EAEd,SAAS,EACT,KAAK,QAAQ,EAEb,KAAK,WAAW,EAChB,KAAK,WAAW,EAEhB,KAAK,gBAAgB,EAErB,KAAK,MAAM,EACX,KAAK,gBAAgB,EACrB,KAAK,eAAe,EAKpB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,
|
|
1
|
+
{"version":3,"file":"remote-env.d.ts","sourceRoot":"","sources":["../src/remote-env.ts"],"names":[],"mappings":"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"}
|
package/dist/remote-env.js
CHANGED
|
@@ -731,7 +731,7 @@ export class RemoteExecutionEnv {
|
|
|
731
731
|
const watcher = await RemoteWatcher.open(this.connection, resolved, onChange, this.#watchOptions);
|
|
732
732
|
const afterOpen = abortResult(context.abortSignal);
|
|
733
733
|
if (afterOpen) {
|
|
734
|
-
await watcher.
|
|
734
|
+
await watcher.stop(context);
|
|
735
735
|
return afterOpen;
|
|
736
736
|
}
|
|
737
737
|
return ok(watcher);
|
package/dist/remote-env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-env.js","sourceRoot":"","sources":["../src/remote-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAqB,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAIN,cAAc,EACd,GAAG,EACH,SAAS,EAOT,EAAE,EAMF,aAAa,GAKb,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAA8B,YAAY,EAAE,WAAW,EAAmB,MAAM,iBAAiB,CAAC;AACzG,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAA2B,MAAM,YAAY,CAAC;AAEpE,MAAM,cAAc,GAAG,aAAa,CAAC;AACrC,MAAM,mBAAmB,GAAG,cAAc,GAAG,IAAI,CAAC;AAClD,mFAAmF;AACnF,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC;AAC9B,MAAM,UAAU,GAAG,CAAC,CAAC;AACrB,gGAAgG;AAChG,MAAM,WAAW,GAAG,GAAG,GAAG,IAAI,CAAC;AAC/B,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,gHAAgH;AAChH,MAAM,eAAe,GAAG,GAAG,GAAG,IAAI,CAAC;AACnC,MAAM,uBAAuB,GAAG,EAAE,GAAG,IAAI,CAAC;AAC1C,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAClC,wCAAwC;AACxC,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,CAAC;AAkB7B,8CAA8C;AAC9C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAsB;IACtD,OAAO,YAAY,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;AACnF,CAAC;AAED,SAAS,MAAM,CAAC,IAAY,EAAE,MAAsB,EAAE,KAAmB;IACxE,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,uBAAuB,EAAE,IAAI,CAAC,CAAC,CAAC;IACjG,OAAO,EAAE,CAAC;QACT,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC1B,IAAI;QACJ,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO,EAAE,MAAM,CAAC,QAAQ,GAAG,IAAI,GAAG,MAAM,CAAC,SAAS,GAAG,GAAG;KACxD,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,MAA6B,EAAE,KAAa;IAC3D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,CAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC3B,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC;IAC1B,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,SAAS,CACvB,IAA6D,EAC7D,MAAc,EACd,MAAc,EACd,KAAa,EACb,OAAsB;IAEtB,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,IAAI,GAAG,MAAM,CAAC;IAClB,MAAM,QAAQ,GAAqD,EAAE,CAAC;IACtE,OAAO,KAAK,GAAG,MAAM,EAAE,CAAC;QACvB,OAAO,QAAQ,CAAC,MAAM,GAAG,UAAU,IAAI,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;YAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC;YACrD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC/B,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACvC,IAAI,IAAI,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAG,CAAC;QAC/B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;QAC/B,IAAI,OAAO,EAAE;YAAE,OAAO,SAAS,CAAC;QAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM;QAC9B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC;QACtB,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,8EAA8E;YAC9E,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YACpB,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC;QACvB,CAAC;IACF,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC1B,CAAC;AAED,iEAAiE;AACjE,MAAM,MAAM;IACF,GAAG,CAAqB;IACxB,EAAE,CAAS;IACX,OAAO,CAAS;IAChB,IAAI,CAAS;IAEtB,YAAY,GAAuB,EAAE,EAAU,EAAE,OAAe,EAAE,IAAY;QAC7E,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,EAAU,EAAE,IAAI,GAAS,EAAE,EAAE,OAAO,GAAmD,EAAE;QAChG,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7G,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAA0B,EAAE,MAAc;QACrD,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IACvG,CAAC;IAED,KAAK,CAAC,KAAK;QACV,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACD;AAED,MAAM,kBAAkB;IACd,OAAO,CAAS;IACzB,OAAO,GAAG,KAAK,CAAC;IAEhB,YAAY,MAAc;QACzB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,IAAI,KAAK;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED,aAAa;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,yBAAyB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxG,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAgB;QAC1B,MAAM,KAAK,GAAG,WAAW,CAAW,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,aAAa,EAAY,CAAC;QACvG,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,IAAI,CAAC;YACJ,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACrD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,IAAiC,EAAE,MAAM,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;QAC7G,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5C,CAAC;IACF,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAc,EAAE,OAAgB;QAC1D,MAAM,KAAK,GAAG,WAAW,CAAa,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,aAAa,EAAc,CAAC;QAC3G,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YAChG,OAAO,GAAG,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,sDAAsD,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1G,CAAC;QACD,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,SAAS,CAC3B,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,EAC1C,MAAM,EACN,MAAM,EACN,UAAU,EACV,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAC3C,CAAC;YACF,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,GAAG,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACpF,OAAO,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5C,CAAC;IACF,CAAC;IAED,KAAK,CAAC,SAAS,CACd,OAAgD,EAChD,OAAgB;QAEhB,MAAM,KAAK,GAAG,WAAW,CAAW,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,aAAa,EAAY,CAAC;QACvG,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QACvC,IACC,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC;YAChC,SAAS,GAAG,CAAC;YACb,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,SAAS,CAAC,CAAC,EAClF,CAAC;YACF,OAAO,GAAG,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,oBAAoB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,CAAC;YACJ,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAC1C,WAAW,EACX,EAAE,SAAS,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAC5D,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAC1D,CAAC;YACF,OAAO,EAAE,CAAC,IAA2B,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5C,CAAC;IACF,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAiB;QAC5B,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;CACD;AAED,MAAM,eAAe;IACX,OAAO,CAAS;IACzB,KAAK,GAAG,KAAK,CAAC;IACd,OAAO,GAAG,KAAK,CAAC;IAEhB,YAAY,MAAc;QACzB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,IAAI,CACT,UAAkB,EAClB,OAAgB;QAEhB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QAC/B,MAAM,OAAO,GAAG,WAAW,CAAyC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC/F,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,GAAG,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,4BAA4B,EAAE,IAAI,CAAC,CAAC,CAAC;QAC3F,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;YAC1D,OAAO,GAAG,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,4CAA4C,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,OAAO,GAAe,EAAE,CAAC;QAC/B,IAAI,CAAC;YACJ,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC5D,yEAAyE;YACzE,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;gBACnD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC7F,MAAM,SAAS,GAAG,WAAW,CAAyC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;gBACjG,IAAI,SAAS;oBAAE,OAAO,SAAS,CAAC;gBAChC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAA2B,EAAE,CAAC;oBACtD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;oBAClD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;wBAC/B,2EAA2E;wBAC3E,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ;4BAAE,SAAS;wBAC5C,OAAO,GAAG,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;oBAClE,CAAC;oBACD,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAK,EAAE,KAAK,CAAC,CAAC;oBACnD,IAAI,IAAI,CAAC,EAAE;wBAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACvC,CAAC;gBACD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;YACjC,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;IACF,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAiB;QAC5B,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;CACD;AAED,sFAAsF;AACtF,MAAM,oBAAoB;IAChB,OAAO,CAAS;IAChB,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;IACxC,OAAO,GAAG,CAAC,CAAC;IACZ,SAAS,GAAG,EAAE,CAAC;IACf,MAAM,GAAG,KAAK,CAAC;IACf,OAAO,GAAG,KAAK,CAAC;IAEhB,YAAY,MAAc;QACzB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAgB;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QAC/B,MAAM,OAAO,GAAG,WAAW,CAAuB,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC7E,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,GAAG,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,4BAA4B,EAAE,IAAI,CAAC,CAAC,CAAC;QAC3F,IAAI,CAAC;YACJ,OAAO,IAAI,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC7C,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;oBACpB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;oBAC9C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;oBACnD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvC,CAAC;gBACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBACjB,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;wBAAE,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;oBACtD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;oBAC5B,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;oBACpB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;gBACxC,CAAC;gBACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;gBACjE,MAAM,cAAc,GAAG,WAAW,CAAuB,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;gBACpF,IAAI,cAAc;oBAAE,OAAO,cAAc,CAAC;gBAC1C,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC;gBAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACxB,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;oBACzC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACpB,CAAC;qBAAM,CAAC;oBACP,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC/C,CAAC;YACF,CAAC;QACF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;IACF,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAiB;QAC5B,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;CACD;AAED;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IACrB,EAAE,CAAS;IACpB,GAAG,CAAS;IACH,UAAU,CAAa;IACvB,UAAU,CAAqB;IAC/B,SAAS,CAAqC;IAC9C,aAAa,CAAqB;IAC3C,kEAAkE;IACzD,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE9C,YAAY,OAAkC;QAC7C,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;QAClC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;IAC1C,CAAC;IAED,kGAAkG;IAClG,KAAK,CAAC,QAAQ,CAAC,IAAY;QAC1B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC;QACxD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;QACtC,IAAI,UAAU,GAAG,IAAI,CAAC;QACtB,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;YACxB,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC;QACxB,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACrF,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC;gBACJ,UAAU,GAAG,aAAa,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;YACrD,CAAC;YAAC,MAAM,CAAC;gBACR,uDAAuD;YACxD,CAAC;QACF,CAAC;QACD,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACnE,IAAI,OAAO,EAAE,CAAC;YACb,6GAA6G;YAC7G,mFAAmF;YACnF,MAAM,KAAK,GAAG,uBAAuB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC5D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvF,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC;gBAC3D,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;oBAAE,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC;gBACpG,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACxC,CAAC;QACF,CAAC;QACD,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,OAAO,CACZ,IAAY,EACZ,OAAgB,EAChB,GAAqC,EACrC,KAAK,GAAsB,QAAQ;QAEnC,IAAI,QAAgB,CAAC;QACrB,IAAI,CAAC;YACJ,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;QACD,MAAM,OAAO,GAAG,WAAW,CAAI,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC9D,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,IAAI,CAAC;YACJ,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC;YAClC,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;gBACtB,MAAM,KAAK,GAAG,WAAW,CAAI,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;gBAC5D,IAAI,KAAK;oBAAE,OAAO,KAAK,CAAC;YACzB,CAAC;YACD,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC1C,CAAC;IACF,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,IAAU;QACvC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QACjF,OAAO,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAgB,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7G,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAY,EAAE,QAAiB;QACjD,IAAI,CAAC;YACJ,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;IACF,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAe,EAAE,QAAiB;QAChD,IAAI,CAAC;YACJ,OAAO,EAAE,CAAC,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;QAC/D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QAChC,CAAC;IACF,CAAC;IAED,oGAAoG;IACpG,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,QAAiB,EAAE,OAAgB;QAChE,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;QACnC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YACrD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YACtE,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;YAC/C,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,2BAA2B,EAAE,QAAQ,CAAC,CAAC;YACpF,IAAI,CAAC;gBACJ,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;oBAAE,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,SAAiB,CAAC,CAAC;gBAChF,IAAI,OAAO,EAAE;oBAAE,MAAM,KAAK,EAAE,CAAC;gBAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAsB,CAAC;gBACzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClD,IAAI,IAAI,GAAG,aAAa,EAAE,CAAC;oBAC1B,MAAM,IAAI,SAAS,CAAC,SAAS,EAAE,cAAc,IAAI,yBAAyB,EAAE,QAAQ,CAAC,CAAC;gBACvF,CAAC;gBACD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBAChB,0EAA0E;oBAC1E,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;oBAC1C,MAAM,MAAM,GAAiB,EAAE,CAAC;oBAChC,IAAI,KAAK,GAAG,CAAC,CAAC;oBACd,IAAI,IAAI,GAAG,EAAE,CAAC;oBACd,OAAO,IAAI,EAAE,CAAC;wBACb,IAAI,OAAO,EAAE;4BAAE,MAAM,KAAK,EAAE,CAAC;wBAC7B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,uBAAuB,CAAC,CAAC;wBACrE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;4BAAE,MAAM;wBAC9B,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC;wBACtB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;wBACnB,IAAI,QAAQ;4BAAE,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;oBAC5C,CAAC;oBACD,IAAI,CAAC,QAAQ;wBAAE,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBACnD,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;gBAChD,CAAC;gBACD,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACf,8FAA8F;oBAC9F,IAAI,IAAI,IAAI,eAAe;wBAAE,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;oBAC7E,MAAM,IAAI,GAAG,MAAM,SAAS,CAC3B,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,EACxC,CAAC,EACD,IAAI,EACJ,eAAe,EACf,OAAO,CACP,CAAC;oBACF,IAAI,IAAI,KAAK,SAAS;wBAAE,MAAM,KAAK,EAAE,CAAC;oBACtC,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC/C,CAAC;gBACD,8FAA8F;gBAC9F,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;gBAC/C,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;gBAC1C,IAAI,IAAI,GAAG,EAAE,CAAC;gBACd,IAAI,KAAK,GAAG,CAAC,CAAC;gBACd,IAAI,KAAK,GAAG,IAAI,CAAC;gBACjB,MAAM,QAAQ,GAA0B,EAAE,CAAC;gBAC3C,IAAI,IAAI,GAAG,CAAC,CAAC;gBACb,OAAO,IAAI,EAAE,CAAC;oBACb,OAAO,QAAQ,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;wBACrC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;wBACzC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;wBACtB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;wBACrB,IAAI,IAAI,MAAM,CAAC;oBAChB,CAAC;oBACD,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAG,CAAC;oBACtC,IAAI,OAAO,EAAE;wBAAE,MAAM,KAAK,EAAE,CAAC;oBAC7B,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC;oBACtB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;wBACrE,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;oBAC7F,CAAC;oBACD,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;oBAC1C,KAAK,GAAG,KAAK,CAAC;gBACf,CAAC;YACF,CAAC;oBAAS,CAAC;gBACV,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACtB,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAY,EAAE,OAAgB;QAChD,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAA8B,CAAC;IACjF,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,IAAY,EAAE,OAAgB;QAClD,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAkC,CAAC;IACtF,CAAC;IAED,KAAK,CAAC,gBAAgB,CACrB,IAAY,EACZ,OAA2C,EAC3C,OAAgB;QAEhB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YACnE,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACtF,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,MAAM,CAAC;QAC9B,MAAM,OAAO,GAAG,WAAW,CAAe,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClF,IAAI,OAAO,EAAE,CAAC;YACb,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAC3B,OAAO,OAAO,CAAC;QAChB,CAAC;QACD,OAAO,EAAE,CAAC,IAAI,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,IAAY,EAAE,OAAgB;QACtD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YACnE,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QAC9D,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,MAAM,CAAC;QAC9B,MAAM,OAAO,GAAG,WAAW,CAAiB,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpF,IAAI,OAAO,EAAE,CAAC;YACb,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAC3B,OAAO,OAAO,CAAC;QAChB,CAAC;QACD,OAAO,EAAE,CAAC,IAAI,oBAAoB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,aAAa,CAClB,IAAY,EACZ,OAA0C,EAC1C,OAAgB;QAEhB,IAAI,OAAO,EAAE,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,IAAI,CAAC;YAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,MAAM,CAAC;QAC9B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,CAAC;YACJ,OAAO,OAAO,EAAE,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;gBAC3E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAClD,IAAI,CAAC,IAAI,CAAC,EAAE;oBAAE,OAAO,IAAI,CAAC;gBAC1B,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;oBAAE,MAAM;gBACpC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC;YACD,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;gBAAS,CAAC;YACV,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC;IACF,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,OAA4B,EAAE,MAAe,EAAE,OAAgB;QACzF,MAAM,KAAK,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QACnF,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;QACxD,OAAO,IAAI,CAAC,OAAO,CAClB,IAAI,EACJ,OAAO,EACP,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClB,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC;YACxC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3G,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAgB,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YACtF,MAAM,QAAQ,GAAuB,EAAE,CAAC;YACxC,IAAI,CAAC;gBACJ,KAAK,IAAI,MAAM,GAAG,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,IAAI,WAAW,EAAE,CAAC;oBAC7E,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;wBACrB,uFAAuF;wBACvF,MAAM,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;wBACnG,IAAI,MAAM,KAAK,SAAS;4BAAE,MAAM,MAAM,CAAC,MAAM,CAAC;wBAC9C,MAAM,IAAI,SAAS,CAAC,SAAS,EAAE,2BAA2B,EAAE,QAAQ,CAAC,CAAC;oBACvE,CAAC;oBACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAC7B,YAAY,EACZ,EAAE,EACF,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC,EAAE,CACzD,CAAC;oBACF,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;oBACxB,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACvB,IAAI,QAAQ,CAAC,MAAM,IAAI,WAAW;wBAAE,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAC5D,CAAC;gBACD,sFAAsF;gBACtF,KAAK,MAAM,OAAO,IAAI,QAAQ;oBAAE,MAAM,OAAO,CAAC;YAC/C,CAAC;oBAAS,CAAC;gBACV,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACnC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACtB,CAAC;QACF,CAAC,EACD,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAC1B,CAAC;IACH,CAAC;IAED,SAAS,CAAC,IAAY,EAAE,OAA4B,EAAE,OAAgB;QACrE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAED,UAAU,CAAC,IAAY,EAAE,OAA4B,EAAE,OAAgB;QACtE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAY,EAAE,IAAY,EAAE,OAAgB;QAC9D,OAAO,IAAI,CAAC,OAAO,CAClB,IAAI,EACJ,OAAO,EACP,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC7C,MAAM,IAAI,SAAS,CAAC,SAAS,EAAE,+CAA+C,EAAE,QAAQ,CAAC,CAAC;YAC3F,CAAC;YACD,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC,EACD,MAAM,CACN,CAAC;IACH,CAAC;IAED,SAAS,CAAC,IAAY,EAAE,OAAgB;QACvC,OAAO,IAAI,CAAC,OAAO,CAClB,IAAI,EACJ,OAAO,EACP,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClB,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5D,CAAC,EACD,MAAM,CACN,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,UAAkB,EAAE,eAAuB,EAAE,OAAgB;QAC7E,IAAI,MAAc,CAAC;QACnB,IAAI,WAAmB,CAAC;QACxB,IAAI,CAAC;YACJ,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YACzC,WAAW,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,OAAO,GAAG,WAAW,CAAO,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACpE,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;YAC3E,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,OAAgB;QAC5C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YACnE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC5E,OAAO,MAAM,CAAC,QAAQ,EAAE,IAAiC,EAAE,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAC/F,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAC1C,CAAC;IAED,OAAO,CAAC,IAAY,EAAE,OAAgB;QACrC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YACrD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACjD,MAAM,OAAO,GAAqB,EAAE,CAAC;YACrC,IAAI,CAAC;gBACJ,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC,IAAI,GAAI,CAAC;oBAChC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;oBAChE,OAAO,CAAC,IAAI,CAAC,GAAI,IAAI,CAAC,OAA4B,CAAC,CAAC;oBACpD,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;gBAC3B,CAAC;YACF,CAAC;oBAAS,CAAC;gBACV,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACtB,CAAC;YACD,gHAAgH;YAChH,2DAA2D;YAC3D,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAChD,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;gBACrB,MAAM,GAAG,GAAG,CAAC,KAAqB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;gBACjG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxD,CAAC;YACD,MAAM,KAAK,GAAe,EAAE,CAAC;YAC7B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,OAAO,CAAC,WAAW,EAAE,OAAO;oBAAE,MAAM,IAAI,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;gBACtF,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACtD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;oBAAE,MAAM,WAAW,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,CAAC;gBAC1F,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAK,EAAE,KAAK,CAAC,CAAC;gBACnD,IAAI,IAAI,CAAC,EAAE;oBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrC,CAAC;YACD,OAAO,KAAK,CAAC;QACd,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,qFAAqF;IACrF,KAAK,CAAC,SAAS,CACd,IAAY,EACZ,OAAqC,EACrC,OAAgB;QAEhB,IAAI,QAAgB,CAAC;QACrB,IAAI,CAAC;YACJ,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC9B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3E,OAAO,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAgB,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;IAC3F,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAY,EAAE,OAAgB;QACjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC7G,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,MAAM,CAAC;QAC9B,MAAM,OAAO,GAAG,WAAW,CAAY,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/E,IAAI,OAAO,EAAE,CAAC;YACb,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAC3B,OAAO,OAAO,CAAC;QAChB,CAAC;QACD,OAAO,EAAE,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,aAAa,CAAC,IAAY,EAAE,OAAgB;QAC3C,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YACrD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC/E,OAAO,IAAI,CAAC,IAAc,CAAC;QAC5B,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,OAAgB;QAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAClD,IAAI,MAAM,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW;YAAE,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QACxD,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,SAAS,CACR,IAAY,EACZ,OAA4C,EAC5C,OAAgB;QAEhB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YACrD,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI,EAAE,CAAC,CAAC;QACnG,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,MAAM,CACL,IAAY,EACZ,OAA6D,EAC7D,OAAgB;QAEhB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YACrD,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE;gBACnC,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,KAAK;gBACtC,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK;aAC9B,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,MAA0B,EAAE,OAAgB;QAC/D,MAAM,OAAO,GAAG,WAAW,CAAS,OAAO,CAAC,WAAW,CAAC,CAAC;QACzD,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,IAAI,CAAC;YACJ,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;YAChD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAChD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1G,OAAO,EAAE,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QAChC,CAAC;IACF,CAAC;IAED,KAAK,CAAC,cAAc,CACnB,OAAyD,EACzD,OAAgB;QAEhB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,GAAG,CAAC;QACxB,IAAI,QAAQ,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC;YACJ,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAChD,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,OAAO,EAAE,MAAM,IAAI,EAAE,GAAG,UAAU,EAAE,GAAG,OAAO,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC;YACpG,mEAAmE;YACnE,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAC5B,OAAO,EACP,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EACjD,EAAE,OAAO,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAC9B,CAAC;YACF,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC1C,CAAC;IACF,CAAC;IAED,KAAK,CAAC,KAAK,CACV,OAA+B,EAC/B,QAAuC,EACvC,OAAgB;QAEhB,MAAM,OAAO,GAAG,WAAW,CAAc,OAAO,CAAC,WAAW,CAAC,CAAC;QAC9D,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CACjC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CACtF,CAAC;YACF,MAAM,YAAY,GAAG,WAAW,CAAc,OAAO,CAAC,WAAW,CAAC,CAAC;YACnE,IAAI,YAAY;gBAAE,OAAO,YAAY,CAAC;YACtC,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;YAClG,MAAM,SAAS,GAAG,WAAW,CAAc,OAAO,CAAC,WAAW,CAAC,CAAC;YAChE,IAAI,SAAS,EAAE,CAAC;gBACf,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAC7B,OAAO,SAAS,CAAC;YAClB,CAAC;YACD,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QAChC,CAAC;IACF,CAAC;IAED,KAAK,CAAC,IAAI,CACT,OAAmC,EACnC,OAAqC,EACrC,OAAgB;QAEhB,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;QACnC,IAAI,MAAM,EAAE,OAAO;YAAE,OAAO,GAAG,CAAC,IAAI,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QAC1E,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;QACjC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;gBAC/C,OAAO,GAAG,CAAC,IAAI,cAAc,CAAC,SAAS,EAAE,qDAAqD,CAAC,CAAC,CAAC;YAClG,CAAC;YACD,IAAI,OAAO,GAAG,IAAI,GAAG,cAAc,EAAE,CAAC;gBACrC,OAAO,GAAG,CAAC,IAAI,cAAc,CAAC,SAAS,EAAE,+BAA+B,mBAAmB,UAAU,CAAC,CAAC,CAAC;YACzG,CAAC;QACF,CAAC;QACD,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,IAAI,CAAC;QAC/C,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACJ,GAAG,GAAG,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAClE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,IAAI,cAAc,CAAC,SAAS,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACnG,CAAC;QACD,IAAI,MAAM,EAAE,OAAO;YAAE,OAAO,GAAG,CAAC,IAAI,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QAC1E,MAAM,GAAG,GAA2B,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CACxC,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,CACzE,EAAE,CAAC;YACH,IAAI,KAAK,KAAK,SAAS;gBAAE,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,GAAG,KAAK,CAAC;QAC1D,CAAC;QACD,IAAI,aAAyC,CAAC;QAC9C,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,OAA2B,CAAC;QAChC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACzC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,IAAI,CAAC;YACJ,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAC7C,MAAM,EACN;gBACC,GAAG,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC;gBACvE,GAAG;gBACH,GAAG;gBACH,UAAU;gBACV,GAAG,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;gBACxE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,EAAE,CAAC;gBAC/D,GAAG,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;gBACjE,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;aACpE,EACD;gBACC,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,OAAO,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE;oBAC/B,OAAO,GAAG,SAAS,CAAC;oBACpB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBACvC,CAAC;gBACD,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;oBAC3B,IAAI,OAAO,IAAI,aAAa,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;wBAAE,OAAO;oBAC9E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;oBAC9F,IAAI,IAAI,KAAK,EAAE,IAAI,OAAO,EAAE,QAAQ,KAAK,SAAS;wBAAE,OAAO;oBAC3D,MAAM,IAAI,GAAoB,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;oBAC1F,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;wBAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAA0B,CAAC;oBACjF,IAAI,CAAC;wBACJ,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;oBACvC,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBAChB,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;wBACxE,aAAa,GAAG,IAAI,cAAc,CAAC,gBAAgB,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;wBAC3E,UAAU,CAAC,KAAK,EAAE,CAAC;oBACpB,CAAC;gBACF,CAAC;aACD,CACD,CAAC;YACF,IAAI,aAAa;gBAAE,OAAO,GAAG,CAAC,aAAa,CAAC,CAAC;YAC7C,OAAO,EAAE,CAAC;gBACT,QAAQ,EAAE,IAAI,CAAC,QAAkB;gBACjC,GAAG,CAAC,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5E,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,aAAa;gBAAE,OAAO,GAAG,CAAC,aAAa,CAAC,CAAC;YAC7C,IAAI,CAAC,CAAC,KAAK,YAAY,WAAW,CAAC,EAAE,CAAC;gBACrC,OAAO,GAAG,CAAC,IAAI,cAAc,CAAC,SAAS,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACnG,CAAC;YACD,MAAM,OAAO,GACZ,KAAK,CAAC,IAAI,KAAK,SAAS;gBACvB,CAAC,CAAC,IAAI,cAAc,CAAC,SAAS,EAAE,WAAW,OAAO,EAAE,CAAC;gBACrD,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS;oBACzB,CAAC,CAAC,IAAI,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC;oBAC1C,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,mBAAmB,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa;wBACnE,CAAC,CAAC,IAAI,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;wBAC/C,CAAC,CAAC,IAAI,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YACnD,IAAI,OAAO,KAAK,CAAC,MAAM,CAAC,SAAS,KAAK,QAAQ;gBAAE,OAAO,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC;YAC3F,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;gBAAS,CAAC;YACV,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,IAAI,OAAO,KAAK,SAAS;gBAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1D,CAAC;IACF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAiB;QAC9B,sGAAsG;QACtG,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC7E,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACD","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { type PlatformPath, posix, win32 } from \"node:path\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Context } from \"@earendil-works/chord\";\nimport {\n\ttype BinaryReader,\n\ttype DirReader,\n\ttype ExecutionEnv,\n\tExecutionError,\n\terr,\n\tFileError,\n\ttype FileInfo,\n\ttype FileKind,\n\ttype FileListing,\n\ttype FileWatcher,\n\ttype LineScan,\n\ttype ListFilesOptions,\n\tok,\n\ttype Result,\n\ttype ShellExecOptions,\n\ttype ShellExecResult,\n\ttype ShellOutputInfo,\n\ttype ShellOutputSkip,\n\tStreamDecoder,\n\ttype TextLine,\n\ttype TextLineReader,\n\ttype WatchChange,\n\ttype WatchTarget,\n} from \"@earendil-works/pi-durable/env\";\nimport { type Connection, type Json, nodePlatform, RemoteError, type RemoteInfo } from \"./connection.ts\";\nimport { abortResult, toFileError } from \"./errors.ts\";\nimport { listFilesOver } from \"./list-files.ts\";\nimport { RemoteWatcher, type RemoteWatchOptions } from \"./watch.ts\";\n\nconst MAX_TIMEOUT_MS = 2_147_483_647;\nconst MAX_TIMEOUT_SECONDS = MAX_TIMEOUT_MS / 1000;\n/** Bytes per `pread` request of a binary reader; several are in flight at once. */\nconst READ_CHUNK = 256 * 1024;\nconst READ_DEPTH = 8;\n/** Node's `writeFile` writes at most this much per call and checks for an abort before each. */\nconst WRITE_CHUNK = 512 * 1024;\nconst WRITE_DEPTH = 8;\n/** Node's `readFile`: chunk of known-size reads, chunk of unknown-size reads, and the largest file it reads. */\nconst READ_FILE_CHUNK = 512 * 1024;\nconst READ_FILE_UNKNOWN_CHUNK = 64 * 1024;\nconst READ_FILE_MAX = 2 ** 31 - 1;\n/** `NodeTextLineReader`'s read size. */\nconst LINE_CHUNK = 64 * 1024;\n\nexport interface RemoteExecutionEnvOptions {\n\tconnection: Connection;\n\t/** The file namespace: equal ids see the same files (`FileSystem.id`), e.g. `pi-env:<env name>`. */\n\tid: string;\n\tcwd: string;\n\tshellPath?: string;\n\t/** Added to the remote environment of every command that inherits it, like `NodeExecutionEnv`'s `shellEnv`. */\n\tshellEnv?: Record<string, string>;\n\t/** How the daemon watches, like `NodeExecutionEnv`'s `watch` option. */\n\twatch?: RemoteWatchOptions;\n}\n\n/** An info record from the daemon. */\ntype RemoteFileInfo = { name: string; kind: FileKind | \"other\"; size: number; mtimeSec: number; mtimeNsec: number };\ntype RemoteDirEntry = { name: string; raw?: number[]; info?: RemoteFileInfo; error?: Json };\n\n/** Node's path rules of the remote system. */\nexport async function remotePath(connection: Connection): Promise<PlatformPath> {\n\treturn nodePlatform(await connection.info()).platform === \"win32\" ? win32 : posix;\n}\n\nfunction toInfo(path: string, remote: RemoteFileInfo, paths: PlatformPath): Result<FileInfo, FileError> {\n\tif (remote.kind === \"other\") return err(new FileError(\"invalid\", \"Unsupported file type\", path));\n\treturn ok({\n\t\tname: paths.basename(path),\n\t\tpath,\n\t\tkind: remote.kind,\n\t\tsize: remote.size,\n\t\tmtimeMs: remote.mtimeSec * 1000 + remote.mtimeNsec / 1e6,\n\t});\n}\n\nfunction concat(chunks: readonly Uint8Array[], total: number): Uint8Array {\n\tif (chunks.length === 1) return chunks[0]!;\n\tconst bytes = new Uint8Array(total);\n\tlet position = 0;\n\tfor (const chunk of chunks) {\n\t\tbytes.set(chunk, position);\n\t\tposition += chunk.length;\n\t}\n\treturn bytes;\n}\n\n/**\n * Read `length` bytes from `offset` as consecutive reads of at most `chunk` bytes, several in flight. Ends early at\n * the end of the file. A short read continues from where it ended, as sequential reads would. `aborted` is checked\n * after each read; `undefined` means aborted.\n */\nasync function readRange(\n\tread: (offset: number, length: number) => Promise<Uint8Array>,\n\toffset: number,\n\tlength: number,\n\tchunk: number,\n\taborted: () => boolean,\n): Promise<{ chunks: Uint8Array[]; total: number } | undefined> {\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\tlet next = offset;\n\tconst inFlight: { length: number; bytes: Promise<Uint8Array> }[] = [];\n\twhile (total < length) {\n\t\twhile (inFlight.length < READ_DEPTH && next < offset + length) {\n\t\t\tconst size = Math.min(offset + length - next, chunk);\n\t\t\tconst bytes = read(next, size);\n\t\t\tbytes.catch(() => {});\n\t\t\tinFlight.push({ length: size, bytes });\n\t\t\tnext += size;\n\t\t}\n\t\tconst head = inFlight.shift()!;\n\t\tconst bytes = await head.bytes;\n\t\tif (aborted()) return undefined;\n\t\tif (bytes.length === 0) break;\n\t\tchunks.push(bytes);\n\t\ttotal += bytes.length;\n\t\tif (bytes.length < head.length) {\n\t\t\t// Reads already in flight assumed a full read; continue right after this one.\n\t\t\tinFlight.length = 0;\n\t\t\tnext = offset + total;\n\t\t}\n\t}\n\treturn { chunks, total };\n}\n\n/** A daemon handle: valid only in the session that opened it. */\nclass Handle {\n\treadonly env: RemoteExecutionEnv;\n\treadonly id: number;\n\treadonly session: number;\n\treadonly path: string;\n\n\tconstructor(env: RemoteExecutionEnv, id: number, session: number, path: string) {\n\t\tthis.env = env;\n\t\tthis.id = id;\n\t\tthis.session = session;\n\t\tthis.path = path;\n\t}\n\n\trequest(op: string, json: Json = {}, options: { signal?: AbortSignal; payload?: Uint8Array } = {}) {\n\t\treturn this.env.connection.request(op, { ...json, handle: this.id }, { ...options, session: this.session });\n\t}\n\n\tasync pread(offset: number | undefined, length: number): Promise<Uint8Array> {\n\t\treturn (await this.request(\"pread\", { ...(offset === undefined ? {} : { offset }), length })).payload;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.request(\"close\").catch(() => undefined);\n\t}\n}\n\nclass RemoteBinaryReader implements BinaryReader {\n\treadonly #handle: Handle;\n\t#closed = false;\n\n\tconstructor(handle: Handle) {\n\t\tthis.#handle = handle;\n\t}\n\n\tget #path(): string {\n\t\treturn this.#handle.path;\n\t}\n\n\t#closedResult<T>(): Result<T, FileError> | undefined {\n\t\treturn this.#closed ? err(new FileError(\"invalid\", \"Binary reader is closed\", this.#path)) : undefined;\n\t}\n\n\tasync info(context: Context): Promise<Result<FileInfo, FileError>> {\n\t\tconst early = abortResult<FileInfo>(context.abortSignal, this.#path) ?? this.#closedResult<FileInfo>();\n\t\tif (early) return early;\n\t\ttry {\n\t\t\tconst { json } = await this.#handle.request(\"fstat\");\n\t\t\treturn toInfo(this.#path, json as unknown as RemoteFileInfo, await remotePath(this.#handle.env.connection));\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, this.#path));\n\t\t}\n\t}\n\n\tasync read(offset: number, length: number, context: Context): Promise<Result<Uint8Array, FileError>> {\n\t\tconst early = abortResult<Uint8Array>(context.abortSignal, this.#path) ?? this.#closedResult<Uint8Array>();\n\t\tif (early) return early;\n\t\tif (!Number.isSafeInteger(offset) || offset < 0 || !Number.isSafeInteger(length) || length < 0) {\n\t\t\treturn err(new FileError(\"invalid\", \"Offset and length must be non-negative safe integers\", this.#path));\n\t\t}\n\t\ttry {\n\t\t\tconst read = await readRange(\n\t\t\t\t(at, size) => this.#handle.pread(at, size),\n\t\t\t\toffset,\n\t\t\t\tlength,\n\t\t\t\tREAD_CHUNK,\n\t\t\t\t() => context.abortSignal?.aborted === true,\n\t\t\t);\n\t\t\tif (read === undefined) return err(new FileError(\"aborted\", \"aborted\", this.#path));\n\t\t\treturn ok(concat(read.chunks, read.total));\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, this.#path));\n\t\t}\n\t}\n\n\tasync scanLines(\n\t\toptions: { startLine: number; endLine?: number },\n\t\tcontext: Context,\n\t): Promise<Result<LineScan, FileError>> {\n\t\tconst early = abortResult<LineScan>(context.abortSignal, this.#path) ?? this.#closedResult<LineScan>();\n\t\tif (early) return early;\n\t\tconst { startLine, endLine } = options;\n\t\tif (\n\t\t\t!Number.isSafeInteger(startLine) ||\n\t\t\tstartLine < 0 ||\n\t\t\t(endLine !== undefined && (!Number.isSafeInteger(endLine) || endLine <= startLine))\n\t\t) {\n\t\t\treturn err(new FileError(\"invalid\", \"Invalid line range\", this.#path));\n\t\t}\n\t\ttry {\n\t\t\tconst { json } = await this.#handle.request(\n\t\t\t\t\"scanLines\",\n\t\t\t\t{ startLine, ...(endLine === undefined ? {} : { endLine }) },\n\t\t\t\tcontext.abortSignal ? { signal: context.abortSignal } : {},\n\t\t\t);\n\t\t\treturn ok(json as unknown as LineScan);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, this.#path));\n\t\t}\n\t}\n\n\tasync close(_context: Context): Promise<void> {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tawait this.#handle.close();\n\t}\n}\n\nclass RemoteDirReader implements DirReader {\n\treadonly #handle: Handle;\n\t#done = false;\n\t#closed = false;\n\n\tconstructor(handle: Handle) {\n\t\tthis.#handle = handle;\n\t}\n\n\tasync next(\n\t\tmaxEntries: number,\n\t\tcontext: Context,\n\t): Promise<Result<{ entries: FileInfo[]; done: boolean }, FileError>> {\n\t\tconst path = this.#handle.path;\n\t\tconst aborted = abortResult<{ entries: FileInfo[]; done: boolean }>(context.abortSignal, path);\n\t\tif (aborted) return aborted;\n\t\tif (this.#closed) return err(new FileError(\"invalid\", \"Directory reader is closed\", path));\n\t\tif (!Number.isSafeInteger(maxEntries) || maxEntries <= 0) {\n\t\t\treturn err(new FileError(\"invalid\", \"maxEntries must be a positive safe integer\", path));\n\t\t}\n\t\tconst entries: FileInfo[] = [];\n\t\ttry {\n\t\t\tconst paths = await remotePath(this.#handle.env.connection);\n\t\t\t// Like `NodeDirReader`, count only entries that are part of the listing.\n\t\t\twhile (!this.#done && entries.length < maxEntries) {\n\t\t\t\tconst { json } = await this.#handle.request(\"readdir\", { max: maxEntries - entries.length });\n\t\t\t\tconst loopAbort = abortResult<{ entries: FileInfo[]; done: boolean }>(context.abortSignal, path);\n\t\t\t\tif (loopAbort) return loopAbort;\n\t\t\t\tfor (const entry of json.entries as RemoteDirEntry[]) {\n\t\t\t\t\tconst entryPath = paths.resolve(path, entry.name);\n\t\t\t\t\tif (entry.error !== undefined) {\n\t\t\t\t\t\t// Removed between enumeration and lstat: not part of the listing any more.\n\t\t\t\t\t\tif (entry.error.code === \"ENOENT\") continue;\n\t\t\t\t\t\treturn err(toFileError(new RemoteError(entry.error), entryPath));\n\t\t\t\t\t}\n\t\t\t\t\tconst info = toInfo(entryPath, entry.info!, paths);\n\t\t\t\t\tif (info.ok) entries.push(info.value);\n\t\t\t\t}\n\t\t\t\tthis.#done = json.done === true;\n\t\t\t}\n\t\t\treturn ok({ entries, done: this.#done });\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, path));\n\t\t}\n\t}\n\n\tasync close(_context: Context): Promise<void> {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tawait this.#handle.close();\n\t}\n}\n\n/** `NodeTextLineReader`: positional reads of a file opened like `open(path, \"r\")`. */\nclass RemoteTextLineReader implements TextLineReader {\n\treadonly #handle: Handle;\n\treadonly #decoder = new StreamDecoder();\n\t#offset = 0;\n\t#buffered = \"\";\n\t#ended = false;\n\t#closed = false;\n\n\tconstructor(handle: Handle) {\n\t\tthis.#handle = handle;\n\t}\n\n\tasync readLine(context: Context): Promise<Result<TextLine | undefined, FileError>> {\n\t\tconst path = this.#handle.path;\n\t\tconst aborted = abortResult<TextLine | undefined>(context.abortSignal, path);\n\t\tif (aborted) return aborted;\n\t\tif (this.#closed) return err(new FileError(\"invalid\", \"Text line reader is closed\", path));\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tconst newline = this.#buffered.indexOf(\"\\n\");\n\t\t\t\tif (newline !== -1) {\n\t\t\t\t\tconst text = this.#buffered.slice(0, newline);\n\t\t\t\t\tthis.#buffered = this.#buffered.slice(newline + 1);\n\t\t\t\t\treturn ok({ text, terminated: true });\n\t\t\t\t}\n\t\t\t\tif (this.#ended) {\n\t\t\t\t\tif (this.#buffered.length === 0) return ok(undefined);\n\t\t\t\t\tconst text = this.#buffered;\n\t\t\t\t\tthis.#buffered = \"\";\n\t\t\t\t\treturn ok({ text, terminated: false });\n\t\t\t\t}\n\t\t\t\tconst bytes = await this.#handle.pread(this.#offset, LINE_CHUNK);\n\t\t\t\tconst afterReadAbort = abortResult<TextLine | undefined>(context.abortSignal, path);\n\t\t\t\tif (afterReadAbort) return afterReadAbort;\n\t\t\t\tthis.#offset += bytes.length;\n\t\t\t\tif (bytes.length === 0) {\n\t\t\t\t\tthis.#buffered += this.#decoder.decode();\n\t\t\t\t\tthis.#ended = true;\n\t\t\t\t} else {\n\t\t\t\t\tthis.#buffered += this.#decoder.decode(bytes);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, path));\n\t\t}\n\t}\n\n\tasync close(_context: Context): Promise<void> {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tthis.#buffered = \"\";\n\t\tawait this.#handle.close();\n\t}\n}\n\n/**\n * An `ExecutionEnv` on another machine, reached through a pi-env daemon. Results match `NodeExecutionEnv` running on\n * that machine: the daemon performs the system calls, and this class applies Node's path, error, and result rules.\n */\nexport class RemoteExecutionEnv implements ExecutionEnv {\n\treadonly id: string;\n\tcwd: string;\n\treadonly connection: Connection;\n\treadonly #shellPath: string | undefined;\n\treadonly #shellEnv: Record<string, string> | undefined;\n\treadonly #watchOptions: RemoteWatchOptions;\n\t/** Running commands this environment started, for `cleanup()`. */\n\treadonly #running = new Map<number, number>();\n\n\tconstructor(options: RemoteExecutionEnvOptions) {\n\t\tthis.id = options.id;\n\t\tthis.cwd = options.cwd;\n\t\tthis.connection = options.connection;\n\t\tthis.#shellPath = options.shellPath;\n\t\tthis.#shellEnv = options.shellEnv;\n\t\tthis.#watchOptions = options.watch ?? {};\n\t}\n\n\t/** Node's `resolvePath` on the remote system, with its home directory and working directories. */\n\tasync #resolve(path: string): Promise<string> {\n\t\tconst info = await this.connection.info();\n\t\tconst windows = nodePlatform(info).platform === \"win32\";\n\t\tconst paths = windows ? win32 : posix;\n\t\tlet normalized = path;\n\t\tif (normalized === \"~\") {\n\t\t\tnormalized = info.home;\n\t\t} else if (normalized.startsWith(\"~/\") || (windows && normalized.startsWith(\"~\\\\\"))) {\n\t\t\tnormalized = paths.join(info.home, normalized.slice(2));\n\t\t} else if (normalized.startsWith(\"file://\")) {\n\t\t\ttry {\n\t\t\t\tnormalized = fileURLToPath(normalized, { windows });\n\t\t\t} catch {\n\t\t\t\t// Keep malformed URLs as ordinary paths, as Node does.\n\t\t\t}\n\t\t}\n\t\tif (paths.isAbsolute(normalized)) return paths.resolve(normalized);\n\t\tif (windows) {\n\t\t\t// A drive-relative path on another drive: Node on Windows resolves it against that drive's working directory\n\t\t\t// (`=D:`), else its own working directory if on that drive, else the drive's root.\n\t\t\tconst drive = /^([a-zA-Z]:)(?![\\\\/])/.exec(normalized)?.[1];\n\t\t\tif (drive !== undefined && drive.toLowerCase() !== this.cwd.slice(0, 2).toLowerCase()) {\n\t\t\t\tlet base = info.driveCwds[drive.toUpperCase()] ?? info.cwd;\n\t\t\t\tif (base.slice(0, 2).toLowerCase() !== drive.toLowerCase() && base[2] === \"\\\\\") base = `${drive}\\\\`;\n\t\t\t\treturn win32.resolve(base, normalized);\n\t\t\t}\n\t\t}\n\t\treturn paths.resolve(this.cwd, normalized);\n\t}\n\n\tasync #fileOp<T>(\n\t\tpath: string,\n\t\tcontext: Context,\n\t\trun: (resolved: string) => Promise<T>,\n\t\tcheck: \"before\" | \"both\" = \"before\",\n\t): Promise<Result<T, FileError>> {\n\t\tlet resolved: string;\n\t\ttry {\n\t\t\tresolved = await this.#resolve(path);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, path));\n\t\t}\n\t\tconst aborted = abortResult<T>(context.abortSignal, resolved);\n\t\tif (aborted) return aborted;\n\t\ttry {\n\t\t\tconst value = await run(resolved);\n\t\t\tif (check === \"both\") {\n\t\t\t\tconst after = abortResult<T>(context.abortSignal, resolved);\n\t\t\t\tif (after) return after;\n\t\t\t}\n\t\t\treturn ok(value);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, resolved));\n\t\t}\n\t}\n\n\tasync #open(resolved: string, json: Json): Promise<{ handle: Handle; json: Json }> {\n\t\tconst reply = await this.connection.request(\"open\", { path: resolved, ...json });\n\t\treturn { handle: new Handle(this, reply.json.handle as number, reply.session, resolved), json: reply.json };\n\t}\n\n\tasync absolutePath(path: string, _context: Context): Promise<Result<string, FileError>> {\n\t\ttry {\n\t\t\treturn ok(await this.#resolve(path));\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, path));\n\t\t}\n\t}\n\n\tasync joinPath(parts: string[], _context: Context): Promise<Result<string, FileError>> {\n\t\ttry {\n\t\t\treturn ok((await remotePath(this.connection)).join(...parts));\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error));\n\t\t}\n\t}\n\n\t/** Node's `readFile`, with or without UTF-8 decoding, over a file opened like `open(path, \"r\")`. */\n\tasync #readFile(path: string, encoding: boolean, context: Context): Promise<Result<Uint8Array | string, FileError>> {\n\t\tconst signal = context.abortSignal;\n\t\treturn this.#fileOp(path, context, async (resolved) => {\n\t\t\tconst { handle, json } = await this.#open(resolved, { mode: \"read\" });\n\t\t\tconst aborted = () => signal?.aborted === true;\n\t\t\tconst abort = () => new FileError(\"aborted\", \"The operation was aborted\", resolved);\n\t\t\ttry {\n\t\t\t\tif (json.statError !== undefined) throw new RemoteError(json.statError as Json);\n\t\t\t\tif (aborted()) throw abort();\n\t\t\t\tconst stat = json.stat as RemoteFileInfo;\n\t\t\t\tconst size = stat.kind === \"file\" ? stat.size : 0;\n\t\t\t\tif (size > READ_FILE_MAX) {\n\t\t\t\t\tthrow new FileError(\"unknown\", `File size (${size}) is greater than 2 GiB`, resolved);\n\t\t\t\t}\n\t\t\t\tif (size === 0) {\n\t\t\t\t\t// Unknown size: sequential reads until the end, as for FIFOs and devices.\n\t\t\t\t\tconst decoder = new StringDecoder(\"utf8\");\n\t\t\t\t\tconst chunks: Uint8Array[] = [];\n\t\t\t\t\tlet total = 0;\n\t\t\t\t\tlet text = \"\";\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tif (aborted()) throw abort();\n\t\t\t\t\t\tconst bytes = await handle.pread(undefined, READ_FILE_UNKNOWN_CHUNK);\n\t\t\t\t\t\tif (bytes.length === 0) break;\n\t\t\t\t\t\ttotal += bytes.length;\n\t\t\t\t\t\tchunks.push(bytes);\n\t\t\t\t\t\tif (encoding) text += decoder.write(bytes);\n\t\t\t\t\t}\n\t\t\t\t\tif (!encoding) return Buffer.concat(chunks, total);\n\t\t\t\t\treturn total === 0 ? \"\" : text + decoder.end();\n\t\t\t\t}\n\t\t\t\tif (!encoding) {\n\t\t\t\t\t// A single read of the whole size, or reads of 512 KiB until the size or the end of the file.\n\t\t\t\t\tif (size <= READ_FILE_CHUNK) return Buffer.from(await handle.pread(0, size));\n\t\t\t\t\tconst read = await readRange(\n\t\t\t\t\t\t(at, length) => handle.pread(at, length),\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tREAD_FILE_CHUNK,\n\t\t\t\t\t\taborted,\n\t\t\t\t\t);\n\t\t\t\t\tif (read === undefined) throw abort();\n\t\t\t\t\treturn Buffer.concat(read.chunks, read.total);\n\t\t\t\t}\n\t\t\t\t// Decoding: reads of min(size, 512 KiB) until the size, a short read, or the end of the file.\n\t\t\t\tconst length = Math.min(size, READ_FILE_CHUNK);\n\t\t\t\tconst decoder = new StringDecoder(\"utf8\");\n\t\t\t\tlet text = \"\";\n\t\t\t\tlet total = 0;\n\t\t\t\tlet first = true;\n\t\t\t\tconst inFlight: Promise<Uint8Array>[] = [];\n\t\t\t\tlet next = 0;\n\t\t\t\twhile (true) {\n\t\t\t\t\twhile (inFlight.length < READ_DEPTH) {\n\t\t\t\t\t\tconst bytes = handle.pread(next, length);\n\t\t\t\t\t\tbytes.catch(() => {});\n\t\t\t\t\t\tinFlight.push(bytes);\n\t\t\t\t\t\tnext += length;\n\t\t\t\t\t}\n\t\t\t\t\tconst bytes = await inFlight.shift()!;\n\t\t\t\t\tif (aborted()) throw abort();\n\t\t\t\t\ttotal += bytes.length;\n\t\t\t\t\tif (bytes.length === 0 || total === size || bytes.length !== length) {\n\t\t\t\t\t\treturn first ? Buffer.from(bytes).toString(\"utf8\") : text + decoder.end(Buffer.from(bytes));\n\t\t\t\t\t}\n\t\t\t\t\ttext += decoder.write(Buffer.from(bytes));\n\t\t\t\t\tfirst = false;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait handle.close();\n\t\t\t}\n\t\t});\n\t}\n\n\tasync readTextFile(path: string, context: Context): Promise<Result<string, FileError>> {\n\t\treturn (await this.#readFile(path, true, context)) as Result<string, FileError>;\n\t}\n\n\tasync readBinaryFile(path: string, context: Context): Promise<Result<Uint8Array, FileError>> {\n\t\treturn (await this.#readFile(path, false, context)) as Result<Uint8Array, FileError>;\n\t}\n\n\tasync openBinaryReader(\n\t\tpath: string,\n\t\toptions: { noFollow?: boolean } | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<BinaryReader, FileError>> {\n\t\tconst opened = await this.#fileOp(path, context, async (resolved) => {\n\t\t\treturn (await this.#open(resolved, { noFollow: options?.noFollow === true })).handle;\n\t\t});\n\t\tif (!opened.ok) return opened;\n\t\tconst aborted = abortResult<BinaryReader>(context.abortSignal, opened.value.path);\n\t\tif (aborted) {\n\t\t\tawait opened.value.close();\n\t\t\treturn aborted;\n\t\t}\n\t\treturn ok(new RemoteBinaryReader(opened.value));\n\t}\n\n\tasync openTextLineReader(path: string, context: Context): Promise<Result<TextLineReader, FileError>> {\n\t\tconst opened = await this.#fileOp(path, context, async (resolved) => {\n\t\t\treturn (await this.#open(resolved, { mode: \"read\" })).handle;\n\t\t});\n\t\tif (!opened.ok) return opened;\n\t\tconst aborted = abortResult<TextLineReader>(context.abortSignal, opened.value.path);\n\t\tif (aborted) {\n\t\t\tawait opened.value.close();\n\t\t\treturn aborted;\n\t\t}\n\t\treturn ok(new RemoteTextLineReader(opened.value));\n\t}\n\n\tasync readTextLines(\n\t\tpath: string,\n\t\toptions: { maxLines?: number } | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<string[], FileError>> {\n\t\tif (options?.maxLines !== undefined && options.maxLines <= 0) return ok([]);\n\t\tconst opened = await this.openTextLineReader(path, context);\n\t\tif (!opened.ok) return opened;\n\t\tconst lines: string[] = [];\n\t\ttry {\n\t\t\twhile (options?.maxLines === undefined || lines.length < options.maxLines) {\n\t\t\t\tconst line = await opened.value.readLine(context);\n\t\t\t\tif (!line.ok) return line;\n\t\t\t\tif (line.value === undefined) break;\n\t\t\t\tlines.push(line.value.text);\n\t\t\t}\n\t\t\treturn ok(lines);\n\t\t} finally {\n\t\t\tawait opened.value.close(context);\n\t\t}\n\t}\n\n\t/**\n\t * Node's `writeFile` (abort checked before each 512 KiB write) or `appendFile` (no checks, one after): the first\n\t * request creates parents, opens, and writes the first chunk; later chunks go to the same open file.\n\t */\n\tasync #write(path: string, content: string | Uint8Array, append: boolean, context: Context) {\n\t\tconst bytes = typeof content === \"string\" ? Buffer.from(content, \"utf8\") : content;\n\t\tconst signal = append ? undefined : context.abortSignal;\n\t\treturn this.#fileOp(\n\t\t\tpath,\n\t\t\tcontext,\n\t\t\tasync (resolved) => {\n\t\t\t\tconst first = bytes.subarray(0, WRITE_CHUNK);\n\t\t\t\tconst keep = bytes.length > WRITE_CHUNK;\n\t\t\t\tconst reply = await this.connection.request(\"write\", { path: resolved, append, keep }, { payload: first });\n\t\t\t\tif (!keep) return;\n\t\t\t\tconst handle = new Handle(this, reply.json.handle as number, reply.session, resolved);\n\t\t\t\tconst inFlight: Promise<unknown>[] = [];\n\t\t\t\ttry {\n\t\t\t\t\tfor (let offset = WRITE_CHUNK; offset < bytes.length; offset += WRITE_CHUNK) {\n\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t// A chunk that failed before this check fails the write, as it would have in sequence.\n\t\t\t\t\t\t\tconst failed = (await Promise.allSettled(inFlight)).find((result) => result.status === \"rejected\");\n\t\t\t\t\t\t\tif (failed !== undefined) throw failed.reason;\n\t\t\t\t\t\t\tthrow new FileError(\"aborted\", \"The operation was aborted\", resolved);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst written = handle.request(\n\t\t\t\t\t\t\t\"writeChunk\",\n\t\t\t\t\t\t\t{},\n\t\t\t\t\t\t\t{ payload: bytes.subarray(offset, offset + WRITE_CHUNK) },\n\t\t\t\t\t\t);\n\t\t\t\t\t\twritten.catch(() => {});\n\t\t\t\t\t\tinFlight.push(written);\n\t\t\t\t\t\tif (inFlight.length >= WRITE_DEPTH) await inFlight.shift();\n\t\t\t\t\t}\n\t\t\t\t\t// The first failure; later chunks are refused by the daemon, so the file has no gaps.\n\t\t\t\t\tfor (const written of inFlight) await written;\n\t\t\t\t} finally {\n\t\t\t\t\tawait Promise.allSettled(inFlight);\n\t\t\t\t\tawait handle.close();\n\t\t\t\t}\n\t\t\t},\n\t\t\tappend ? \"both\" : \"before\",\n\t\t);\n\t}\n\n\twriteFile(path: string, content: string | Uint8Array, context: Context): Promise<Result<void, FileError>> {\n\t\treturn this.#write(path, content, false, context);\n\t}\n\n\tappendFile(path: string, content: string | Uint8Array, context: Context): Promise<Result<void, FileError>> {\n\t\treturn this.#write(path, content, true, context);\n\t}\n\n\tasync truncateFile(path: string, size: number, context: Context): Promise<Result<void, FileError>> {\n\t\treturn this.#fileOp(\n\t\t\tpath,\n\t\t\tcontext,\n\t\t\tasync (resolved) => {\n\t\t\t\tif (!Number.isSafeInteger(size) || size < 0) {\n\t\t\t\t\tthrow new FileError(\"invalid\", \"File size must be a non-negative safe integer\", resolved);\n\t\t\t\t}\n\t\t\t\tawait this.connection.request(\"truncate\", { path: resolved, size });\n\t\t\t},\n\t\t\t\"both\",\n\t\t);\n\t}\n\n\tflushFile(path: string, context: Context): Promise<Result<void, FileError>> {\n\t\treturn this.#fileOp(\n\t\t\tpath,\n\t\t\tcontext,\n\t\t\tasync (resolved) => {\n\t\t\t\tawait this.connection.request(\"fsync\", { path: resolved });\n\t\t\t},\n\t\t\t\"both\",\n\t\t);\n\t}\n\n\tasync renameFile(sourcePath: string, destinationPath: string, context: Context): Promise<Result<void, FileError>> {\n\t\tlet source: string;\n\t\tlet destination: string;\n\t\ttry {\n\t\t\tsource = await this.#resolve(sourcePath);\n\t\t\tdestination = await this.#resolve(destinationPath);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, sourcePath));\n\t\t}\n\t\tconst aborted = abortResult<void>(context.abortSignal, destination);\n\t\tif (aborted) return aborted;\n\t\ttry {\n\t\t\tawait this.connection.request(\"rename\", { path: source, to: destination });\n\t\t\treturn ok(undefined);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, source));\n\t\t}\n\t}\n\n\tasync fileInfo(path: string, context: Context): Promise<Result<FileInfo, FileError>> {\n\t\tconst result = await this.#fileOp(path, context, async (resolved) => {\n\t\t\tconst { json } = await this.connection.request(\"lstat\", { path: resolved });\n\t\t\treturn toInfo(resolved, json as unknown as RemoteFileInfo, await remotePath(this.connection));\n\t\t});\n\t\treturn result.ok ? result.value : result;\n\t}\n\n\tlistDir(path: string, context: Context): Promise<Result<FileInfo[], FileError>> {\n\t\treturn this.#fileOp(path, context, async (resolved) => {\n\t\t\tconst { handle } = await this.#openDir(resolved);\n\t\t\tconst entries: RemoteDirEntry[] = [];\n\t\t\ttry {\n\t\t\t\tfor (let done = false; !done; ) {\n\t\t\t\t\tconst { json } = await handle.request(\"readdir\", { max: 1000 });\n\t\t\t\t\tentries.push(...(json.entries as RemoteDirEntry[]));\n\t\t\t\t\tdone = json.done === true;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait handle.close();\n\t\t\t}\n\t\t\t// Node's `readdir` fails on any entry it cannot lstat. libuv sorts names by their bytes on POSIX; on Windows it\n\t\t\t// keeps the file system's order, which the daemon reports.\n\t\t\tconst paths = await remotePath(this.connection);\n\t\t\tif (paths === posix) {\n\t\t\t\tconst key = (entry: RemoteDirEntry) => Buffer.from(entry.raw ?? Buffer.from(entry.name, \"utf8\"));\n\t\t\t\tentries.sort((a, b) => Buffer.compare(key(a), key(b)));\n\t\t\t}\n\t\t\tconst infos: FileInfo[] = [];\n\t\t\tfor (const entry of entries) {\n\t\t\t\tif (context.abortSignal?.aborted) throw new FileError(\"aborted\", \"aborted\", resolved);\n\t\t\t\tconst entryPath = paths.resolve(resolved, entry.name);\n\t\t\t\tif (entry.error !== undefined) throw toFileError(new RemoteError(entry.error), entryPath);\n\t\t\t\tconst info = toInfo(entryPath, entry.info!, paths);\n\t\t\t\tif (info.ok) infos.push(info.value);\n\t\t\t}\n\t\t\treturn infos;\n\t\t});\n\t}\n\n\t/** Through the daemon; `not_supported` with a daemon released before `listFiles`. */\n\tasync listFiles(\n\t\tpath: string,\n\t\toptions: ListFilesOptions | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<FileListing, FileError>> {\n\t\tlet resolved: string;\n\t\ttry {\n\t\t\tresolved = await this.#resolve(path);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, path));\n\t\t}\n\t\treturn listFilesOver(this.connection, resolved, options, context);\n\t}\n\n\tasync #openDir(resolved: string): Promise<{ handle: Handle }> {\n\t\tconst reply = await this.connection.request(\"opendir\", { path: resolved });\n\t\treturn { handle: new Handle(this, reply.json.handle as number, reply.session, resolved) };\n\t}\n\n\tasync openDirReader(path: string, context: Context): Promise<Result<DirReader, FileError>> {\n\t\tconst opened = await this.#fileOp(path, context, async (resolved) => (await this.#openDir(resolved)).handle);\n\t\tif (!opened.ok) return opened;\n\t\tconst aborted = abortResult<DirReader>(context.abortSignal, opened.value.path);\n\t\tif (aborted) {\n\t\t\tawait opened.value.close();\n\t\t\treturn aborted;\n\t\t}\n\t\treturn ok(new RemoteDirReader(opened.value));\n\t}\n\n\tcanonicalPath(path: string, context: Context): Promise<Result<string, FileError>> {\n\t\treturn this.#fileOp(path, context, async (resolved) => {\n\t\t\tconst { json } = await this.connection.request(\"realpath\", { path: resolved });\n\t\t\treturn json.path as string;\n\t\t});\n\t}\n\n\tasync exists(path: string, context: Context): Promise<Result<boolean, FileError>> {\n\t\tconst result = await this.fileInfo(path, context);\n\t\tif (result.ok) return ok(true);\n\t\tif (result.error.code === \"not_found\") return ok(false);\n\t\treturn err(result.error);\n\t}\n\n\tcreateDir(\n\t\tpath: string,\n\t\toptions: { recursive?: boolean } | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<void, FileError>> {\n\t\treturn this.#fileOp(path, context, async (resolved) => {\n\t\t\tawait this.connection.request(\"mkdir\", { path: resolved, recursive: options?.recursive ?? true });\n\t\t});\n\t}\n\n\tremove(\n\t\tpath: string,\n\t\toptions: { recursive?: boolean; force?: boolean } | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<void, FileError>> {\n\t\treturn this.#fileOp(path, context, async (resolved) => {\n\t\t\tawait this.connection.request(\"rm\", {\n\t\t\t\tpath: resolved,\n\t\t\t\trecursive: options?.recursive ?? false,\n\t\t\t\tforce: options?.force ?? false,\n\t\t\t});\n\t\t});\n\t}\n\n\tasync createTempDir(prefix: string | undefined, context: Context): Promise<Result<string, FileError>> {\n\t\tconst aborted = abortResult<string>(context.abortSignal);\n\t\tif (aborted) return aborted;\n\t\ttry {\n\t\t\tconst { tmpdir } = await this.connection.info();\n\t\t\tconst paths = await remotePath(this.connection);\n\t\t\tconst { json } = await this.connection.request(\"mkdtemp\", { path: paths.join(tmpdir, prefix ?? \"tmp-\") });\n\t\t\treturn ok(json.path as string);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error));\n\t\t}\n\t}\n\n\tasync createTempFile(\n\t\toptions: { prefix?: string; suffix?: string } | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<string, FileError>> {\n\t\tconst dir = await this.createTempDir(\"tmp-\", context);\n\t\tif (!dir.ok) return dir;\n\t\tlet filePath = \"\";\n\t\ttry {\n\t\t\tconst paths = await remotePath(this.connection);\n\t\t\tfilePath = paths.join(dir.value, `${options?.prefix ?? \"\"}${randomUUID()}${options?.suffix ?? \"\"}`);\n\t\t\t// Node's `writeFile(filePath, \"\")`, which does not create parents.\n\t\t\tawait this.connection.request(\n\t\t\t\t\"write\",\n\t\t\t\t{ path: filePath, append: false, parents: false },\n\t\t\t\t{ payload: new Uint8Array(0) },\n\t\t\t);\n\t\t\treturn ok(filePath);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, filePath));\n\t\t}\n\t}\n\n\tasync watch(\n\t\ttargets: readonly WatchTarget[],\n\t\tonChange: (change: WatchChange) => void,\n\t\tcontext: Context,\n\t): Promise<Result<FileWatcher, FileError>> {\n\t\tconst aborted = abortResult<FileWatcher>(context.abortSignal);\n\t\tif (aborted) return aborted;\n\t\ttry {\n\t\t\tconst resolved = await Promise.all(\n\t\t\t\ttargets.map(async (target) => ({ ...target, path: await this.#resolve(target.path) })),\n\t\t\t);\n\t\t\tconst afterResolve = abortResult<FileWatcher>(context.abortSignal);\n\t\t\tif (afterResolve) return afterResolve;\n\t\t\tconst watcher = await RemoteWatcher.open(this.connection, resolved, onChange, this.#watchOptions);\n\t\t\tconst afterOpen = abortResult<FileWatcher>(context.abortSignal);\n\t\t\tif (afterOpen) {\n\t\t\t\tawait watcher.close(context);\n\t\t\t\treturn afterOpen;\n\t\t\t}\n\t\t\treturn ok(watcher);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error));\n\t\t}\n\t}\n\n\tasync exec(\n\t\tcommand: string | readonly string[],\n\t\toptions: ShellExecOptions | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<ShellExecResult, ExecutionError>> {\n\t\tconst signal = context.abortSignal;\n\t\tif (signal?.aborted) return err(new ExecutionError(\"aborted\", \"aborted\"));\n\t\tconst timeout = options?.timeout;\n\t\tif (timeout !== undefined) {\n\t\t\tif (!Number.isFinite(timeout) || timeout <= 0) {\n\t\t\t\treturn err(new ExecutionError(\"timeout\", \"Invalid timeout: must be a finite number of seconds\"));\n\t\t\t}\n\t\t\tif (timeout * 1000 > MAX_TIMEOUT_MS) {\n\t\t\t\treturn err(new ExecutionError(\"timeout\", `Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`));\n\t\t\t}\n\t\t}\n\t\tconst inheritEnv = options?.inheritEnv ?? true;\n\t\tlet cwd: string;\n\t\ttry {\n\t\t\tcwd = options?.cwd ? await this.#resolve(options.cwd) : this.cwd;\n\t\t} catch (error) {\n\t\t\treturn err(new ExecutionError(\"unknown\", error instanceof Error ? error.message : String(error)));\n\t\t}\n\t\tif (signal?.aborted) return err(new ExecutionError(\"aborted\", \"aborted\"));\n\t\tconst env: Record<string, string> = {};\n\t\tfor (const [key, value] of Object.entries(\n\t\t\tinheritEnv ? { ...this.#shellEnv, ...options?.env } : { ...options?.env },\n\t\t)) {\n\t\t\tif (value !== undefined) env[key.toWellFormed()] = value;\n\t\t}\n\t\tlet callbackError: ExecutionError | undefined;\n\t\tlet settled = false;\n\t\tlet running: number | undefined;\n\t\tconst controller = new AbortController();\n\t\tconst onAbort = () => controller.abort();\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\ttry {\n\t\t\tconst { json } = await this.connection.request(\n\t\t\t\t\"exec\",\n\t\t\t\t{\n\t\t\t\t\t...(typeof command === \"string\" ? { command } : { argv: [...command] }),\n\t\t\t\t\tcwd,\n\t\t\t\t\tenv,\n\t\t\t\t\tinheritEnv,\n\t\t\t\t\t...(this.#shellPath === undefined ? {} : { shellPath: this.#shellPath }),\n\t\t\t\t\t...(timeout === undefined ? {} : { timeoutMs: timeout * 1000 }),\n\t\t\t\t\t...(options?.spill === undefined ? {} : { spill: options.spill }),\n\t\t\t\t\t...(options?.window === undefined ? {} : { window: options.window }),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\tonStart: (requestId, session) => {\n\t\t\t\t\t\trunning = requestId;\n\t\t\t\t\t\tthis.#running.set(requestId, session);\n\t\t\t\t\t},\n\t\t\t\t\tonEvent: (event, payload) => {\n\t\t\t\t\t\tif (settled || callbackError !== undefined || event.kind !== \"output\") return;\n\t\t\t\t\t\tconst text = Buffer.from(payload.buffer, payload.byteOffset, payload.length).toString(\"utf8\");\n\t\t\t\t\t\tif (text === \"\" || options?.onOutput === undefined) return;\n\t\t\t\t\t\tconst info: ShellOutputInfo = { stream: event.stream === \"stderr\" ? \"stderr\" : \"stdout\" };\n\t\t\t\t\t\tif (event.skipped !== undefined) info.skipped = event.skipped as ShellOutputSkip;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\toptions.onOutput(text, context, info);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconst cause = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\t\t\tcallbackError = new ExecutionError(\"callback_error\", cause.message, cause);\n\t\t\t\t\t\t\tcontroller.abort();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (callbackError) return err(callbackError);\n\t\t\treturn ok({\n\t\t\t\texitCode: json.exitCode as number,\n\t\t\t\t...(typeof json.spillPath === \"string\" ? { spillPath: json.spillPath } : {}),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (callbackError) return err(callbackError);\n\t\t\tif (!(error instanceof RemoteError)) {\n\t\t\t\treturn err(new ExecutionError(\"unknown\", error instanceof Error ? error.message : String(error)));\n\t\t\t}\n\t\t\tconst failure =\n\t\t\t\terror.code === \"timeout\"\n\t\t\t\t\t? new ExecutionError(\"timeout\", `timeout:${timeout}`)\n\t\t\t\t\t: error.code === \"aborted\"\n\t\t\t\t\t\t? new ExecutionError(\"aborted\", \"aborted\")\n\t\t\t\t\t\t: error.code === \"shell_unavailable\" || error.code === \"spawn_error\"\n\t\t\t\t\t\t\t? new ExecutionError(error.code, error.message)\n\t\t\t\t\t\t\t: new ExecutionError(\"unknown\", error.message);\n\t\t\tif (typeof error.fields.spillPath === \"string\") failure.spillPath = error.fields.spillPath;\n\t\t\treturn err(failure);\n\t\t} finally {\n\t\t\tsettled = true;\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tif (running !== undefined) this.#running.delete(running);\n\t\t}\n\t}\n\n\tasync cleanup(_context: Context): Promise<void> {\n\t\t// Kill without aborting, so the commands settle with their killed status, as `NodeExecutionEnv` does.\n\t\tfor (const [id, session] of this.#running) this.connection.kill(id, session);\n\t\tthis.#running.clear();\n\t}\n}\n\nexport type { RemoteInfo };\n"]}
|
|
1
|
+
{"version":3,"file":"remote-env.js","sourceRoot":"","sources":["../src/remote-env.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { type PlatformPath, posix, win32 } from \"node:path\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Context } from \"@earendil-works/chord\";\nimport {\n\ttype BinaryReader,\n\ttype DirReader,\n\ttype ExecutionEnv,\n\tExecutionError,\n\terr,\n\ttype FileChange,\n\tFileError,\n\ttype FileInfo,\n\ttype FileKind,\n\ttype FileListing,\n\ttype FileWatcher,\n\ttype LineScan,\n\ttype ListFilesOptions,\n\tok,\n\ttype Result,\n\ttype ShellExecOptions,\n\ttype ShellExecResult,\n\ttype ShellOutputInfo,\n\ttype ShellOutputSkip,\n\tStreamDecoder,\n\ttype TextLine,\n\ttype TextLineReader,\n\ttype WatchTarget,\n} from \"@earendil-works/pi-durable/env\";\nimport { type Connection, type Json, nodePlatform, RemoteError, type RemoteInfo } from \"./connection.ts\";\nimport { abortResult, toFileError } from \"./errors.ts\";\nimport { listFilesOver } from \"./list-files.ts\";\nimport { RemoteWatcher, type RemoteWatchOptions } from \"./watch.ts\";\n\nconst MAX_TIMEOUT_MS = 2_147_483_647;\nconst MAX_TIMEOUT_SECONDS = MAX_TIMEOUT_MS / 1000;\n/** Bytes per `pread` request of a binary reader; several are in flight at once. */\nconst READ_CHUNK = 256 * 1024;\nconst READ_DEPTH = 8;\n/** Node's `writeFile` writes at most this much per call and checks for an abort before each. */\nconst WRITE_CHUNK = 512 * 1024;\nconst WRITE_DEPTH = 8;\n/** Node's `readFile`: chunk of known-size reads, chunk of unknown-size reads, and the largest file it reads. */\nconst READ_FILE_CHUNK = 512 * 1024;\nconst READ_FILE_UNKNOWN_CHUNK = 64 * 1024;\nconst READ_FILE_MAX = 2 ** 31 - 1;\n/** `NodeTextLineReader`'s read size. */\nconst LINE_CHUNK = 64 * 1024;\n\nexport interface RemoteExecutionEnvOptions {\n\tconnection: Connection;\n\t/** The file namespace: equal ids see the same files (`FileSystem.id`), e.g. `pi-env:<env name>`. */\n\tid: string;\n\tcwd: string;\n\tshellPath?: string;\n\t/** Added to the remote environment of every command that inherits it, like `NodeExecutionEnv`'s `shellEnv`. */\n\tshellEnv?: Record<string, string>;\n\t/** How the daemon watches, like `NodeExecutionEnv`'s `watch` option. */\n\twatch?: RemoteWatchOptions;\n}\n\n/** An info record from the daemon. */\ntype RemoteFileInfo = { name: string; kind: FileKind | \"other\"; size: number; mtimeSec: number; mtimeNsec: number };\ntype RemoteDirEntry = { name: string; raw?: number[]; info?: RemoteFileInfo; error?: Json };\n\n/** Node's path rules of the remote system. */\nexport async function remotePath(connection: Connection): Promise<PlatformPath> {\n\treturn nodePlatform(await connection.info()).platform === \"win32\" ? win32 : posix;\n}\n\nfunction toInfo(path: string, remote: RemoteFileInfo, paths: PlatformPath): Result<FileInfo, FileError> {\n\tif (remote.kind === \"other\") return err(new FileError(\"invalid\", \"Unsupported file type\", path));\n\treturn ok({\n\t\tname: paths.basename(path),\n\t\tpath,\n\t\tkind: remote.kind,\n\t\tsize: remote.size,\n\t\tmtimeMs: remote.mtimeSec * 1000 + remote.mtimeNsec / 1e6,\n\t});\n}\n\nfunction concat(chunks: readonly Uint8Array[], total: number): Uint8Array {\n\tif (chunks.length === 1) return chunks[0]!;\n\tconst bytes = new Uint8Array(total);\n\tlet position = 0;\n\tfor (const chunk of chunks) {\n\t\tbytes.set(chunk, position);\n\t\tposition += chunk.length;\n\t}\n\treturn bytes;\n}\n\n/**\n * Read `length` bytes from `offset` as consecutive reads of at most `chunk` bytes, several in flight. Ends early at\n * the end of the file. A short read continues from where it ended, as sequential reads would. `aborted` is checked\n * after each read; `undefined` means aborted.\n */\nasync function readRange(\n\tread: (offset: number, length: number) => Promise<Uint8Array>,\n\toffset: number,\n\tlength: number,\n\tchunk: number,\n\taborted: () => boolean,\n): Promise<{ chunks: Uint8Array[]; total: number } | undefined> {\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\tlet next = offset;\n\tconst inFlight: { length: number; bytes: Promise<Uint8Array> }[] = [];\n\twhile (total < length) {\n\t\twhile (inFlight.length < READ_DEPTH && next < offset + length) {\n\t\t\tconst size = Math.min(offset + length - next, chunk);\n\t\t\tconst bytes = read(next, size);\n\t\t\tbytes.catch(() => {});\n\t\t\tinFlight.push({ length: size, bytes });\n\t\t\tnext += size;\n\t\t}\n\t\tconst head = inFlight.shift()!;\n\t\tconst bytes = await head.bytes;\n\t\tif (aborted()) return undefined;\n\t\tif (bytes.length === 0) break;\n\t\tchunks.push(bytes);\n\t\ttotal += bytes.length;\n\t\tif (bytes.length < head.length) {\n\t\t\t// Reads already in flight assumed a full read; continue right after this one.\n\t\t\tinFlight.length = 0;\n\t\t\tnext = offset + total;\n\t\t}\n\t}\n\treturn { chunks, total };\n}\n\n/** A daemon handle: valid only in the session that opened it. */\nclass Handle {\n\treadonly env: RemoteExecutionEnv;\n\treadonly id: number;\n\treadonly session: number;\n\treadonly path: string;\n\n\tconstructor(env: RemoteExecutionEnv, id: number, session: number, path: string) {\n\t\tthis.env = env;\n\t\tthis.id = id;\n\t\tthis.session = session;\n\t\tthis.path = path;\n\t}\n\n\trequest(op: string, json: Json = {}, options: { signal?: AbortSignal; payload?: Uint8Array } = {}) {\n\t\treturn this.env.connection.request(op, { ...json, handle: this.id }, { ...options, session: this.session });\n\t}\n\n\tasync pread(offset: number | undefined, length: number): Promise<Uint8Array> {\n\t\treturn (await this.request(\"pread\", { ...(offset === undefined ? {} : { offset }), length })).payload;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.request(\"close\").catch(() => undefined);\n\t}\n}\n\nclass RemoteBinaryReader implements BinaryReader {\n\treadonly #handle: Handle;\n\t#closed = false;\n\n\tconstructor(handle: Handle) {\n\t\tthis.#handle = handle;\n\t}\n\n\tget #path(): string {\n\t\treturn this.#handle.path;\n\t}\n\n\t#closedResult<T>(): Result<T, FileError> | undefined {\n\t\treturn this.#closed ? err(new FileError(\"invalid\", \"Binary reader is closed\", this.#path)) : undefined;\n\t}\n\n\tasync info(context: Context): Promise<Result<FileInfo, FileError>> {\n\t\tconst early = abortResult<FileInfo>(context.abortSignal, this.#path) ?? this.#closedResult<FileInfo>();\n\t\tif (early) return early;\n\t\ttry {\n\t\t\tconst { json } = await this.#handle.request(\"fstat\");\n\t\t\treturn toInfo(this.#path, json as unknown as RemoteFileInfo, await remotePath(this.#handle.env.connection));\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, this.#path));\n\t\t}\n\t}\n\n\tasync read(offset: number, length: number, context: Context): Promise<Result<Uint8Array, FileError>> {\n\t\tconst early = abortResult<Uint8Array>(context.abortSignal, this.#path) ?? this.#closedResult<Uint8Array>();\n\t\tif (early) return early;\n\t\tif (!Number.isSafeInteger(offset) || offset < 0 || !Number.isSafeInteger(length) || length < 0) {\n\t\t\treturn err(new FileError(\"invalid\", \"Offset and length must be non-negative safe integers\", this.#path));\n\t\t}\n\t\ttry {\n\t\t\tconst read = await readRange(\n\t\t\t\t(at, size) => this.#handle.pread(at, size),\n\t\t\t\toffset,\n\t\t\t\tlength,\n\t\t\t\tREAD_CHUNK,\n\t\t\t\t() => context.abortSignal?.aborted === true,\n\t\t\t);\n\t\t\tif (read === undefined) return err(new FileError(\"aborted\", \"aborted\", this.#path));\n\t\t\treturn ok(concat(read.chunks, read.total));\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, this.#path));\n\t\t}\n\t}\n\n\tasync scanLines(\n\t\toptions: { startLine: number; endLine?: number },\n\t\tcontext: Context,\n\t): Promise<Result<LineScan, FileError>> {\n\t\tconst early = abortResult<LineScan>(context.abortSignal, this.#path) ?? this.#closedResult<LineScan>();\n\t\tif (early) return early;\n\t\tconst { startLine, endLine } = options;\n\t\tif (\n\t\t\t!Number.isSafeInteger(startLine) ||\n\t\t\tstartLine < 0 ||\n\t\t\t(endLine !== undefined && (!Number.isSafeInteger(endLine) || endLine <= startLine))\n\t\t) {\n\t\t\treturn err(new FileError(\"invalid\", \"Invalid line range\", this.#path));\n\t\t}\n\t\ttry {\n\t\t\tconst { json } = await this.#handle.request(\n\t\t\t\t\"scanLines\",\n\t\t\t\t{ startLine, ...(endLine === undefined ? {} : { endLine }) },\n\t\t\t\tcontext.abortSignal ? { signal: context.abortSignal } : {},\n\t\t\t);\n\t\t\treturn ok(json as unknown as LineScan);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, this.#path));\n\t\t}\n\t}\n\n\tasync close(_context: Context): Promise<void> {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tawait this.#handle.close();\n\t}\n}\n\nclass RemoteDirReader implements DirReader {\n\treadonly #handle: Handle;\n\t#done = false;\n\t#closed = false;\n\n\tconstructor(handle: Handle) {\n\t\tthis.#handle = handle;\n\t}\n\n\tasync next(\n\t\tmaxEntries: number,\n\t\tcontext: Context,\n\t): Promise<Result<{ entries: FileInfo[]; done: boolean }, FileError>> {\n\t\tconst path = this.#handle.path;\n\t\tconst aborted = abortResult<{ entries: FileInfo[]; done: boolean }>(context.abortSignal, path);\n\t\tif (aborted) return aborted;\n\t\tif (this.#closed) return err(new FileError(\"invalid\", \"Directory reader is closed\", path));\n\t\tif (!Number.isSafeInteger(maxEntries) || maxEntries <= 0) {\n\t\t\treturn err(new FileError(\"invalid\", \"maxEntries must be a positive safe integer\", path));\n\t\t}\n\t\tconst entries: FileInfo[] = [];\n\t\ttry {\n\t\t\tconst paths = await remotePath(this.#handle.env.connection);\n\t\t\t// Like `NodeDirReader`, count only entries that are part of the listing.\n\t\t\twhile (!this.#done && entries.length < maxEntries) {\n\t\t\t\tconst { json } = await this.#handle.request(\"readdir\", { max: maxEntries - entries.length });\n\t\t\t\tconst loopAbort = abortResult<{ entries: FileInfo[]; done: boolean }>(context.abortSignal, path);\n\t\t\t\tif (loopAbort) return loopAbort;\n\t\t\t\tfor (const entry of json.entries as RemoteDirEntry[]) {\n\t\t\t\t\tconst entryPath = paths.resolve(path, entry.name);\n\t\t\t\t\tif (entry.error !== undefined) {\n\t\t\t\t\t\t// Removed between enumeration and lstat: not part of the listing any more.\n\t\t\t\t\t\tif (entry.error.code === \"ENOENT\") continue;\n\t\t\t\t\t\treturn err(toFileError(new RemoteError(entry.error), entryPath));\n\t\t\t\t\t}\n\t\t\t\t\tconst info = toInfo(entryPath, entry.info!, paths);\n\t\t\t\t\tif (info.ok) entries.push(info.value);\n\t\t\t\t}\n\t\t\t\tthis.#done = json.done === true;\n\t\t\t}\n\t\t\treturn ok({ entries, done: this.#done });\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, path));\n\t\t}\n\t}\n\n\tasync close(_context: Context): Promise<void> {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tawait this.#handle.close();\n\t}\n}\n\n/** `NodeTextLineReader`: positional reads of a file opened like `open(path, \"r\")`. */\nclass RemoteTextLineReader implements TextLineReader {\n\treadonly #handle: Handle;\n\treadonly #decoder = new StreamDecoder();\n\t#offset = 0;\n\t#buffered = \"\";\n\t#ended = false;\n\t#closed = false;\n\n\tconstructor(handle: Handle) {\n\t\tthis.#handle = handle;\n\t}\n\n\tasync readLine(context: Context): Promise<Result<TextLine | undefined, FileError>> {\n\t\tconst path = this.#handle.path;\n\t\tconst aborted = abortResult<TextLine | undefined>(context.abortSignal, path);\n\t\tif (aborted) return aborted;\n\t\tif (this.#closed) return err(new FileError(\"invalid\", \"Text line reader is closed\", path));\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tconst newline = this.#buffered.indexOf(\"\\n\");\n\t\t\t\tif (newline !== -1) {\n\t\t\t\t\tconst text = this.#buffered.slice(0, newline);\n\t\t\t\t\tthis.#buffered = this.#buffered.slice(newline + 1);\n\t\t\t\t\treturn ok({ text, terminated: true });\n\t\t\t\t}\n\t\t\t\tif (this.#ended) {\n\t\t\t\t\tif (this.#buffered.length === 0) return ok(undefined);\n\t\t\t\t\tconst text = this.#buffered;\n\t\t\t\t\tthis.#buffered = \"\";\n\t\t\t\t\treturn ok({ text, terminated: false });\n\t\t\t\t}\n\t\t\t\tconst bytes = await this.#handle.pread(this.#offset, LINE_CHUNK);\n\t\t\t\tconst afterReadAbort = abortResult<TextLine | undefined>(context.abortSignal, path);\n\t\t\t\tif (afterReadAbort) return afterReadAbort;\n\t\t\t\tthis.#offset += bytes.length;\n\t\t\t\tif (bytes.length === 0) {\n\t\t\t\t\tthis.#buffered += this.#decoder.decode();\n\t\t\t\t\tthis.#ended = true;\n\t\t\t\t} else {\n\t\t\t\t\tthis.#buffered += this.#decoder.decode(bytes);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, path));\n\t\t}\n\t}\n\n\tasync close(_context: Context): Promise<void> {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tthis.#buffered = \"\";\n\t\tawait this.#handle.close();\n\t}\n}\n\n/**\n * An `ExecutionEnv` on another machine, reached through a pi-env daemon. Results match `NodeExecutionEnv` running on\n * that machine: the daemon performs the system calls, and this class applies Node's path, error, and result rules.\n */\nexport class RemoteExecutionEnv implements ExecutionEnv {\n\treadonly id: string;\n\tcwd: string;\n\treadonly connection: Connection;\n\treadonly #shellPath: string | undefined;\n\treadonly #shellEnv: Record<string, string> | undefined;\n\treadonly #watchOptions: RemoteWatchOptions;\n\t/** Running commands this environment started, for `cleanup()`. */\n\treadonly #running = new Map<number, number>();\n\n\tconstructor(options: RemoteExecutionEnvOptions) {\n\t\tthis.id = options.id;\n\t\tthis.cwd = options.cwd;\n\t\tthis.connection = options.connection;\n\t\tthis.#shellPath = options.shellPath;\n\t\tthis.#shellEnv = options.shellEnv;\n\t\tthis.#watchOptions = options.watch ?? {};\n\t}\n\n\t/** Node's `resolvePath` on the remote system, with its home directory and working directories. */\n\tasync #resolve(path: string): Promise<string> {\n\t\tconst info = await this.connection.info();\n\t\tconst windows = nodePlatform(info).platform === \"win32\";\n\t\tconst paths = windows ? win32 : posix;\n\t\tlet normalized = path;\n\t\tif (normalized === \"~\") {\n\t\t\tnormalized = info.home;\n\t\t} else if (normalized.startsWith(\"~/\") || (windows && normalized.startsWith(\"~\\\\\"))) {\n\t\t\tnormalized = paths.join(info.home, normalized.slice(2));\n\t\t} else if (normalized.startsWith(\"file://\")) {\n\t\t\ttry {\n\t\t\t\tnormalized = fileURLToPath(normalized, { windows });\n\t\t\t} catch {\n\t\t\t\t// Keep malformed URLs as ordinary paths, as Node does.\n\t\t\t}\n\t\t}\n\t\tif (paths.isAbsolute(normalized)) return paths.resolve(normalized);\n\t\tif (windows) {\n\t\t\t// A drive-relative path on another drive: Node on Windows resolves it against that drive's working directory\n\t\t\t// (`=D:`), else its own working directory if on that drive, else the drive's root.\n\t\t\tconst drive = /^([a-zA-Z]:)(?![\\\\/])/.exec(normalized)?.[1];\n\t\t\tif (drive !== undefined && drive.toLowerCase() !== this.cwd.slice(0, 2).toLowerCase()) {\n\t\t\t\tlet base = info.driveCwds[drive.toUpperCase()] ?? info.cwd;\n\t\t\t\tif (base.slice(0, 2).toLowerCase() !== drive.toLowerCase() && base[2] === \"\\\\\") base = `${drive}\\\\`;\n\t\t\t\treturn win32.resolve(base, normalized);\n\t\t\t}\n\t\t}\n\t\treturn paths.resolve(this.cwd, normalized);\n\t}\n\n\tasync #fileOp<T>(\n\t\tpath: string,\n\t\tcontext: Context,\n\t\trun: (resolved: string) => Promise<T>,\n\t\tcheck: \"before\" | \"both\" = \"before\",\n\t): Promise<Result<T, FileError>> {\n\t\tlet resolved: string;\n\t\ttry {\n\t\t\tresolved = await this.#resolve(path);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, path));\n\t\t}\n\t\tconst aborted = abortResult<T>(context.abortSignal, resolved);\n\t\tif (aborted) return aborted;\n\t\ttry {\n\t\t\tconst value = await run(resolved);\n\t\t\tif (check === \"both\") {\n\t\t\t\tconst after = abortResult<T>(context.abortSignal, resolved);\n\t\t\t\tif (after) return after;\n\t\t\t}\n\t\t\treturn ok(value);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, resolved));\n\t\t}\n\t}\n\n\tasync #open(resolved: string, json: Json): Promise<{ handle: Handle; json: Json }> {\n\t\tconst reply = await this.connection.request(\"open\", { path: resolved, ...json });\n\t\treturn { handle: new Handle(this, reply.json.handle as number, reply.session, resolved), json: reply.json };\n\t}\n\n\tasync absolutePath(path: string, _context: Context): Promise<Result<string, FileError>> {\n\t\ttry {\n\t\t\treturn ok(await this.#resolve(path));\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, path));\n\t\t}\n\t}\n\n\tasync joinPath(parts: string[], _context: Context): Promise<Result<string, FileError>> {\n\t\ttry {\n\t\t\treturn ok((await remotePath(this.connection)).join(...parts));\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error));\n\t\t}\n\t}\n\n\t/** Node's `readFile`, with or without UTF-8 decoding, over a file opened like `open(path, \"r\")`. */\n\tasync #readFile(path: string, encoding: boolean, context: Context): Promise<Result<Uint8Array | string, FileError>> {\n\t\tconst signal = context.abortSignal;\n\t\treturn this.#fileOp(path, context, async (resolved) => {\n\t\t\tconst { handle, json } = await this.#open(resolved, { mode: \"read\" });\n\t\t\tconst aborted = () => signal?.aborted === true;\n\t\t\tconst abort = () => new FileError(\"aborted\", \"The operation was aborted\", resolved);\n\t\t\ttry {\n\t\t\t\tif (json.statError !== undefined) throw new RemoteError(json.statError as Json);\n\t\t\t\tif (aborted()) throw abort();\n\t\t\t\tconst stat = json.stat as RemoteFileInfo;\n\t\t\t\tconst size = stat.kind === \"file\" ? stat.size : 0;\n\t\t\t\tif (size > READ_FILE_MAX) {\n\t\t\t\t\tthrow new FileError(\"unknown\", `File size (${size}) is greater than 2 GiB`, resolved);\n\t\t\t\t}\n\t\t\t\tif (size === 0) {\n\t\t\t\t\t// Unknown size: sequential reads until the end, as for FIFOs and devices.\n\t\t\t\t\tconst decoder = new StringDecoder(\"utf8\");\n\t\t\t\t\tconst chunks: Uint8Array[] = [];\n\t\t\t\t\tlet total = 0;\n\t\t\t\t\tlet text = \"\";\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tif (aborted()) throw abort();\n\t\t\t\t\t\tconst bytes = await handle.pread(undefined, READ_FILE_UNKNOWN_CHUNK);\n\t\t\t\t\t\tif (bytes.length === 0) break;\n\t\t\t\t\t\ttotal += bytes.length;\n\t\t\t\t\t\tchunks.push(bytes);\n\t\t\t\t\t\tif (encoding) text += decoder.write(bytes);\n\t\t\t\t\t}\n\t\t\t\t\tif (!encoding) return Buffer.concat(chunks, total);\n\t\t\t\t\treturn total === 0 ? \"\" : text + decoder.end();\n\t\t\t\t}\n\t\t\t\tif (!encoding) {\n\t\t\t\t\t// A single read of the whole size, or reads of 512 KiB until the size or the end of the file.\n\t\t\t\t\tif (size <= READ_FILE_CHUNK) return Buffer.from(await handle.pread(0, size));\n\t\t\t\t\tconst read = await readRange(\n\t\t\t\t\t\t(at, length) => handle.pread(at, length),\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tREAD_FILE_CHUNK,\n\t\t\t\t\t\taborted,\n\t\t\t\t\t);\n\t\t\t\t\tif (read === undefined) throw abort();\n\t\t\t\t\treturn Buffer.concat(read.chunks, read.total);\n\t\t\t\t}\n\t\t\t\t// Decoding: reads of min(size, 512 KiB) until the size, a short read, or the end of the file.\n\t\t\t\tconst length = Math.min(size, READ_FILE_CHUNK);\n\t\t\t\tconst decoder = new StringDecoder(\"utf8\");\n\t\t\t\tlet text = \"\";\n\t\t\t\tlet total = 0;\n\t\t\t\tlet first = true;\n\t\t\t\tconst inFlight: Promise<Uint8Array>[] = [];\n\t\t\t\tlet next = 0;\n\t\t\t\twhile (true) {\n\t\t\t\t\twhile (inFlight.length < READ_DEPTH) {\n\t\t\t\t\t\tconst bytes = handle.pread(next, length);\n\t\t\t\t\t\tbytes.catch(() => {});\n\t\t\t\t\t\tinFlight.push(bytes);\n\t\t\t\t\t\tnext += length;\n\t\t\t\t\t}\n\t\t\t\t\tconst bytes = await inFlight.shift()!;\n\t\t\t\t\tif (aborted()) throw abort();\n\t\t\t\t\ttotal += bytes.length;\n\t\t\t\t\tif (bytes.length === 0 || total === size || bytes.length !== length) {\n\t\t\t\t\t\treturn first ? Buffer.from(bytes).toString(\"utf8\") : text + decoder.end(Buffer.from(bytes));\n\t\t\t\t\t}\n\t\t\t\t\ttext += decoder.write(Buffer.from(bytes));\n\t\t\t\t\tfirst = false;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait handle.close();\n\t\t\t}\n\t\t});\n\t}\n\n\tasync readTextFile(path: string, context: Context): Promise<Result<string, FileError>> {\n\t\treturn (await this.#readFile(path, true, context)) as Result<string, FileError>;\n\t}\n\n\tasync readBinaryFile(path: string, context: Context): Promise<Result<Uint8Array, FileError>> {\n\t\treturn (await this.#readFile(path, false, context)) as Result<Uint8Array, FileError>;\n\t}\n\n\tasync openBinaryReader(\n\t\tpath: string,\n\t\toptions: { noFollow?: boolean } | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<BinaryReader, FileError>> {\n\t\tconst opened = await this.#fileOp(path, context, async (resolved) => {\n\t\t\treturn (await this.#open(resolved, { noFollow: options?.noFollow === true })).handle;\n\t\t});\n\t\tif (!opened.ok) return opened;\n\t\tconst aborted = abortResult<BinaryReader>(context.abortSignal, opened.value.path);\n\t\tif (aborted) {\n\t\t\tawait opened.value.close();\n\t\t\treturn aborted;\n\t\t}\n\t\treturn ok(new RemoteBinaryReader(opened.value));\n\t}\n\n\tasync openTextLineReader(path: string, context: Context): Promise<Result<TextLineReader, FileError>> {\n\t\tconst opened = await this.#fileOp(path, context, async (resolved) => {\n\t\t\treturn (await this.#open(resolved, { mode: \"read\" })).handle;\n\t\t});\n\t\tif (!opened.ok) return opened;\n\t\tconst aborted = abortResult<TextLineReader>(context.abortSignal, opened.value.path);\n\t\tif (aborted) {\n\t\t\tawait opened.value.close();\n\t\t\treturn aborted;\n\t\t}\n\t\treturn ok(new RemoteTextLineReader(opened.value));\n\t}\n\n\tasync readTextLines(\n\t\tpath: string,\n\t\toptions: { maxLines?: number } | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<string[], FileError>> {\n\t\tif (options?.maxLines !== undefined && options.maxLines <= 0) return ok([]);\n\t\tconst opened = await this.openTextLineReader(path, context);\n\t\tif (!opened.ok) return opened;\n\t\tconst lines: string[] = [];\n\t\ttry {\n\t\t\twhile (options?.maxLines === undefined || lines.length < options.maxLines) {\n\t\t\t\tconst line = await opened.value.readLine(context);\n\t\t\t\tif (!line.ok) return line;\n\t\t\t\tif (line.value === undefined) break;\n\t\t\t\tlines.push(line.value.text);\n\t\t\t}\n\t\t\treturn ok(lines);\n\t\t} finally {\n\t\t\tawait opened.value.close(context);\n\t\t}\n\t}\n\n\t/**\n\t * Node's `writeFile` (abort checked before each 512 KiB write) or `appendFile` (no checks, one after): the first\n\t * request creates parents, opens, and writes the first chunk; later chunks go to the same open file.\n\t */\n\tasync #write(path: string, content: string | Uint8Array, append: boolean, context: Context) {\n\t\tconst bytes = typeof content === \"string\" ? Buffer.from(content, \"utf8\") : content;\n\t\tconst signal = append ? undefined : context.abortSignal;\n\t\treturn this.#fileOp(\n\t\t\tpath,\n\t\t\tcontext,\n\t\t\tasync (resolved) => {\n\t\t\t\tconst first = bytes.subarray(0, WRITE_CHUNK);\n\t\t\t\tconst keep = bytes.length > WRITE_CHUNK;\n\t\t\t\tconst reply = await this.connection.request(\"write\", { path: resolved, append, keep }, { payload: first });\n\t\t\t\tif (!keep) return;\n\t\t\t\tconst handle = new Handle(this, reply.json.handle as number, reply.session, resolved);\n\t\t\t\tconst inFlight: Promise<unknown>[] = [];\n\t\t\t\ttry {\n\t\t\t\t\tfor (let offset = WRITE_CHUNK; offset < bytes.length; offset += WRITE_CHUNK) {\n\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t// A chunk that failed before this check fails the write, as it would have in sequence.\n\t\t\t\t\t\t\tconst failed = (await Promise.allSettled(inFlight)).find((result) => result.status === \"rejected\");\n\t\t\t\t\t\t\tif (failed !== undefined) throw failed.reason;\n\t\t\t\t\t\t\tthrow new FileError(\"aborted\", \"The operation was aborted\", resolved);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst written = handle.request(\n\t\t\t\t\t\t\t\"writeChunk\",\n\t\t\t\t\t\t\t{},\n\t\t\t\t\t\t\t{ payload: bytes.subarray(offset, offset + WRITE_CHUNK) },\n\t\t\t\t\t\t);\n\t\t\t\t\t\twritten.catch(() => {});\n\t\t\t\t\t\tinFlight.push(written);\n\t\t\t\t\t\tif (inFlight.length >= WRITE_DEPTH) await inFlight.shift();\n\t\t\t\t\t}\n\t\t\t\t\t// The first failure; later chunks are refused by the daemon, so the file has no gaps.\n\t\t\t\t\tfor (const written of inFlight) await written;\n\t\t\t\t} finally {\n\t\t\t\t\tawait Promise.allSettled(inFlight);\n\t\t\t\t\tawait handle.close();\n\t\t\t\t}\n\t\t\t},\n\t\t\tappend ? \"both\" : \"before\",\n\t\t);\n\t}\n\n\twriteFile(path: string, content: string | Uint8Array, context: Context): Promise<Result<void, FileError>> {\n\t\treturn this.#write(path, content, false, context);\n\t}\n\n\tappendFile(path: string, content: string | Uint8Array, context: Context): Promise<Result<void, FileError>> {\n\t\treturn this.#write(path, content, true, context);\n\t}\n\n\tasync truncateFile(path: string, size: number, context: Context): Promise<Result<void, FileError>> {\n\t\treturn this.#fileOp(\n\t\t\tpath,\n\t\t\tcontext,\n\t\t\tasync (resolved) => {\n\t\t\t\tif (!Number.isSafeInteger(size) || size < 0) {\n\t\t\t\t\tthrow new FileError(\"invalid\", \"File size must be a non-negative safe integer\", resolved);\n\t\t\t\t}\n\t\t\t\tawait this.connection.request(\"truncate\", { path: resolved, size });\n\t\t\t},\n\t\t\t\"both\",\n\t\t);\n\t}\n\n\tflushFile(path: string, context: Context): Promise<Result<void, FileError>> {\n\t\treturn this.#fileOp(\n\t\t\tpath,\n\t\t\tcontext,\n\t\t\tasync (resolved) => {\n\t\t\t\tawait this.connection.request(\"fsync\", { path: resolved });\n\t\t\t},\n\t\t\t\"both\",\n\t\t);\n\t}\n\n\tasync renameFile(sourcePath: string, destinationPath: string, context: Context): Promise<Result<void, FileError>> {\n\t\tlet source: string;\n\t\tlet destination: string;\n\t\ttry {\n\t\t\tsource = await this.#resolve(sourcePath);\n\t\t\tdestination = await this.#resolve(destinationPath);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, sourcePath));\n\t\t}\n\t\tconst aborted = abortResult<void>(context.abortSignal, destination);\n\t\tif (aborted) return aborted;\n\t\ttry {\n\t\t\tawait this.connection.request(\"rename\", { path: source, to: destination });\n\t\t\treturn ok(undefined);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, source));\n\t\t}\n\t}\n\n\tasync fileInfo(path: string, context: Context): Promise<Result<FileInfo, FileError>> {\n\t\tconst result = await this.#fileOp(path, context, async (resolved) => {\n\t\t\tconst { json } = await this.connection.request(\"lstat\", { path: resolved });\n\t\t\treturn toInfo(resolved, json as unknown as RemoteFileInfo, await remotePath(this.connection));\n\t\t});\n\t\treturn result.ok ? result.value : result;\n\t}\n\n\tlistDir(path: string, context: Context): Promise<Result<FileInfo[], FileError>> {\n\t\treturn this.#fileOp(path, context, async (resolved) => {\n\t\t\tconst { handle } = await this.#openDir(resolved);\n\t\t\tconst entries: RemoteDirEntry[] = [];\n\t\t\ttry {\n\t\t\t\tfor (let done = false; !done; ) {\n\t\t\t\t\tconst { json } = await handle.request(\"readdir\", { max: 1000 });\n\t\t\t\t\tentries.push(...(json.entries as RemoteDirEntry[]));\n\t\t\t\t\tdone = json.done === true;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait handle.close();\n\t\t\t}\n\t\t\t// Node's `readdir` fails on any entry it cannot lstat. libuv sorts names by their bytes on POSIX; on Windows it\n\t\t\t// keeps the file system's order, which the daemon reports.\n\t\t\tconst paths = await remotePath(this.connection);\n\t\t\tif (paths === posix) {\n\t\t\t\tconst key = (entry: RemoteDirEntry) => Buffer.from(entry.raw ?? Buffer.from(entry.name, \"utf8\"));\n\t\t\t\tentries.sort((a, b) => Buffer.compare(key(a), key(b)));\n\t\t\t}\n\t\t\tconst infos: FileInfo[] = [];\n\t\t\tfor (const entry of entries) {\n\t\t\t\tif (context.abortSignal?.aborted) throw new FileError(\"aborted\", \"aborted\", resolved);\n\t\t\t\tconst entryPath = paths.resolve(resolved, entry.name);\n\t\t\t\tif (entry.error !== undefined) throw toFileError(new RemoteError(entry.error), entryPath);\n\t\t\t\tconst info = toInfo(entryPath, entry.info!, paths);\n\t\t\t\tif (info.ok) infos.push(info.value);\n\t\t\t}\n\t\t\treturn infos;\n\t\t});\n\t}\n\n\t/** Through the daemon; `not_supported` with a daemon released before `listFiles`. */\n\tasync listFiles(\n\t\tpath: string,\n\t\toptions: ListFilesOptions | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<FileListing, FileError>> {\n\t\tlet resolved: string;\n\t\ttry {\n\t\t\tresolved = await this.#resolve(path);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, path));\n\t\t}\n\t\treturn listFilesOver(this.connection, resolved, options, context);\n\t}\n\n\tasync #openDir(resolved: string): Promise<{ handle: Handle }> {\n\t\tconst reply = await this.connection.request(\"opendir\", { path: resolved });\n\t\treturn { handle: new Handle(this, reply.json.handle as number, reply.session, resolved) };\n\t}\n\n\tasync openDirReader(path: string, context: Context): Promise<Result<DirReader, FileError>> {\n\t\tconst opened = await this.#fileOp(path, context, async (resolved) => (await this.#openDir(resolved)).handle);\n\t\tif (!opened.ok) return opened;\n\t\tconst aborted = abortResult<DirReader>(context.abortSignal, opened.value.path);\n\t\tif (aborted) {\n\t\t\tawait opened.value.close();\n\t\t\treturn aborted;\n\t\t}\n\t\treturn ok(new RemoteDirReader(opened.value));\n\t}\n\n\tcanonicalPath(path: string, context: Context): Promise<Result<string, FileError>> {\n\t\treturn this.#fileOp(path, context, async (resolved) => {\n\t\t\tconst { json } = await this.connection.request(\"realpath\", { path: resolved });\n\t\t\treturn json.path as string;\n\t\t});\n\t}\n\n\tasync exists(path: string, context: Context): Promise<Result<boolean, FileError>> {\n\t\tconst result = await this.fileInfo(path, context);\n\t\tif (result.ok) return ok(true);\n\t\tif (result.error.code === \"not_found\") return ok(false);\n\t\treturn err(result.error);\n\t}\n\n\tcreateDir(\n\t\tpath: string,\n\t\toptions: { recursive?: boolean } | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<void, FileError>> {\n\t\treturn this.#fileOp(path, context, async (resolved) => {\n\t\t\tawait this.connection.request(\"mkdir\", { path: resolved, recursive: options?.recursive ?? true });\n\t\t});\n\t}\n\n\tremove(\n\t\tpath: string,\n\t\toptions: { recursive?: boolean; force?: boolean } | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<void, FileError>> {\n\t\treturn this.#fileOp(path, context, async (resolved) => {\n\t\t\tawait this.connection.request(\"rm\", {\n\t\t\t\tpath: resolved,\n\t\t\t\trecursive: options?.recursive ?? false,\n\t\t\t\tforce: options?.force ?? false,\n\t\t\t});\n\t\t});\n\t}\n\n\tasync createTempDir(prefix: string | undefined, context: Context): Promise<Result<string, FileError>> {\n\t\tconst aborted = abortResult<string>(context.abortSignal);\n\t\tif (aborted) return aborted;\n\t\ttry {\n\t\t\tconst { tmpdir } = await this.connection.info();\n\t\t\tconst paths = await remotePath(this.connection);\n\t\t\tconst { json } = await this.connection.request(\"mkdtemp\", { path: paths.join(tmpdir, prefix ?? \"tmp-\") });\n\t\t\treturn ok(json.path as string);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error));\n\t\t}\n\t}\n\n\tasync createTempFile(\n\t\toptions: { prefix?: string; suffix?: string } | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<string, FileError>> {\n\t\tconst dir = await this.createTempDir(\"tmp-\", context);\n\t\tif (!dir.ok) return dir;\n\t\tlet filePath = \"\";\n\t\ttry {\n\t\t\tconst paths = await remotePath(this.connection);\n\t\t\tfilePath = paths.join(dir.value, `${options?.prefix ?? \"\"}${randomUUID()}${options?.suffix ?? \"\"}`);\n\t\t\t// Node's `writeFile(filePath, \"\")`, which does not create parents.\n\t\t\tawait this.connection.request(\n\t\t\t\t\"write\",\n\t\t\t\t{ path: filePath, append: false, parents: false },\n\t\t\t\t{ payload: new Uint8Array(0) },\n\t\t\t);\n\t\t\treturn ok(filePath);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error, filePath));\n\t\t}\n\t}\n\n\tasync watch(\n\t\ttargets: readonly WatchTarget[],\n\t\tonChange: (change: FileChange) => void,\n\t\tcontext: Context,\n\t): Promise<Result<FileWatcher, FileError>> {\n\t\tconst aborted = abortResult<FileWatcher>(context.abortSignal);\n\t\tif (aborted) return aborted;\n\t\ttry {\n\t\t\tconst resolved = await Promise.all(\n\t\t\t\ttargets.map(async (target) => ({ ...target, path: await this.#resolve(target.path) })),\n\t\t\t);\n\t\t\tconst afterResolve = abortResult<FileWatcher>(context.abortSignal);\n\t\t\tif (afterResolve) return afterResolve;\n\t\t\tconst watcher = await RemoteWatcher.open(this.connection, resolved, onChange, this.#watchOptions);\n\t\t\tconst afterOpen = abortResult<FileWatcher>(context.abortSignal);\n\t\t\tif (afterOpen) {\n\t\t\t\tawait watcher.stop(context);\n\t\t\t\treturn afterOpen;\n\t\t\t}\n\t\t\treturn ok(watcher);\n\t\t} catch (error) {\n\t\t\treturn err(toFileError(error));\n\t\t}\n\t}\n\n\tasync exec(\n\t\tcommand: string | readonly string[],\n\t\toptions: ShellExecOptions | undefined,\n\t\tcontext: Context,\n\t): Promise<Result<ShellExecResult, ExecutionError>> {\n\t\tconst signal = context.abortSignal;\n\t\tif (signal?.aborted) return err(new ExecutionError(\"aborted\", \"aborted\"));\n\t\tconst timeout = options?.timeout;\n\t\tif (timeout !== undefined) {\n\t\t\tif (!Number.isFinite(timeout) || timeout <= 0) {\n\t\t\t\treturn err(new ExecutionError(\"timeout\", \"Invalid timeout: must be a finite number of seconds\"));\n\t\t\t}\n\t\t\tif (timeout * 1000 > MAX_TIMEOUT_MS) {\n\t\t\t\treturn err(new ExecutionError(\"timeout\", `Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`));\n\t\t\t}\n\t\t}\n\t\tconst inheritEnv = options?.inheritEnv ?? true;\n\t\tlet cwd: string;\n\t\ttry {\n\t\t\tcwd = options?.cwd ? await this.#resolve(options.cwd) : this.cwd;\n\t\t} catch (error) {\n\t\t\treturn err(new ExecutionError(\"unknown\", error instanceof Error ? error.message : String(error)));\n\t\t}\n\t\tif (signal?.aborted) return err(new ExecutionError(\"aborted\", \"aborted\"));\n\t\tconst env: Record<string, string> = {};\n\t\tfor (const [key, value] of Object.entries(\n\t\t\tinheritEnv ? { ...this.#shellEnv, ...options?.env } : { ...options?.env },\n\t\t)) {\n\t\t\tif (value !== undefined) env[key.toWellFormed()] = value;\n\t\t}\n\t\tlet callbackError: ExecutionError | undefined;\n\t\tlet settled = false;\n\t\tlet running: number | undefined;\n\t\tconst controller = new AbortController();\n\t\tconst onAbort = () => controller.abort();\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\ttry {\n\t\t\tconst { json } = await this.connection.request(\n\t\t\t\t\"exec\",\n\t\t\t\t{\n\t\t\t\t\t...(typeof command === \"string\" ? { command } : { argv: [...command] }),\n\t\t\t\t\tcwd,\n\t\t\t\t\tenv,\n\t\t\t\t\tinheritEnv,\n\t\t\t\t\t...(this.#shellPath === undefined ? {} : { shellPath: this.#shellPath }),\n\t\t\t\t\t...(timeout === undefined ? {} : { timeoutMs: timeout * 1000 }),\n\t\t\t\t\t...(options?.spill === undefined ? {} : { spill: options.spill }),\n\t\t\t\t\t...(options?.window === undefined ? {} : { window: options.window }),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\tonStart: (requestId, session) => {\n\t\t\t\t\t\trunning = requestId;\n\t\t\t\t\t\tthis.#running.set(requestId, session);\n\t\t\t\t\t},\n\t\t\t\t\tonEvent: (event, payload) => {\n\t\t\t\t\t\tif (settled || callbackError !== undefined || event.kind !== \"output\") return;\n\t\t\t\t\t\tconst text = Buffer.from(payload.buffer, payload.byteOffset, payload.length).toString(\"utf8\");\n\t\t\t\t\t\tif (text === \"\" || options?.onOutput === undefined) return;\n\t\t\t\t\t\tconst info: ShellOutputInfo = { stream: event.stream === \"stderr\" ? \"stderr\" : \"stdout\" };\n\t\t\t\t\t\tif (event.skipped !== undefined) info.skipped = event.skipped as ShellOutputSkip;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\toptions.onOutput(text, context, info);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconst cause = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\t\t\tcallbackError = new ExecutionError(\"callback_error\", cause.message, cause);\n\t\t\t\t\t\t\tcontroller.abort();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (callbackError) return err(callbackError);\n\t\t\treturn ok({\n\t\t\t\texitCode: json.exitCode as number,\n\t\t\t\t...(typeof json.spillPath === \"string\" ? { spillPath: json.spillPath } : {}),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (callbackError) return err(callbackError);\n\t\t\tif (!(error instanceof RemoteError)) {\n\t\t\t\treturn err(new ExecutionError(\"unknown\", error instanceof Error ? error.message : String(error)));\n\t\t\t}\n\t\t\tconst failure =\n\t\t\t\terror.code === \"timeout\"\n\t\t\t\t\t? new ExecutionError(\"timeout\", `timeout:${timeout}`)\n\t\t\t\t\t: error.code === \"aborted\"\n\t\t\t\t\t\t? new ExecutionError(\"aborted\", \"aborted\")\n\t\t\t\t\t\t: error.code === \"shell_unavailable\" || error.code === \"spawn_error\"\n\t\t\t\t\t\t\t? new ExecutionError(error.code, error.message)\n\t\t\t\t\t\t\t: new ExecutionError(\"unknown\", error.message);\n\t\t\tif (typeof error.fields.spillPath === \"string\") failure.spillPath = error.fields.spillPath;\n\t\t\treturn err(failure);\n\t\t} finally {\n\t\t\tsettled = true;\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tif (running !== undefined) this.#running.delete(running);\n\t\t}\n\t}\n\n\tasync cleanup(_context: Context): Promise<void> {\n\t\t// Kill without aborting, so the commands settle with their killed status, as `NodeExecutionEnv` does.\n\t\tfor (const [id, session] of this.#running) this.connection.kill(id, session);\n\t\tthis.#running.clear();\n\t}\n}\n\nexport type { RemoteInfo };\n"]}
|
package/dist/watch.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Context } from "@earendil-works/chord";
|
|
2
|
-
import { type
|
|
2
|
+
import { type FileChange, type FileWatcher, type WatchTarget } from "@earendil-works/pi-durable/env";
|
|
3
3
|
import { type Connection } from "./connection.ts";
|
|
4
4
|
/** How the daemon watches, like `NodeExecutionEnv`'s `NodeWatchOptions`. */
|
|
5
5
|
export interface RemoteWatchOptions {
|
|
@@ -18,8 +18,8 @@ export declare class RemoteWatcher implements FileWatcher {
|
|
|
18
18
|
#private;
|
|
19
19
|
private constructor();
|
|
20
20
|
/** Watch `targets` (resolved paths); fails like `NodeFileWatcher.open` if coverage cannot be established. */
|
|
21
|
-
static open(connection: Connection, targets: readonly WatchTarget[], onChange: (change:
|
|
21
|
+
static open(connection: Connection, targets: readonly WatchTarget[], onChange: (change: FileChange) => void, options?: RemoteWatchOptions): Promise<RemoteWatcher>;
|
|
22
22
|
get mode(): "native" | "polling";
|
|
23
|
-
|
|
23
|
+
stop(_context: Context): Promise<void>;
|
|
24
24
|
}
|
|
25
25
|
//# sourceMappingURL=watch.d.ts.map
|
package/dist/watch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,KAAK,UAAU,EAAa,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAChH,OAAO,EAAE,KAAK,UAAU,EAAoB,MAAM,iBAAiB,CAAC;AAGpE,4EAA4E;AAC5E,MAAM,WAAW,kBAAkB;IAClC,gGAAgG;IAChG,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAQD;;;GAGG;AACH,qBAAa,aAAc,YAAW,WAAW;;IAWhD,OAAO,eAUN;IAED,6GAA6G;IAC7G,OAAa,IAAI,CAChB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,SAAS,WAAW,EAAE,EAC/B,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,EACtC,OAAO,GAAE,kBAAuB,GAC9B,OAAO,CAAC,aAAa,CAAC,CAIxB;IAED,IAAI,IAAI,IAAI,QAAQ,GAAG,SAAS,CAE/B;IAEK,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAM3C;CA2FD"}
|
package/dist/watch.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { FileError } from "@earendil-works/pi-durable/env";
|
|
2
2
|
import { isConnectionLost } from "./connection.js";
|
|
3
3
|
import { toFileError } from "./errors.js";
|
|
4
|
+
/** The one `overflow` change; it carries nothing else. */
|
|
5
|
+
const OVERFLOW = { kind: "overflow" };
|
|
4
6
|
const RECONNECT_FIRST_MS = 1000;
|
|
5
7
|
const RECONNECT_MAX_MS = 30_000;
|
|
6
8
|
/**
|
|
@@ -13,7 +15,7 @@ export class RemoteWatcher {
|
|
|
13
15
|
#onChange;
|
|
14
16
|
#options;
|
|
15
17
|
#mode = "native";
|
|
16
|
-
#
|
|
18
|
+
#stopped = false;
|
|
17
19
|
#controller;
|
|
18
20
|
#request;
|
|
19
21
|
#wake;
|
|
@@ -32,16 +34,16 @@ export class RemoteWatcher {
|
|
|
32
34
|
get mode() {
|
|
33
35
|
return this.#mode;
|
|
34
36
|
}
|
|
35
|
-
async
|
|
36
|
-
if (this.#
|
|
37
|
+
async stop(_context) {
|
|
38
|
+
if (this.#stopped)
|
|
37
39
|
return;
|
|
38
|
-
this.#
|
|
40
|
+
this.#stopped = true;
|
|
39
41
|
this.#wake?.();
|
|
40
42
|
this.#controller?.abort();
|
|
41
43
|
await this.#request;
|
|
42
44
|
}
|
|
43
45
|
#deliver(change) {
|
|
44
|
-
if (this.#
|
|
46
|
+
if (this.#stopped)
|
|
45
47
|
return;
|
|
46
48
|
try {
|
|
47
49
|
this.#onChange(change);
|
|
@@ -74,15 +76,16 @@ export class RemoteWatcher {
|
|
|
74
76
|
else if (event.kind === "change") {
|
|
75
77
|
if (event.mode === "polling")
|
|
76
78
|
this.#mode = "polling";
|
|
79
|
+
// The daemon's wire format: `{ overflow: true }` or `{ paths }`.
|
|
77
80
|
if (event.overflow === true)
|
|
78
|
-
this.#deliver(
|
|
81
|
+
this.#deliver(OVERFLOW);
|
|
79
82
|
else
|
|
80
|
-
this.#deliver({ paths: event.paths });
|
|
83
|
+
this.#deliver({ kind: "paths", paths: event.paths });
|
|
81
84
|
}
|
|
82
85
|
else if (event.kind === "error") {
|
|
83
86
|
const code = event.code === "permission_denied" ? "permission_denied" : "invalid";
|
|
84
|
-
this.#deliver({ error: new FileError(code, String(event.message)) });
|
|
85
|
-
this.#
|
|
87
|
+
this.#deliver({ kind: "failed", error: new FileError(code, String(event.message)) });
|
|
88
|
+
this.#stopped = true;
|
|
86
89
|
}
|
|
87
90
|
},
|
|
88
91
|
});
|
|
@@ -91,19 +94,19 @@ export class RemoteWatcher {
|
|
|
91
94
|
reject(error);
|
|
92
95
|
return;
|
|
93
96
|
}
|
|
94
|
-
if (this.#
|
|
97
|
+
if (this.#stopped)
|
|
95
98
|
return;
|
|
96
99
|
if (isConnectionLost(error)) {
|
|
97
100
|
void this.#reconnect();
|
|
98
101
|
return;
|
|
99
102
|
}
|
|
100
|
-
this.#deliver({ error: toFileError(error) });
|
|
101
|
-
this.#
|
|
103
|
+
this.#deliver({ kind: "failed", error: toFileError(error) });
|
|
104
|
+
this.#stopped = true;
|
|
102
105
|
});
|
|
103
106
|
});
|
|
104
107
|
}
|
|
105
108
|
async #reconnect() {
|
|
106
|
-
for (let delay = RECONNECT_FIRST_MS; !this.#
|
|
109
|
+
for (let delay = RECONNECT_FIRST_MS; !this.#stopped; delay = Math.min(delay * 2, RECONNECT_MAX_MS)) {
|
|
107
110
|
await new Promise((resolve) => {
|
|
108
111
|
const timer = setTimeout(resolve, delay);
|
|
109
112
|
timer.unref();
|
|
@@ -113,19 +116,19 @@ export class RemoteWatcher {
|
|
|
113
116
|
};
|
|
114
117
|
});
|
|
115
118
|
this.#wake = undefined;
|
|
116
|
-
if (this.#
|
|
119
|
+
if (this.#stopped)
|
|
117
120
|
return;
|
|
118
121
|
try {
|
|
119
122
|
await this.#start();
|
|
120
123
|
// Changes while disconnected were not seen.
|
|
121
|
-
this.#deliver(
|
|
124
|
+
this.#deliver(OVERFLOW);
|
|
122
125
|
return;
|
|
123
126
|
}
|
|
124
127
|
catch (error) {
|
|
125
128
|
if (isConnectionLost(error))
|
|
126
129
|
continue;
|
|
127
|
-
this.#deliver({ error: toFileError(error) });
|
|
128
|
-
this.#
|
|
130
|
+
this.#deliver({ kind: "failed", error: toFileError(error) });
|
|
131
|
+
this.#stopped = true;
|
|
129
132
|
return;
|
|
130
133
|
}
|
|
131
134
|
}
|
package/dist/watch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Context } from \"@earendil-works/chord\";\nimport { FileError, type FileWatcher, type WatchChange, type WatchTarget } from \"@earendil-works/pi-durable/env\";\nimport { type Connection, isConnectionLost } from \"./connection.ts\";\nimport { toFileError } from \"./errors.ts\";\n\n/** How the daemon watches, like `NodeExecutionEnv`'s `NodeWatchOptions`. */\nexport interface RemoteWatchOptions {\n\t/** Force a mode; by default Windows and file systems that do not report remote changes poll. */\n\tmode?: \"native\" | \"polling\";\n\t/** Interval between snapshots in `polling` mode; default 2000 ms. */\n\tpollIntervalMs?: number;\n\t/** Most directories one watcher covers; default 10,000. */\n\tmaxDirectories?: number;\n}\n\nconst RECONNECT_FIRST_MS = 1000;\nconst RECONNECT_MAX_MS = 30_000;\n\n/**\n * A watcher running in the daemon (Durable's `NodeFileWatcher` next to the files). When the connection is lost, it is\n * opened again once the connection can be started again, and reports `overflow`: changes in between were not seen.\n */\nexport class RemoteWatcher implements FileWatcher {\n\treadonly #connection: Connection;\n\treadonly #targets: readonly WatchTarget[];\n\treadonly #onChange: (change: WatchChange) => void;\n\treadonly #options: RemoteWatchOptions;\n\t#mode: \"native\" | \"polling\" = \"native\";\n\t#closed = false;\n\t#controller: AbortController | undefined;\n\t#request: Promise<void> | undefined;\n\t#wake: (() => void) | undefined;\n\n\tprivate constructor(\n\t\tconnection: Connection,\n\t\ttargets: readonly WatchTarget[],\n\t\tonChange: (change: WatchChange) => void,\n\t\toptions: RemoteWatchOptions,\n\t) {\n\t\tthis.#connection = connection;\n\t\tthis.#targets = targets;\n\t\tthis.#onChange = onChange;\n\t\tthis.#options = options;\n\t}\n\n\t/** Watch `targets` (resolved paths); fails like `NodeFileWatcher.open` if coverage cannot be established. */\n\tstatic async open(\n\t\tconnection: Connection,\n\t\ttargets: readonly WatchTarget[],\n\t\tonChange: (change: WatchChange) => void,\n\t\toptions: RemoteWatchOptions = {},\n\t): Promise<RemoteWatcher> {\n\t\tconst watcher = new RemoteWatcher(connection, targets, onChange, options);\n\t\tawait watcher.#start();\n\t\treturn watcher;\n\t}\n\n\tget mode(): \"native\" | \"polling\" {\n\t\treturn this.#mode;\n\t}\n\n\tasync close(_context: Context): Promise<void> {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tthis.#wake?.();\n\t\tthis.#controller?.abort();\n\t\tawait this.#request;\n\t}\n\n\t#deliver(change: WatchChange): void {\n\t\tif (this.#closed) return;\n\t\ttry {\n\t\t\tthis.#onChange(change);\n\t\t} catch {\n\t\t\t// A throwing callback must not stop watching.\n\t\t}\n\t}\n\n\t/** Open the daemon's watcher; resolves once it reports coverage. */\n\t#start(): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet ready = false;\n\t\t\tconst controller = new AbortController();\n\t\t\tthis.#controller = controller;\n\t\t\tconst request = this.#connection.request(\n\t\t\t\t\"watch\",\n\t\t\t\t{\n\t\t\t\t\ttargets: this.#targets.map((target) => ({\n\t\t\t\t\t\tpath: target.path,\n\t\t\t\t\t\trecursive: target.recursive === true,\n\t\t\t\t\t\texclude: { hidden: target.exclude?.hidden === true, names: [...(target.exclude?.names ?? [])] },\n\t\t\t\t\t})),\n\t\t\t\t\t...this.#options,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\tonEvent: (event) => {\n\t\t\t\t\t\tif (event.kind === \"ready\") {\n\t\t\t\t\t\t\tready = true;\n\t\t\t\t\t\t\tthis.#mode = event.mode === \"polling\" ? \"polling\" : \"native\";\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t} else if (event.kind === \"change\") {\n\t\t\t\t\t\t\tif (event.mode === \"polling\") this.#mode = \"polling\";\n\t\t\t\t\t\t\tif (event.overflow === true) this.#deliver({ overflow: true });\n\t\t\t\t\t\t\telse this.#deliver({ paths: event.paths as string[] });\n\t\t\t\t\t\t} else if (event.kind === \"error\") {\n\t\t\t\t\t\t\tconst code = event.code === \"permission_denied\" ? \"permission_denied\" : \"invalid\";\n\t\t\t\t\t\t\tthis.#deliver({ error: new FileError(code, String(event.message)) });\n\t\t\t\t\t\t\tthis.#closed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.#request = request.then(\n\t\t\t\t() => {},\n\t\t\t\t(error: unknown) => {\n\t\t\t\t\tif (!ready) {\n\t\t\t\t\t\treject(error);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (this.#closed) return;\n\t\t\t\t\tif (isConnectionLost(error)) {\n\t\t\t\t\t\tvoid this.#reconnect();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.#deliver({ error: toFileError(error) });\n\t\t\t\t\tthis.#closed = true;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tasync #reconnect(): Promise<void> {\n\t\tfor (let delay = RECONNECT_FIRST_MS; !this.#closed; delay = Math.min(delay * 2, RECONNECT_MAX_MS)) {\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tconst timer = setTimeout(resolve, delay);\n\t\t\t\ttimer.unref();\n\t\t\t\tthis.#wake = () => {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tresolve();\n\t\t\t\t};\n\t\t\t});\n\t\t\tthis.#wake = undefined;\n\t\t\tif (this.#closed) return;\n\t\t\ttry {\n\t\t\t\tawait this.#start();\n\t\t\t\t// Changes while disconnected were not seen.\n\t\t\t\tthis.#deliver({ overflow: true });\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tif (isConnectionLost(error)) continue;\n\t\t\t\tthis.#deliver({ error: toFileError(error) });\n\t\t\t\tthis.#closed = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Context } from \"@earendil-works/chord\";\nimport { type FileChange, FileError, type FileWatcher, type WatchTarget } from \"@earendil-works/pi-durable/env\";\nimport { type Connection, isConnectionLost } from \"./connection.ts\";\nimport { toFileError } from \"./errors.ts\";\n\n/** How the daemon watches, like `NodeExecutionEnv`'s `NodeWatchOptions`. */\nexport interface RemoteWatchOptions {\n\t/** Force a mode; by default Windows and file systems that do not report remote changes poll. */\n\tmode?: \"native\" | \"polling\";\n\t/** Interval between snapshots in `polling` mode; default 2000 ms. */\n\tpollIntervalMs?: number;\n\t/** Most directories one watcher covers; default 10,000. */\n\tmaxDirectories?: number;\n}\n\n/** The one `overflow` change; it carries nothing else. */\nconst OVERFLOW: FileChange = { kind: \"overflow\" };\n\nconst RECONNECT_FIRST_MS = 1000;\nconst RECONNECT_MAX_MS = 30_000;\n\n/**\n * A watcher running in the daemon (Durable's `NodeFileWatcher` next to the files). When the connection is lost, it is\n * opened again once the connection can be started again, and reports `overflow`: changes in between were not seen.\n */\nexport class RemoteWatcher implements FileWatcher {\n\treadonly #connection: Connection;\n\treadonly #targets: readonly WatchTarget[];\n\treadonly #onChange: (change: FileChange) => void;\n\treadonly #options: RemoteWatchOptions;\n\t#mode: \"native\" | \"polling\" = \"native\";\n\t#stopped = false;\n\t#controller: AbortController | undefined;\n\t#request: Promise<void> | undefined;\n\t#wake: (() => void) | undefined;\n\n\tprivate constructor(\n\t\tconnection: Connection,\n\t\ttargets: readonly WatchTarget[],\n\t\tonChange: (change: FileChange) => void,\n\t\toptions: RemoteWatchOptions,\n\t) {\n\t\tthis.#connection = connection;\n\t\tthis.#targets = targets;\n\t\tthis.#onChange = onChange;\n\t\tthis.#options = options;\n\t}\n\n\t/** Watch `targets` (resolved paths); fails like `NodeFileWatcher.open` if coverage cannot be established. */\n\tstatic async open(\n\t\tconnection: Connection,\n\t\ttargets: readonly WatchTarget[],\n\t\tonChange: (change: FileChange) => void,\n\t\toptions: RemoteWatchOptions = {},\n\t): Promise<RemoteWatcher> {\n\t\tconst watcher = new RemoteWatcher(connection, targets, onChange, options);\n\t\tawait watcher.#start();\n\t\treturn watcher;\n\t}\n\n\tget mode(): \"native\" | \"polling\" {\n\t\treturn this.#mode;\n\t}\n\n\tasync stop(_context: Context): Promise<void> {\n\t\tif (this.#stopped) return;\n\t\tthis.#stopped = true;\n\t\tthis.#wake?.();\n\t\tthis.#controller?.abort();\n\t\tawait this.#request;\n\t}\n\n\t#deliver(change: FileChange): void {\n\t\tif (this.#stopped) return;\n\t\ttry {\n\t\t\tthis.#onChange(change);\n\t\t} catch {\n\t\t\t// A throwing callback must not stop watching.\n\t\t}\n\t}\n\n\t/** Open the daemon's watcher; resolves once it reports coverage. */\n\t#start(): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet ready = false;\n\t\t\tconst controller = new AbortController();\n\t\t\tthis.#controller = controller;\n\t\t\tconst request = this.#connection.request(\n\t\t\t\t\"watch\",\n\t\t\t\t{\n\t\t\t\t\ttargets: this.#targets.map((target) => ({\n\t\t\t\t\t\tpath: target.path,\n\t\t\t\t\t\trecursive: target.recursive === true,\n\t\t\t\t\t\texclude: { hidden: target.exclude?.hidden === true, names: [...(target.exclude?.names ?? [])] },\n\t\t\t\t\t})),\n\t\t\t\t\t...this.#options,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\tonEvent: (event) => {\n\t\t\t\t\t\tif (event.kind === \"ready\") {\n\t\t\t\t\t\t\tready = true;\n\t\t\t\t\t\t\tthis.#mode = event.mode === \"polling\" ? \"polling\" : \"native\";\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t} else if (event.kind === \"change\") {\n\t\t\t\t\t\t\tif (event.mode === \"polling\") this.#mode = \"polling\";\n\t\t\t\t\t\t\t// The daemon's wire format: `{ overflow: true }` or `{ paths }`.\n\t\t\t\t\t\t\tif (event.overflow === true) this.#deliver(OVERFLOW);\n\t\t\t\t\t\t\telse this.#deliver({ kind: \"paths\", paths: event.paths as string[] });\n\t\t\t\t\t\t} else if (event.kind === \"error\") {\n\t\t\t\t\t\t\tconst code = event.code === \"permission_denied\" ? \"permission_denied\" : \"invalid\";\n\t\t\t\t\t\t\tthis.#deliver({ kind: \"failed\", error: new FileError(code, String(event.message)) });\n\t\t\t\t\t\t\tthis.#stopped = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.#request = request.then(\n\t\t\t\t() => {},\n\t\t\t\t(error: unknown) => {\n\t\t\t\t\tif (!ready) {\n\t\t\t\t\t\treject(error);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (this.#stopped) return;\n\t\t\t\t\tif (isConnectionLost(error)) {\n\t\t\t\t\t\tvoid this.#reconnect();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.#deliver({ kind: \"failed\", error: toFileError(error) });\n\t\t\t\t\tthis.#stopped = true;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tasync #reconnect(): Promise<void> {\n\t\tfor (let delay = RECONNECT_FIRST_MS; !this.#stopped; delay = Math.min(delay * 2, RECONNECT_MAX_MS)) {\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tconst timer = setTimeout(resolve, delay);\n\t\t\t\ttimer.unref();\n\t\t\t\tthis.#wake = () => {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tresolve();\n\t\t\t\t};\n\t\t\t});\n\t\t\tthis.#wake = undefined;\n\t\t\tif (this.#stopped) return;\n\t\t\ttry {\n\t\t\t\tawait this.#start();\n\t\t\t\t// Changes while disconnected were not seen.\n\t\t\t\tthis.#deliver(OVERFLOW);\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tif (isConnectionLost(error)) continue;\n\t\t\t\tthis.#deliver({ kind: \"failed\", error: toFileError(error) });\n\t\t\t\tthis.#stopped = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
package/docs/protocol.md
CHANGED
|
@@ -62,9 +62,11 @@ command as a full pipe would.
|
|
|
62
62
|
## Liveness
|
|
63
63
|
|
|
64
64
|
Each side sends `ping` every 5 seconds. The daemon kills every process group it started and exits after 30 seconds
|
|
65
|
-
without receiving any bytes,
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
without receiving any bytes, when stdin ends, or on `SIGTERM`, `SIGINT` or `SIGHUP`. A dropped connection or a
|
|
66
|
+
stopped daemon therefore stops remote commands. On Windows, a terminated daemon cannot clean up: a job object kills
|
|
67
|
+
each command's own process, but not processes that one started. The client fails requests of a lost connection with
|
|
68
|
+
`{ code: "unknown", lost: true }` and starts a new daemon on the next request; handles belong to the daemon that opened
|
|
69
|
+
them, so requests on them fail instead of reaching the new one.
|
|
68
70
|
|
|
69
71
|
## Operations
|
|
70
72
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earendil-works/pi-env",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Remote execution environments for Pi Durable: a small daemon deployed over SSH and its ExecutionEnv client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"CHANGELOG.md"
|
|
23
23
|
],
|
|
24
24
|
"scripts": {
|
|
25
|
-
"clean": "
|
|
25
|
+
"clean": "node ../../scripts/package-files.mjs clean dist",
|
|
26
26
|
"build": "tsc -p tsconfig.build.json",
|
|
27
27
|
"build:daemon": "cargo build --manifest-path daemon/Cargo.toml --locked",
|
|
28
28
|
"test": "vitest --run",
|
|
@@ -45,11 +45,10 @@
|
|
|
45
45
|
"node": ">=22.19.0"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@earendil-works/chord": "1.
|
|
49
|
-
"@earendil-works/pi-durable": "1.
|
|
48
|
+
"@earendil-works/chord": "1.5.0",
|
|
49
|
+
"@earendil-works/pi-durable": "1.5.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"
|
|
53
|
-
"vitest": "4.1.11"
|
|
52
|
+
"vitest": "4.1.12"
|
|
54
53
|
}
|
|
55
54
|
}
|