@code-yeongyu/senpi-agent-core 2026.9.12-3 → 2026.9.12
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/README.md +0 -4
- package/dist/harness/agent-harness.d.ts +384 -639
- package/dist/harness/agent-harness.d.ts.map +1 -1
- package/dist/harness/agent-harness.js +250 -5
- package/dist/harness/agent-harness.js.map +1 -1
- package/dist/harness/compaction/branch-summarization.d.ts +6 -12
- package/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/harness/compaction/branch-summarization.js +27 -33
- package/dist/harness/compaction/branch-summarization.js.map +1 -1
- package/dist/harness/compaction/compaction.d.ts +8 -30
- package/dist/harness/compaction/compaction.d.ts.map +1 -1
- package/dist/harness/compaction/compaction.js +64 -53
- package/dist/harness/compaction/compaction.js.map +1 -1
- package/dist/harness/env/nodejs.d.ts +28 -25
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +125 -368
- package/dist/harness/env/nodejs.js.map +1 -1
- package/dist/harness/events.d.ts +38 -20
- package/dist/harness/events.d.ts.map +1 -1
- package/dist/harness/events.js +55 -233
- package/dist/harness/events.js.map +1 -1
- package/dist/harness/messages.d.ts +2 -2
- package/dist/harness/messages.d.ts.map +1 -1
- package/dist/harness/messages.js.map +1 -1
- package/dist/harness/prompt-templates.d.ts +2 -3
- package/dist/harness/prompt-templates.d.ts.map +1 -1
- package/dist/harness/prompt-templates.js +17 -17
- package/dist/harness/prompt-templates.js.map +1 -1
- package/dist/harness/reducer.d.ts +100 -0
- package/dist/harness/reducer.d.ts.map +1 -0
- package/dist/harness/reducer.js +420 -0
- package/dist/harness/reducer.js.map +1 -0
- package/dist/harness/result.d.ts +0 -93
- package/dist/harness/result.d.ts.map +1 -1
- package/dist/harness/result.js +0 -39
- package/dist/harness/result.js.map +1 -1
- package/dist/harness/session/context.d.ts +19 -6
- package/dist/harness/session/context.d.ts.map +1 -1
- package/dist/harness/session/context.js +53 -31
- package/dist/harness/session/context.js.map +1 -1
- package/dist/harness/session/index.d.ts +5 -9
- package/dist/harness/session/index.d.ts.map +1 -1
- package/dist/harness/session/index.js +4 -7
- package/dist/harness/session/index.js.map +1 -1
- package/dist/harness/session/jsonl/codec.d.ts +8 -19
- package/dist/harness/session/jsonl/codec.d.ts.map +1 -1
- package/dist/harness/session/jsonl/codec.js +219 -34
- package/dist/harness/session/jsonl/codec.js.map +1 -1
- package/dist/harness/session/jsonl/errors.d.ts +9 -0
- package/dist/harness/session/jsonl/errors.d.ts.map +1 -0
- package/dist/harness/session/jsonl/errors.js +18 -0
- package/dist/harness/session/jsonl/errors.js.map +1 -0
- package/dist/harness/session/jsonl/repo.d.ts +24 -27
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
- package/dist/harness/session/jsonl/repo.js +151 -276
- package/dist/harness/session/jsonl/repo.js.map +1 -1
- package/dist/harness/session/jsonl/storage.d.ts +41 -39
- package/dist/harness/session/jsonl/storage.d.ts.map +1 -1
- package/dist/harness/session/jsonl/storage.js +196 -175
- package/dist/harness/session/jsonl/storage.js.map +1 -1
- package/dist/harness/session/jsonl/types.d.ts +22 -23
- package/dist/harness/session/jsonl/types.d.ts.map +1 -1
- package/dist/harness/session/jsonl/types.js +1 -2
- package/dist/harness/session/jsonl/types.js.map +1 -1
- package/dist/harness/session/jsonl.d.ts +3 -0
- package/dist/harness/session/jsonl.d.ts.map +1 -0
- package/dist/harness/session/jsonl.js +2 -0
- package/dist/harness/session/jsonl.js.map +1 -0
- package/dist/harness/session/memory.d.ts +40 -44
- package/dist/harness/session/memory.d.ts.map +1 -1
- package/dist/harness/session/memory.js +115 -333
- package/dist/harness/session/memory.js.map +1 -1
- package/dist/harness/session/session.d.ts +51 -78
- package/dist/harness/session/session.d.ts.map +1 -1
- package/dist/harness/session/session.js +207 -327
- package/dist/harness/session/session.js.map +1 -1
- package/dist/harness/session/state.d.ts +65 -0
- package/dist/harness/session/state.d.ts.map +1 -0
- package/dist/harness/session/state.js +320 -0
- package/dist/harness/session/state.js.map +1 -0
- package/dist/harness/session/testing/conformance.d.ts +4 -0
- package/dist/harness/session/testing/conformance.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance.js +762 -0
- package/dist/harness/session/testing/conformance.js.map +1 -0
- package/dist/harness/session/testing/index.d.ts +2 -9
- package/dist/harness/session/testing/index.d.ts.map +1 -1
- package/dist/harness/session/testing/index.js +1 -8
- package/dist/harness/session/testing/index.js.map +1 -1
- package/dist/harness/session/testing/types.d.ts +7 -5
- package/dist/harness/session/testing/types.d.ts.map +1 -1
- package/dist/harness/session/testing/types.js.map +1 -1
- package/dist/harness/session/types.d.ts +265 -425
- package/dist/harness/session/types.d.ts.map +1 -1
- package/dist/harness/session/types.js +7 -7
- package/dist/harness/session/types.js.map +1 -1
- package/dist/harness/skills.d.ts +2 -3
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +26 -29
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/telemetry.d.ts +43 -64
- package/dist/harness/telemetry.d.ts.map +1 -1
- package/dist/harness/telemetry.js +26 -45
- package/dist/harness/telemetry.js.map +1 -1
- package/dist/harness/tools/bash.d.ts +4 -4
- package/dist/harness/tools/bash.d.ts.map +1 -1
- package/dist/harness/tools/bash.js +93 -66
- package/dist/harness/tools/bash.js.map +1 -1
- package/dist/harness/tools/edit.d.ts.map +1 -1
- package/dist/harness/tools/edit.js +13 -17
- package/dist/harness/tools/edit.js.map +1 -1
- package/dist/harness/tools/file-mutation-queue.d.ts +1 -2
- package/dist/harness/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/harness/tools/file-mutation-queue.js +5 -5
- package/dist/harness/tools/file-mutation-queue.js.map +1 -1
- package/dist/harness/tools/path-utils.d.ts +2 -3
- package/dist/harness/tools/path-utils.d.ts.map +1 -1
- package/dist/harness/tools/path-utils.js +5 -5
- package/dist/harness/tools/path-utils.js.map +1 -1
- package/dist/harness/tools/read.d.ts +1 -2
- package/dist/harness/tools/read.d.ts.map +1 -1
- package/dist/harness/tools/read.js +6 -4
- package/dist/harness/tools/read.js.map +1 -1
- package/dist/harness/tools/write.d.ts.map +1 -1
- package/dist/harness/tools/write.js +8 -12
- package/dist/harness/tools/write.js.map +1 -1
- package/dist/harness/types.d.ts +45 -128
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/utils/shell-output.d.ts +5 -19
- package/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/dist/harness/utils/shell-output.js +192 -65
- package/dist/harness/utils/shell-output.js.map +1 -1
- package/dist/harness/utils/truncate.d.ts +0 -1
- package/dist/harness/utils/truncate.d.ts.map +1 -1
- package/dist/harness/utils/truncate.js +1 -1
- package/dist/harness/utils/truncate.js.map +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/search/index.d.ts +16 -24
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +1 -1
- package/dist/search/index.js.map +1 -1
- package/dist/search/scanning.d.ts +29 -0
- package/dist/search/scanning.d.ts.map +1 -0
- package/dist/search/scanning.js +103 -0
- package/dist/search/scanning.js.map +1 -0
- package/dist/types.d.ts +0 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -27
- package/dist/harness/config.d.ts +0 -9
- package/dist/harness/config.d.ts.map +0 -1
- package/dist/harness/config.js +0 -35
- package/dist/harness/config.js.map +0 -1
- package/dist/harness/context.d.ts +0 -9
- package/dist/harness/context.d.ts.map +0 -1
- package/dist/harness/context.js +0 -13
- package/dist/harness/context.js.map +0 -1
- package/dist/harness/execution/assistant.d.ts +0 -42
- package/dist/harness/execution/assistant.d.ts.map +0 -1
- package/dist/harness/execution/assistant.js +0 -82
- package/dist/harness/execution/assistant.js.map +0 -1
- package/dist/harness/execution/effect-gate.d.ts +0 -22
- package/dist/harness/execution/effect-gate.d.ts.map +0 -1
- package/dist/harness/execution/effect-gate.js +0 -48
- package/dist/harness/execution/effect-gate.js.map +0 -1
- package/dist/harness/execution/tools.d.ts +0 -67
- package/dist/harness/execution/tools.d.ts.map +0 -1
- package/dist/harness/execution/tools.js +0 -121
- package/dist/harness/execution/tools.js.map +0 -1
- package/dist/harness/hooks.d.ts +0 -38
- package/dist/harness/hooks.d.ts.map +0 -1
- package/dist/harness/hooks.js +0 -404
- package/dist/harness/hooks.js.map +0 -1
- package/dist/harness/runtime/drive/boundary.d.ts +0 -28
- package/dist/harness/runtime/drive/boundary.d.ts.map +0 -1
- package/dist/harness/runtime/drive/boundary.js +0 -173
- package/dist/harness/runtime/drive/boundary.js.map +0 -1
- package/dist/harness/runtime/drive/checkpoint.d.ts +0 -8
- package/dist/harness/runtime/drive/checkpoint.d.ts.map +0 -1
- package/dist/harness/runtime/drive/checkpoint.js +0 -133
- package/dist/harness/runtime/drive/checkpoint.js.map +0 -1
- package/dist/harness/runtime/drive/deferred.d.ts +0 -15
- package/dist/harness/runtime/drive/deferred.d.ts.map +0 -1
- package/dist/harness/runtime/drive/deferred.js +0 -179
- package/dist/harness/runtime/drive/deferred.js.map +0 -1
- package/dist/harness/runtime/drive/generation.d.ts +0 -8
- package/dist/harness/runtime/drive/generation.d.ts.map +0 -1
- package/dist/harness/runtime/drive/generation.js +0 -205
- package/dist/harness/runtime/drive/generation.js.map +0 -1
- package/dist/harness/runtime/drive/reconcile.d.ts +0 -5
- package/dist/harness/runtime/drive/reconcile.d.ts.map +0 -1
- package/dist/harness/runtime/drive/reconcile.js +0 -140
- package/dist/harness/runtime/drive/reconcile.js.map +0 -1
- package/dist/harness/runtime/drive/recovery.d.ts +0 -8
- package/dist/harness/runtime/drive/recovery.d.ts.map +0 -1
- package/dist/harness/runtime/drive/recovery.js +0 -85
- package/dist/harness/runtime/drive/recovery.js.map +0 -1
- package/dist/harness/runtime/drive/response.d.ts +0 -23
- package/dist/harness/runtime/drive/response.d.ts.map +0 -1
- package/dist/harness/runtime/drive/response.js +0 -394
- package/dist/harness/runtime/drive/response.js.map +0 -1
- package/dist/harness/runtime/drive/retry.d.ts +0 -4
- package/dist/harness/runtime/drive/retry.d.ts.map +0 -1
- package/dist/harness/runtime/drive/retry.js +0 -34
- package/dist/harness/runtime/drive/retry.js.map +0 -1
- package/dist/harness/runtime/drive/structural.d.ts +0 -32
- package/dist/harness/runtime/drive/structural.d.ts.map +0 -1
- package/dist/harness/runtime/drive/structural.js +0 -929
- package/dist/harness/runtime/drive/structural.js.map +0 -1
- package/dist/harness/runtime/drive/terminal.d.ts +0 -7
- package/dist/harness/runtime/drive/terminal.d.ts.map +0 -1
- package/dist/harness/runtime/drive/terminal.js +0 -49
- package/dist/harness/runtime/drive/terminal.js.map +0 -1
- package/dist/harness/runtime/drive/tool-placement.d.ts +0 -14
- package/dist/harness/runtime/drive/tool-placement.d.ts.map +0 -1
- package/dist/harness/runtime/drive/tool-placement.js +0 -244
- package/dist/harness/runtime/drive/tool-placement.js.map +0 -1
- package/dist/harness/runtime/drive/tools.d.ts +0 -6
- package/dist/harness/runtime/drive/tools.d.ts.map +0 -1
- package/dist/harness/runtime/drive/tools.js +0 -449
- package/dist/harness/runtime/drive/tools.js.map +0 -1
- package/dist/harness/runtime/drive.d.ts +0 -6
- package/dist/harness/runtime/drive.d.ts.map +0 -1
- package/dist/harness/runtime/drive.js +0 -93
- package/dist/harness/runtime/drive.js.map +0 -1
- package/dist/harness/runtime/harness.d.ts +0 -59
- package/dist/harness/runtime/harness.d.ts.map +0 -1
- package/dist/harness/runtime/harness.js +0 -302
- package/dist/harness/runtime/harness.js.map +0 -1
- package/dist/harness/runtime/index.d.ts +0 -2
- package/dist/harness/runtime/index.d.ts.map +0 -1
- package/dist/harness/runtime/index.js +0 -2
- package/dist/harness/runtime/index.js.map +0 -1
- package/dist/harness/runtime/lane.d.ts +0 -118
- package/dist/harness/runtime/lane.d.ts.map +0 -1
- package/dist/harness/runtime/lane.js +0 -1559
- package/dist/harness/runtime/lane.js.map +0 -1
- package/dist/harness/runtime/progress.d.ts +0 -15
- package/dist/harness/runtime/progress.d.ts.map +0 -1
- package/dist/harness/runtime/progress.js +0 -66
- package/dist/harness/runtime/progress.js.map +0 -1
- package/dist/harness/runtime/reducer.d.ts +0 -5
- package/dist/harness/runtime/reducer.d.ts.map +0 -1
- package/dist/harness/runtime/reducer.js +0 -240
- package/dist/harness/runtime/reducer.js.map +0 -1
- package/dist/harness/runtime/restore.d.ts +0 -24
- package/dist/harness/runtime/restore.d.ts.map +0 -1
- package/dist/harness/runtime/restore.js +0 -117
- package/dist/harness/runtime/restore.js.map +0 -1
- package/dist/harness/runtime/transcript.d.ts +0 -21
- package/dist/harness/runtime/transcript.d.ts.map +0 -1
- package/dist/harness/runtime/transcript.js +0 -72
- package/dist/harness/runtime/transcript.js.map +0 -1
- package/dist/harness/runtime/types.d.ts +0 -105
- package/dist/harness/runtime/types.d.ts.map +0 -1
- package/dist/harness/runtime/types.js +0 -50
- package/dist/harness/runtime/types.js.map +0 -1
- package/dist/harness/session/commit.d.ts +0 -53
- package/dist/harness/session/commit.d.ts.map +0 -1
- package/dist/harness/session/commit.js +0 -57
- package/dist/harness/session/commit.js.map +0 -1
- package/dist/harness/session/fork-policy.d.ts +0 -21
- package/dist/harness/session/fork-policy.d.ts.map +0 -1
- package/dist/harness/session/fork-policy.js +0 -55
- package/dist/harness/session/fork-policy.js.map +0 -1
- package/dist/harness/session/fork.d.ts +0 -16
- package/dist/harness/session/fork.d.ts.map +0 -1
- package/dist/harness/session/fork.js +0 -79
- package/dist/harness/session/fork.js.map +0 -1
- package/dist/harness/session/in-memory-storage-state.d.ts +0 -39
- package/dist/harness/session/in-memory-storage-state.d.ts.map +0 -1
- package/dist/harness/session/in-memory-storage-state.js +0 -269
- package/dist/harness/session/in-memory-storage-state.js.map +0 -1
- package/dist/harness/session/jsonl/fork.d.ts +0 -38
- package/dist/harness/session/jsonl/fork.d.ts.map +0 -1
- package/dist/harness/session/jsonl/fork.js +0 -266
- package/dist/harness/session/jsonl/fork.js.map +0 -1
- package/dist/harness/session/jsonl/index.d.ts +0 -4
- package/dist/harness/session/jsonl/index.d.ts.map +0 -1
- package/dist/harness/session/jsonl/index.js +0 -4
- package/dist/harness/session/jsonl/index.js.map +0 -1
- package/dist/harness/session/jsonl/io.d.ts +0 -14
- package/dist/harness/session/jsonl/io.d.ts.map +0 -1
- package/dist/harness/session/jsonl/io.js +0 -86
- package/dist/harness/session/jsonl/io.js.map +0 -1
- package/dist/harness/session/jsonl/legacy-v3.d.ts +0 -44
- package/dist/harness/session/jsonl/legacy-v3.d.ts.map +0 -1
- package/dist/harness/session/jsonl/legacy-v3.js +0 -454
- package/dist/harness/session/jsonl/legacy-v3.js.map +0 -1
- package/dist/harness/session/mutation-line.d.ts +0 -8
- package/dist/harness/session/mutation-line.d.ts.map +0 -1
- package/dist/harness/session/mutation-line.js +0 -22
- package/dist/harness/session/mutation-line.js.map +0 -1
- package/dist/harness/session/testing/benchmark/datasets.d.ts +0 -12
- package/dist/harness/session/testing/benchmark/datasets.d.ts.map +0 -1
- package/dist/harness/session/testing/benchmark/datasets.js +0 -24
- package/dist/harness/session/testing/benchmark/datasets.js.map +0 -1
- package/dist/harness/session/testing/benchmark/session-repo.d.ts +0 -42
- package/dist/harness/session/testing/benchmark/session-repo.d.ts.map +0 -1
- package/dist/harness/session/testing/benchmark/session-repo.js +0 -127
- package/dist/harness/session/testing/benchmark/session-repo.js.map +0 -1
- package/dist/harness/session/testing/benchmark/storage.d.ts +0 -25
- package/dist/harness/session/testing/benchmark/storage.d.ts.map +0 -1
- package/dist/harness/session/testing/benchmark/storage.js +0 -114
- package/dist/harness/session/testing/benchmark/storage.js.map +0 -1
- package/dist/harness/session/testing/conformance/session-repo.d.ts +0 -23
- package/dist/harness/session/testing/conformance/session-repo.d.ts.map +0 -1
- package/dist/harness/session/testing/conformance/session-repo.js +0 -809
- package/dist/harness/session/testing/conformance/session-repo.js.map +0 -1
- package/dist/harness/session/testing/conformance/storage.d.ts +0 -4
- package/dist/harness/session/testing/conformance/storage.d.ts.map +0 -1
- package/dist/harness/session/testing/conformance/storage.js +0 -600
- package/dist/harness/session/testing/conformance/storage.js.map +0 -1
- package/dist/harness/session/testing/gating-storage.d.ts +0 -26
- package/dist/harness/session/testing/gating-storage.d.ts.map +0 -1
- package/dist/harness/session/testing/gating-storage.js +0 -103
- package/dist/harness/session/testing/gating-storage.js.map +0 -1
- package/dist/harness/session/testing/instrumented-storage.d.ts +0 -11
- package/dist/harness/session/testing/instrumented-storage.d.ts.map +0 -1
- package/dist/harness/session/testing/instrumented-storage.js +0 -19
- package/dist/harness/session/testing/instrumented-storage.js.map +0 -1
- package/dist/harness/session/testing/storage-decorator.d.ts +0 -20
- package/dist/harness/session/testing/storage-decorator.d.ts.map +0 -1
- package/dist/harness/session/testing/storage-decorator.js +0 -40
- package/dist/harness/session/testing/storage-decorator.js.map +0 -1
- package/dist/harness/session/values.d.ts +0 -95
- package/dist/harness/session/values.d.ts.map +0 -1
- package/dist/harness/session/values.js +0 -81
- package/dist/harness/session/values.js.map +0 -1
- package/dist/harness/utils/adaptive-publisher.d.ts +0 -24
- package/dist/harness/utils/adaptive-publisher.d.ts.map +0 -1
- package/dist/harness/utils/adaptive-publisher.js +0 -79
- package/dist/harness/utils/adaptive-publisher.js.map +0 -1
- package/dist/harness/utils/output-capture.d.ts +0 -31
- package/dist/harness/utils/output-capture.d.ts.map +0 -1
- package/dist/harness/utils/output-capture.js +0 -217
- package/dist/harness/utils/output-capture.js.map +0 -1
- package/dist/harness/utils/usage.d.ts +0 -4
- package/dist/harness/utils/usage.d.ts.map +0 -1
- package/dist/harness/utils/usage.js +0 -33
- package/dist/harness/utils/usage.js.map +0 -1
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { spawn, spawnSync } from "node:child_process";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
|
-
import { constants,
|
|
4
|
-
import { access, appendFile, lstat, mkdir, mkdtemp,
|
|
5
|
-
import { homedir,
|
|
3
|
+
import { constants, createReadStream, existsSync } from "node:fs";
|
|
4
|
+
import { access, appendFile, lstat, mkdir, mkdtemp, readdir, readFile, realpath, rename, rm, writeFile, } from "node:fs/promises";
|
|
5
|
+
import { homedir, tmpdir } from "node:os";
|
|
6
6
|
import { basename, isAbsolute, join, resolve } from "node:path";
|
|
7
|
+
import { createInterface } from "node:readline";
|
|
7
8
|
import { fileURLToPath } from "node:url";
|
|
8
9
|
import { ExecutionError, err, FileError, ok, toError, } from "../types.js";
|
|
9
|
-
import { OutputCapture } from "../utils/output-capture.js";
|
|
10
10
|
const MAX_TIMEOUT_MS = 2_147_483_647;
|
|
11
11
|
const MAX_TIMEOUT_SECONDS = MAX_TIMEOUT_MS / 1000;
|
|
12
12
|
const EXIT_STDIO_GRACE_MS = 100;
|
|
13
|
-
const SPILL_HIGH_WATER_MARK = 8 * 1024 * 1024;
|
|
14
13
|
function resolveTimeoutMs(timeout) {
|
|
15
14
|
if (timeout === undefined)
|
|
16
15
|
return ok(undefined);
|
|
@@ -290,12 +289,11 @@ function killProcessTree(pid) {
|
|
|
290
289
|
}
|
|
291
290
|
}
|
|
292
291
|
}
|
|
293
|
-
function waitForChildProcess(child
|
|
292
|
+
function waitForChildProcess(child) {
|
|
294
293
|
return new Promise((resolvePromise, reject) => {
|
|
295
294
|
let settled = false;
|
|
296
295
|
let exited = false;
|
|
297
296
|
let exitCode = null;
|
|
298
|
-
let exitSignal = null;
|
|
299
297
|
let postExitTimer;
|
|
300
298
|
let stdoutEnded = child.stdout === null;
|
|
301
299
|
let stderrEnded = child.stderr === null;
|
|
@@ -310,28 +308,23 @@ function waitForChildProcess(child, spillIsDraining) {
|
|
|
310
308
|
child.stdout?.removeListener("data", onData);
|
|
311
309
|
child.stderr?.removeListener("data", onData);
|
|
312
310
|
};
|
|
313
|
-
const finalize = () => {
|
|
311
|
+
const finalize = (code) => {
|
|
314
312
|
if (settled)
|
|
315
313
|
return;
|
|
316
314
|
settled = true;
|
|
317
315
|
cleanup();
|
|
318
316
|
child.stdout?.destroy();
|
|
319
317
|
child.stderr?.destroy();
|
|
320
|
-
resolvePromise(
|
|
318
|
+
resolvePromise(code);
|
|
321
319
|
};
|
|
322
320
|
const maybeFinalizeAfterExit = () => {
|
|
323
321
|
if (exited && stdoutEnded && stderrEnded)
|
|
324
|
-
finalize();
|
|
322
|
+
finalize(exitCode);
|
|
325
323
|
};
|
|
326
324
|
const armIdleTimer = () => {
|
|
327
325
|
if (postExitTimer)
|
|
328
326
|
clearTimeout(postExitTimer);
|
|
329
|
-
postExitTimer = setTimeout(() =>
|
|
330
|
-
if (spillIsDraining())
|
|
331
|
-
armIdleTimer();
|
|
332
|
-
else
|
|
333
|
-
finalize();
|
|
334
|
-
}, EXIT_STDIO_GRACE_MS);
|
|
327
|
+
postExitTimer = setTimeout(() => finalize(exitCode), EXIT_STDIO_GRACE_MS);
|
|
335
328
|
};
|
|
336
329
|
const onData = () => {
|
|
337
330
|
if (exited && !settled)
|
|
@@ -352,19 +345,14 @@ function waitForChildProcess(child, spillIsDraining) {
|
|
|
352
345
|
cleanup();
|
|
353
346
|
reject(error);
|
|
354
347
|
};
|
|
355
|
-
const onExit = (code
|
|
348
|
+
const onExit = (code) => {
|
|
356
349
|
exited = true;
|
|
357
350
|
exitCode = code;
|
|
358
|
-
exitSignal = signal;
|
|
359
351
|
maybeFinalizeAfterExit();
|
|
360
352
|
if (!settled)
|
|
361
353
|
armIdleTimer();
|
|
362
354
|
};
|
|
363
|
-
const onClose = (code
|
|
364
|
-
exitCode = code;
|
|
365
|
-
exitSignal = signal;
|
|
366
|
-
finalize();
|
|
367
|
-
};
|
|
355
|
+
const onClose = (code) => finalize(code);
|
|
368
356
|
child.stdout?.once("end", onStdoutEnd);
|
|
369
357
|
child.stderr?.once("end", onStderrEnd);
|
|
370
358
|
child.stdout?.on("data", onData);
|
|
@@ -375,71 +363,6 @@ function waitForChildProcess(child, spillIsDraining) {
|
|
|
375
363
|
});
|
|
376
364
|
}
|
|
377
365
|
const NORMAL_CALLBACK_SETTLEMENT_TIMEOUT_MS = 5_000;
|
|
378
|
-
/** Strict LF reader; Node readline does not report whether its final line was newline-terminated. */
|
|
379
|
-
class NodeTextLineReader {
|
|
380
|
-
constructor(file, path) {
|
|
381
|
-
this.decoder = new TextDecoder();
|
|
382
|
-
this.chunk = new Uint8Array(64 * 1024);
|
|
383
|
-
this.byteOffset = 0;
|
|
384
|
-
this.buffered = "";
|
|
385
|
-
this.ended = false;
|
|
386
|
-
this.closed = false;
|
|
387
|
-
this.file = file;
|
|
388
|
-
this.path = path;
|
|
389
|
-
}
|
|
390
|
-
async readLine(context) {
|
|
391
|
-
const aborted = abortResult(context.abortSignal, this.path);
|
|
392
|
-
if (aborted)
|
|
393
|
-
return aborted;
|
|
394
|
-
if (this.closed)
|
|
395
|
-
return err(new FileError("invalid", "Text line reader is closed", this.path));
|
|
396
|
-
try {
|
|
397
|
-
while (true) {
|
|
398
|
-
const newline = this.buffered.indexOf("\n");
|
|
399
|
-
if (newline !== -1) {
|
|
400
|
-
const text = this.buffered.slice(0, newline);
|
|
401
|
-
this.buffered = this.buffered.slice(newline + 1);
|
|
402
|
-
return ok({ text, terminated: true });
|
|
403
|
-
}
|
|
404
|
-
if (this.ended) {
|
|
405
|
-
if (this.buffered.length === 0)
|
|
406
|
-
return ok(undefined);
|
|
407
|
-
const text = this.buffered;
|
|
408
|
-
this.buffered = "";
|
|
409
|
-
return ok({ text, terminated: false });
|
|
410
|
-
}
|
|
411
|
-
// Explicit positions allow an aborted read to be retried without skipping bytes.
|
|
412
|
-
const { bytesRead } = await this.file.read(this.chunk, 0, this.chunk.length, this.byteOffset);
|
|
413
|
-
const afterReadAbort = abortResult(context.abortSignal, this.path);
|
|
414
|
-
if (afterReadAbort)
|
|
415
|
-
return afterReadAbort;
|
|
416
|
-
this.byteOffset += bytesRead;
|
|
417
|
-
if (bytesRead === 0) {
|
|
418
|
-
this.buffered += this.decoder.decode();
|
|
419
|
-
this.ended = true;
|
|
420
|
-
}
|
|
421
|
-
else {
|
|
422
|
-
this.buffered += this.decoder.decode(this.chunk.subarray(0, bytesRead), { stream: true });
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
catch (error) {
|
|
427
|
-
return err(toFileError(error, this.path));
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
async close(_context) {
|
|
431
|
-
if (this.closed)
|
|
432
|
-
return;
|
|
433
|
-
this.closed = true;
|
|
434
|
-
this.buffered = "";
|
|
435
|
-
try {
|
|
436
|
-
await this.file.close();
|
|
437
|
-
}
|
|
438
|
-
catch {
|
|
439
|
-
// Closing is best-effort, including after cancellation or an earlier I/O failure.
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
366
|
export class NodeExecutionEnv {
|
|
444
367
|
constructor(options) {
|
|
445
368
|
this.activeChildPids = new Set();
|
|
@@ -447,15 +370,14 @@ export class NodeExecutionEnv {
|
|
|
447
370
|
this.shellPath = options.shellPath;
|
|
448
371
|
this.shellEnv = options.shellEnv;
|
|
449
372
|
}
|
|
450
|
-
async absolutePath(path
|
|
373
|
+
async absolutePath(path) {
|
|
451
374
|
return ok(resolvePath(this.cwd, path));
|
|
452
375
|
}
|
|
453
|
-
async joinPath(parts
|
|
376
|
+
async joinPath(parts) {
|
|
454
377
|
return ok(join(...parts));
|
|
455
378
|
}
|
|
456
|
-
async exec(command, options
|
|
457
|
-
|
|
458
|
-
if (signal?.aborted)
|
|
379
|
+
async exec(command, options) {
|
|
380
|
+
if (options?.abortSignal?.aborted)
|
|
459
381
|
return err(new ExecutionError("aborted", "aborted"));
|
|
460
382
|
const timeoutMsResult = resolveTimeoutMs(options?.timeout);
|
|
461
383
|
if (!timeoutMsResult.ok)
|
|
@@ -473,136 +395,30 @@ export class NodeExecutionEnv {
|
|
|
473
395
|
return err(new ExecutionError("spawn_error", `Working directory does not exist: ${cwd}\nCannot execute bash commands.`, cause));
|
|
474
396
|
}
|
|
475
397
|
return await new Promise((resolvePromise) => {
|
|
398
|
+
let stdout = "";
|
|
399
|
+
let stderr = "";
|
|
476
400
|
let settled = false;
|
|
477
401
|
let timedOut = false;
|
|
478
402
|
let callbackError;
|
|
479
|
-
let spillError;
|
|
480
403
|
const callbackPromises = new Set();
|
|
481
404
|
let child;
|
|
482
405
|
let timeoutId;
|
|
483
|
-
const spillPrefix = [];
|
|
484
|
-
let spillPath;
|
|
485
|
-
const spillQueue = [];
|
|
486
|
-
let spillStart;
|
|
487
|
-
let spillStream;
|
|
488
|
-
let spillBackpressured = false;
|
|
489
406
|
const onAbort = () => {
|
|
490
|
-
if (child?.pid)
|
|
407
|
+
if (child?.pid) {
|
|
491
408
|
killProcessTree(child.pid);
|
|
409
|
+
}
|
|
492
410
|
};
|
|
493
|
-
const failCallback = (error) => {
|
|
494
|
-
if (callbackError !== undefined)
|
|
495
|
-
return;
|
|
496
|
-
const cause = toError(error);
|
|
497
|
-
// The raw rejection value is the cause so observers that reject with a non-Error
|
|
498
|
-
// payload can still be identified by callers.
|
|
499
|
-
callbackError = new ExecutionError("callback_error", cause.message, error);
|
|
500
|
-
onAbort();
|
|
501
|
-
};
|
|
502
|
-
// An observer may return a promise. Track it so a rejection fails the execution with a
|
|
503
|
-
// callback error instead of escaping as an unhandled rejection.
|
|
504
|
-
const observeUpdate = options?.onUpdate;
|
|
505
|
-
const trackedOnUpdate = observeUpdate === undefined
|
|
506
|
-
? undefined
|
|
507
|
-
: (update, updateContext) => {
|
|
508
|
-
const settlement = observeUpdate(update, updateContext);
|
|
509
|
-
if (settlement === undefined || settlement === null)
|
|
510
|
-
return;
|
|
511
|
-
const tracked = Promise.resolve(settlement).then(() => undefined, (error) => {
|
|
512
|
-
failCallback(error);
|
|
513
|
-
});
|
|
514
|
-
callbackPromises.add(tracked);
|
|
515
|
-
void tracked.finally(() => callbackPromises.delete(tracked));
|
|
516
|
-
};
|
|
517
|
-
let capture;
|
|
518
|
-
try {
|
|
519
|
-
capture = new OutputCapture(options?.capture, context, {
|
|
520
|
-
onUpdate: trackedOnUpdate,
|
|
521
|
-
onError: failCallback,
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
catch (error) {
|
|
525
|
-
const cause = toError(error);
|
|
526
|
-
resolvePromise(err(new ExecutionError("unknown", cause.message, cause)));
|
|
527
|
-
return;
|
|
528
|
-
}
|
|
529
411
|
const settle = (result) => {
|
|
530
|
-
if (settled)
|
|
531
|
-
return;
|
|
532
|
-
settled = true;
|
|
533
412
|
if (timeoutId)
|
|
534
413
|
clearTimeout(timeoutId);
|
|
535
|
-
if (
|
|
536
|
-
|
|
414
|
+
if (options?.abortSignal)
|
|
415
|
+
options.abortSignal.removeEventListener("abort", onAbort);
|
|
537
416
|
if (child?.pid)
|
|
538
417
|
this.activeChildPids.delete(child.pid);
|
|
539
|
-
|
|
540
|
-
resolvePromise(result);
|
|
541
|
-
};
|
|
542
|
-
const pauseOutput = () => {
|
|
543
|
-
child?.stdout?.pause();
|
|
544
|
-
child?.stderr?.pause();
|
|
545
|
-
};
|
|
546
|
-
const resumeOutput = () => {
|
|
547
|
-
if (callbackError || spillError || timedOut || signal?.aborted || spillBackpressured)
|
|
548
|
-
return;
|
|
549
|
-
child?.stdout?.resume();
|
|
550
|
-
child?.stderr?.resume();
|
|
551
|
-
};
|
|
552
|
-
const failSpill = (error) => {
|
|
553
|
-
if (spillError !== undefined)
|
|
554
|
-
return;
|
|
555
|
-
const cause = toError(error);
|
|
556
|
-
spillError = new ExecutionError("unknown", `Failed to preserve complete shell output: ${cause.message}`, cause);
|
|
557
|
-
spillBackpressured = false;
|
|
558
|
-
onAbort();
|
|
559
|
-
};
|
|
560
|
-
const writeSpill = (chunk) => {
|
|
561
|
-
if (spillStream === undefined || chunk.length === 0)
|
|
562
|
-
return;
|
|
563
|
-
if (spillStream.write(chunk) || spillBackpressured)
|
|
564
|
-
return;
|
|
565
|
-
spillBackpressured = true;
|
|
566
|
-
pauseOutput();
|
|
567
|
-
spillStream.once("drain", () => {
|
|
568
|
-
spillBackpressured = false;
|
|
569
|
-
resumeOutput();
|
|
570
|
-
});
|
|
571
|
-
};
|
|
572
|
-
const startSpill = (chunk) => {
|
|
573
|
-
if (spillStream !== undefined) {
|
|
574
|
-
writeSpill(chunk);
|
|
575
|
-
return;
|
|
576
|
-
}
|
|
577
|
-
spillQueue.push(chunk);
|
|
578
|
-
if (spillStart !== undefined)
|
|
579
|
-
return;
|
|
580
|
-
pauseOutput();
|
|
581
|
-
spillStart = (async () => {
|
|
582
|
-
const created = await this.createTempFile({ prefix: "pi-output-", suffix: ".log" }, context);
|
|
583
|
-
if (!created.ok)
|
|
584
|
-
throw created.error;
|
|
585
|
-
spillPath = created.value;
|
|
586
|
-
capture.setSpillPath(spillPath);
|
|
587
|
-
spillStream = createWriteStream(spillPath, { flags: "a", highWaterMark: SPILL_HIGH_WATER_MARK });
|
|
588
|
-
spillStream.on("error", failSpill);
|
|
589
|
-
for (const queued of spillQueue)
|
|
590
|
-
writeSpill(queued);
|
|
591
|
-
spillQueue.length = 0;
|
|
592
|
-
})()
|
|
593
|
-
.catch(failSpill)
|
|
594
|
-
.finally(resumeOutput);
|
|
595
|
-
};
|
|
596
|
-
const finishSpill = async () => {
|
|
597
|
-
await spillStart;
|
|
598
|
-
const stream = spillStream;
|
|
599
|
-
if (stream === undefined || spillError !== undefined || stream.destroyed)
|
|
418
|
+
if (settled)
|
|
600
419
|
return;
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
stream.once("finish", resolveFinish);
|
|
604
|
-
stream.end();
|
|
605
|
-
});
|
|
420
|
+
settled = true;
|
|
421
|
+
resolvePromise(result);
|
|
606
422
|
};
|
|
607
423
|
try {
|
|
608
424
|
const commandFromStdin = shellConfig.value.commandTransport === "stdin";
|
|
@@ -626,76 +442,65 @@ export class NodeExecutionEnv {
|
|
|
626
442
|
return;
|
|
627
443
|
}
|
|
628
444
|
timeoutId =
|
|
629
|
-
timeoutMs
|
|
630
|
-
?
|
|
631
|
-
: setTimeout(() => {
|
|
445
|
+
timeoutMs !== undefined
|
|
446
|
+
? setTimeout(() => {
|
|
632
447
|
timedOut = true;
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
448
|
+
if (child?.pid) {
|
|
449
|
+
killProcessTree(child.pid);
|
|
450
|
+
}
|
|
451
|
+
}, timeoutMs)
|
|
452
|
+
: undefined;
|
|
453
|
+
if (options?.abortSignal) {
|
|
454
|
+
if (options.abortSignal.aborted) {
|
|
637
455
|
onAbort();
|
|
638
|
-
else
|
|
639
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
640
|
-
}
|
|
641
|
-
const feed = (chunk) => {
|
|
642
|
-
try {
|
|
643
|
-
const wasTruncated = capture.truncated;
|
|
644
|
-
capture.push(chunk);
|
|
645
|
-
if (!options?.capture?.spill || chunk.length === 0)
|
|
646
|
-
return;
|
|
647
|
-
if (spillPath !== undefined || wasTruncated) {
|
|
648
|
-
startSpill(chunk);
|
|
649
|
-
}
|
|
650
|
-
else if (capture.truncated) {
|
|
651
|
-
for (const prefix of spillPrefix)
|
|
652
|
-
startSpill(prefix);
|
|
653
|
-
spillPrefix.length = 0;
|
|
654
|
-
startSpill(chunk);
|
|
655
|
-
}
|
|
656
|
-
else {
|
|
657
|
-
spillPrefix.push(chunk);
|
|
658
|
-
}
|
|
659
456
|
}
|
|
660
|
-
|
|
661
|
-
|
|
457
|
+
else {
|
|
458
|
+
options.abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
662
459
|
}
|
|
460
|
+
}
|
|
461
|
+
child.stdout?.setEncoding("utf8");
|
|
462
|
+
child.stderr?.setEncoding("utf8");
|
|
463
|
+
const handleChunk = (chunk, callback, append) => {
|
|
464
|
+
append(chunk);
|
|
465
|
+
if (callback === undefined)
|
|
466
|
+
return;
|
|
467
|
+
const callbackPromise = Promise.resolve()
|
|
468
|
+
.then(() => callback(chunk))
|
|
469
|
+
.catch((error) => {
|
|
470
|
+
if (!callbackError) {
|
|
471
|
+
const cause = toError(error);
|
|
472
|
+
callbackError = new ExecutionError("callback_error", cause.message, error);
|
|
473
|
+
onAbort();
|
|
474
|
+
}
|
|
475
|
+
throw error;
|
|
476
|
+
});
|
|
477
|
+
callbackPromises.add(callbackPromise);
|
|
478
|
+
void callbackPromise.then(() => callbackPromises.delete(callbackPromise), () => callbackPromises.delete(callbackPromise));
|
|
663
479
|
};
|
|
664
|
-
child.stdout?.on("data",
|
|
665
|
-
child.stderr?.on("data",
|
|
666
|
-
void waitForChildProcess(child
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
480
|
+
child.stdout?.on("data", (chunk) => handleChunk(chunk, options?.onStdout, (value) => (stdout += value)));
|
|
481
|
+
child.stderr?.on("data", (chunk) => handleChunk(chunk, options?.onStderr, (value) => (stderr += value)));
|
|
482
|
+
void waitForChildProcess(child).then(async (code) => {
|
|
483
|
+
// Normal command completion must not be held hostage by an observer that
|
|
484
|
+
// never settles. Abort completion uses the shorter cancellation path above;
|
|
485
|
+
// this generous bound preserves slow, legitimate callbacks without hanging
|
|
486
|
+
// the execution forever.
|
|
487
|
+
const callbacksSettled = Promise.allSettled([...callbackPromises]);
|
|
488
|
+
let callbackTimeout;
|
|
489
|
+
const callbackBound = new Promise((resolve) => {
|
|
490
|
+
callbackTimeout = setTimeout(() => resolve(false), NORMAL_CALLBACK_SETTLEMENT_TIMEOUT_MS);
|
|
491
|
+
callbackTimeout.unref?.();
|
|
492
|
+
});
|
|
670
493
|
try {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
failCallback(error);
|
|
676
|
-
}
|
|
677
|
-
// Normal command completion must not be held hostage by an observer that never
|
|
678
|
-
// settles. Abort completion uses the shorter cancellation path above; this generous
|
|
679
|
-
// bound preserves slow, legitimate observers without hanging the execution forever.
|
|
680
|
-
if (callbackPromises.size > 0) {
|
|
681
|
-
const callbacksSettled = Promise.allSettled([...callbackPromises]);
|
|
682
|
-
let callbackTimeout;
|
|
683
|
-
const callbackBound = new Promise((resolve) => {
|
|
684
|
-
callbackTimeout = setTimeout(() => resolve(false), NORMAL_CALLBACK_SETTLEMENT_TIMEOUT_MS);
|
|
685
|
-
callbackTimeout.unref?.();
|
|
686
|
-
});
|
|
687
|
-
try {
|
|
688
|
-
const observersSettled = await Promise.race([callbacksSettled.then(() => true), callbackBound]);
|
|
689
|
-
if (!observersSettled && !callbackError) {
|
|
690
|
-
settle(err(new ExecutionError("callback_error", `Output callback did not settle within ${NORMAL_CALLBACK_SETTLEMENT_TIMEOUT_MS}ms`)));
|
|
691
|
-
return;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
finally {
|
|
695
|
-
if (callbackTimeout)
|
|
696
|
-
clearTimeout(callbackTimeout);
|
|
494
|
+
const settled = await Promise.race([callbacksSettled.then(() => true), callbackBound]);
|
|
495
|
+
if (!settled && !callbackError) {
|
|
496
|
+
settle(err(new ExecutionError("callback_error", "Output callback did not settle within 5000ms")));
|
|
497
|
+
return;
|
|
697
498
|
}
|
|
698
499
|
}
|
|
500
|
+
finally {
|
|
501
|
+
if (callbackTimeout)
|
|
502
|
+
clearTimeout(callbackTimeout);
|
|
503
|
+
}
|
|
699
504
|
if (callbackError) {
|
|
700
505
|
settle(err(callbackError));
|
|
701
506
|
return;
|
|
@@ -704,135 +509,104 @@ export class NodeExecutionEnv {
|
|
|
704
509
|
settle(err(new ExecutionError("timeout", `timeout:${options?.timeout}`)));
|
|
705
510
|
return;
|
|
706
511
|
}
|
|
707
|
-
if (
|
|
512
|
+
if (options?.abortSignal?.aborted) {
|
|
708
513
|
settle(err(new ExecutionError("aborted", "aborted")));
|
|
709
514
|
return;
|
|
710
515
|
}
|
|
711
|
-
|
|
712
|
-
settle(err(spillError));
|
|
713
|
-
return;
|
|
714
|
-
}
|
|
715
|
-
const output = capture.snapshot();
|
|
716
|
-
// A process killed by a signal (e.g. OOM killer) has no exit code; map it
|
|
717
|
-
// to the conventional 128 + signal number so callers do not mistake it
|
|
718
|
-
// for a successful exit.
|
|
719
|
-
const exitCode = code ?? (exitSignal ? 128 + (osConstants.signals[exitSignal] ?? 0) : 1);
|
|
720
|
-
settle(ok({
|
|
721
|
-
exitCode,
|
|
722
|
-
truncation: output.truncation,
|
|
723
|
-
...(output.spillPath === undefined ? {} : { spillPath: output.spillPath }),
|
|
724
|
-
...(output.lastLineBytes === undefined ? {} : { lastLineBytes: output.lastLineBytes }),
|
|
725
|
-
}));
|
|
516
|
+
settle(ok({ stdout, stderr, exitCode: code ?? 0 }));
|
|
726
517
|
}, (error) => settle(err(new ExecutionError("spawn_error", error.message, error))));
|
|
727
518
|
});
|
|
728
519
|
}
|
|
729
|
-
async
|
|
520
|
+
async readTextFile(path, abortSignal) {
|
|
730
521
|
const resolved = resolvePath(this.cwd, path);
|
|
731
|
-
const aborted = abortResult(
|
|
522
|
+
const aborted = abortResult(abortSignal, resolved);
|
|
732
523
|
if (aborted)
|
|
733
524
|
return aborted;
|
|
734
525
|
try {
|
|
735
|
-
|
|
736
|
-
const afterOpenAbort = abortResult(context.abortSignal, resolved);
|
|
737
|
-
if (afterOpenAbort) {
|
|
738
|
-
await file.close().catch(() => undefined);
|
|
739
|
-
return afterOpenAbort;
|
|
740
|
-
}
|
|
741
|
-
return ok(new NodeTextLineReader(file, resolved));
|
|
526
|
+
return ok(await readFile(resolved, { encoding: "utf8", signal: abortSignal }));
|
|
742
527
|
}
|
|
743
528
|
catch (error) {
|
|
744
529
|
return err(toFileError(error, resolved));
|
|
745
530
|
}
|
|
746
531
|
}
|
|
747
|
-
async
|
|
532
|
+
async readTextLines(path, options) {
|
|
748
533
|
const resolved = resolvePath(this.cwd, path);
|
|
749
|
-
const
|
|
750
|
-
const aborted = abortResult(signal, resolved);
|
|
534
|
+
const aborted = abortResult(options?.abortSignal, resolved);
|
|
751
535
|
if (aborted)
|
|
752
536
|
return aborted;
|
|
753
|
-
try {
|
|
754
|
-
return ok(await readFile(resolved, { encoding: "utf8", signal }));
|
|
755
|
-
}
|
|
756
|
-
catch (error) {
|
|
757
|
-
return err(toFileError(error, resolved));
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
async readTextLines(path, options, context) {
|
|
761
537
|
if (options?.maxLines !== undefined && options.maxLines <= 0)
|
|
762
538
|
return ok([]);
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
return opened;
|
|
766
|
-
const lines = [];
|
|
539
|
+
let stream;
|
|
540
|
+
let lineReader;
|
|
767
541
|
try {
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
542
|
+
stream = createReadStream(resolved, { encoding: "utf8", signal: options?.abortSignal });
|
|
543
|
+
lineReader = createInterface({ input: stream, crlfDelay: Infinity });
|
|
544
|
+
const lines = [];
|
|
545
|
+
for await (const line of lineReader) {
|
|
546
|
+
const loopAbort = abortResult(options?.abortSignal, resolved);
|
|
547
|
+
if (loopAbort)
|
|
548
|
+
return loopAbort;
|
|
549
|
+
lines.push(line);
|
|
550
|
+
if (options?.maxLines !== undefined && lines.length >= options.maxLines)
|
|
773
551
|
break;
|
|
774
|
-
lines.push(line.value.text);
|
|
775
552
|
}
|
|
553
|
+
const afterReadAbort = abortResult(options?.abortSignal, resolved);
|
|
554
|
+
if (afterReadAbort)
|
|
555
|
+
return afterReadAbort;
|
|
776
556
|
return ok(lines);
|
|
777
557
|
}
|
|
558
|
+
catch (error) {
|
|
559
|
+
return err(toFileError(error, resolved));
|
|
560
|
+
}
|
|
778
561
|
finally {
|
|
779
|
-
|
|
562
|
+
lineReader?.close();
|
|
563
|
+
stream?.destroy();
|
|
780
564
|
}
|
|
781
565
|
}
|
|
782
|
-
async readBinaryFile(path,
|
|
566
|
+
async readBinaryFile(path, abortSignal) {
|
|
783
567
|
const resolved = resolvePath(this.cwd, path);
|
|
784
|
-
const
|
|
785
|
-
const aborted = abortResult(signal, resolved);
|
|
568
|
+
const aborted = abortResult(abortSignal, resolved);
|
|
786
569
|
if (aborted)
|
|
787
570
|
return aborted;
|
|
788
571
|
try {
|
|
789
|
-
return ok(await readFile(resolved, { signal }));
|
|
572
|
+
return ok(await readFile(resolved, { signal: abortSignal }));
|
|
790
573
|
}
|
|
791
574
|
catch (error) {
|
|
792
575
|
return err(toFileError(error, resolved));
|
|
793
576
|
}
|
|
794
577
|
}
|
|
795
|
-
async writeFile(path, content,
|
|
578
|
+
async writeFile(path, content, abortSignal) {
|
|
796
579
|
const resolved = resolvePath(this.cwd, path);
|
|
797
|
-
const
|
|
798
|
-
const aborted = abortResult(signal, resolved);
|
|
580
|
+
const aborted = abortResult(abortSignal, resolved);
|
|
799
581
|
if (aborted)
|
|
800
582
|
return aborted;
|
|
801
583
|
try {
|
|
802
584
|
await mkdir(resolve(resolved, ".."), { recursive: true });
|
|
803
|
-
const afterMkdirAbort = abortResult(
|
|
585
|
+
const afterMkdirAbort = abortResult(abortSignal, resolved);
|
|
804
586
|
if (afterMkdirAbort)
|
|
805
587
|
return afterMkdirAbort;
|
|
806
|
-
await writeFile(resolved, content, { signal });
|
|
588
|
+
await writeFile(resolved, content, { signal: abortSignal });
|
|
807
589
|
return ok(undefined);
|
|
808
590
|
}
|
|
809
591
|
catch (error) {
|
|
810
592
|
return err(toFileError(error, resolved));
|
|
811
593
|
}
|
|
812
594
|
}
|
|
813
|
-
async appendFile(path, content
|
|
595
|
+
async appendFile(path, content) {
|
|
814
596
|
const resolved = resolvePath(this.cwd, path);
|
|
815
|
-
const signal = context.abortSignal;
|
|
816
|
-
const aborted = abortResult(signal, resolved);
|
|
817
|
-
if (aborted)
|
|
818
|
-
return aborted;
|
|
819
597
|
try {
|
|
820
598
|
await mkdir(resolve(resolved, ".."), { recursive: true });
|
|
821
|
-
const afterMkdirAbort = abortResult(signal, resolved);
|
|
822
|
-
if (afterMkdirAbort)
|
|
823
|
-
return afterMkdirAbort;
|
|
824
599
|
await appendFile(resolved, content);
|
|
825
|
-
|
|
826
|
-
return afterAppendAbort ?? ok(undefined);
|
|
600
|
+
return ok(undefined);
|
|
827
601
|
}
|
|
828
602
|
catch (error) {
|
|
829
603
|
return err(toFileError(error, resolved));
|
|
830
604
|
}
|
|
831
605
|
}
|
|
832
|
-
async renameFile(sourcePath, destinationPath,
|
|
606
|
+
async renameFile(sourcePath, destinationPath, abortSignal) {
|
|
833
607
|
const source = resolvePath(this.cwd, sourcePath);
|
|
834
608
|
const destination = resolvePath(this.cwd, destinationPath);
|
|
835
|
-
const aborted = abortResult(
|
|
609
|
+
const aborted = abortResult(abortSignal, destination);
|
|
836
610
|
if (aborted)
|
|
837
611
|
return aborted;
|
|
838
612
|
try {
|
|
@@ -843,11 +617,8 @@ export class NodeExecutionEnv {
|
|
|
843
617
|
return err(toFileError(error, source));
|
|
844
618
|
}
|
|
845
619
|
}
|
|
846
|
-
async fileInfo(path
|
|
620
|
+
async fileInfo(path) {
|
|
847
621
|
const resolved = resolvePath(this.cwd, path);
|
|
848
|
-
const aborted = abortResult(context.abortSignal, resolved);
|
|
849
|
-
if (aborted)
|
|
850
|
-
return aborted;
|
|
851
622
|
try {
|
|
852
623
|
return fileInfoFromStats(resolved, await lstat(resolved));
|
|
853
624
|
}
|
|
@@ -855,17 +626,16 @@ export class NodeExecutionEnv {
|
|
|
855
626
|
return err(toFileError(error, resolved));
|
|
856
627
|
}
|
|
857
628
|
}
|
|
858
|
-
async listDir(path,
|
|
629
|
+
async listDir(path, abortSignal) {
|
|
859
630
|
const resolved = resolvePath(this.cwd, path);
|
|
860
|
-
const
|
|
861
|
-
const aborted = abortResult(signal, resolved);
|
|
631
|
+
const aborted = abortResult(abortSignal, resolved);
|
|
862
632
|
if (aborted)
|
|
863
633
|
return aborted;
|
|
864
634
|
try {
|
|
865
635
|
const entries = await readdir(resolved, { withFileTypes: true });
|
|
866
636
|
const infos = [];
|
|
867
637
|
for (const entry of entries) {
|
|
868
|
-
const loopAbort = abortResult(
|
|
638
|
+
const loopAbort = abortResult(abortSignal, resolved);
|
|
869
639
|
if (loopAbort)
|
|
870
640
|
return loopAbort;
|
|
871
641
|
const entryPath = resolve(resolved, entry.name);
|
|
@@ -884,11 +654,8 @@ export class NodeExecutionEnv {
|
|
|
884
654
|
return err(toFileError(error, resolved));
|
|
885
655
|
}
|
|
886
656
|
}
|
|
887
|
-
async canonicalPath(path
|
|
657
|
+
async canonicalPath(path) {
|
|
888
658
|
const resolved = resolvePath(this.cwd, path);
|
|
889
|
-
const aborted = abortResult(context.abortSignal, resolved);
|
|
890
|
-
if (aborted)
|
|
891
|
-
return aborted;
|
|
892
659
|
try {
|
|
893
660
|
return ok(await realpath(resolved));
|
|
894
661
|
}
|
|
@@ -896,19 +663,16 @@ export class NodeExecutionEnv {
|
|
|
896
663
|
return err(toFileError(error, resolved));
|
|
897
664
|
}
|
|
898
665
|
}
|
|
899
|
-
async exists(path
|
|
900
|
-
const result = await this.fileInfo(path
|
|
666
|
+
async exists(path) {
|
|
667
|
+
const result = await this.fileInfo(path);
|
|
901
668
|
if (result.ok)
|
|
902
669
|
return ok(true);
|
|
903
670
|
if (result.error.code === "not_found")
|
|
904
671
|
return ok(false);
|
|
905
672
|
return err(result.error);
|
|
906
673
|
}
|
|
907
|
-
async createDir(path, options
|
|
674
|
+
async createDir(path, options) {
|
|
908
675
|
const resolved = resolvePath(this.cwd, path);
|
|
909
|
-
const aborted = abortResult(context.abortSignal, resolved);
|
|
910
|
-
if (aborted)
|
|
911
|
-
return aborted;
|
|
912
676
|
try {
|
|
913
677
|
await mkdir(resolved, { recursive: options?.recursive ?? true });
|
|
914
678
|
return ok(undefined);
|
|
@@ -917,11 +681,8 @@ export class NodeExecutionEnv {
|
|
|
917
681
|
return err(toFileError(error, resolved));
|
|
918
682
|
}
|
|
919
683
|
}
|
|
920
|
-
async remove(path, options
|
|
684
|
+
async remove(path, options) {
|
|
921
685
|
const resolved = resolvePath(this.cwd, path);
|
|
922
|
-
const aborted = abortResult(context.abortSignal, resolved);
|
|
923
|
-
if (aborted)
|
|
924
|
-
return aborted;
|
|
925
686
|
try {
|
|
926
687
|
await rm(resolved, { recursive: options?.recursive ?? false, force: options?.force ?? false });
|
|
927
688
|
return ok(undefined);
|
|
@@ -930,20 +691,16 @@ export class NodeExecutionEnv {
|
|
|
930
691
|
return err(toFileError(error, resolved));
|
|
931
692
|
}
|
|
932
693
|
}
|
|
933
|
-
async createTempDir(prefix
|
|
934
|
-
const aborted = abortResult(context.abortSignal);
|
|
935
|
-
if (aborted)
|
|
936
|
-
return aborted;
|
|
694
|
+
async createTempDir(prefix = "tmp-") {
|
|
937
695
|
try {
|
|
938
|
-
prefix ??= "tmp-";
|
|
939
696
|
return ok(await mkdtemp(join(tmpdir(), prefix)));
|
|
940
697
|
}
|
|
941
698
|
catch (error) {
|
|
942
699
|
return err(toFileError(error));
|
|
943
700
|
}
|
|
944
701
|
}
|
|
945
|
-
async createTempFile(options
|
|
946
|
-
const dir = await this.createTempDir("tmp-"
|
|
702
|
+
async createTempFile(options) {
|
|
703
|
+
const dir = await this.createTempDir("tmp-");
|
|
947
704
|
if (!dir.ok)
|
|
948
705
|
return dir;
|
|
949
706
|
const filePath = join(dir.value, `${options?.prefix ?? ""}${randomUUID()}${options?.suffix ?? ""}`);
|
|
@@ -955,7 +712,7 @@ export class NodeExecutionEnv {
|
|
|
955
712
|
return err(toFileError(error, filePath));
|
|
956
713
|
}
|
|
957
714
|
}
|
|
958
|
-
async cleanup(
|
|
715
|
+
async cleanup() {
|
|
959
716
|
for (const pid of this.activeChildPids)
|
|
960
717
|
killProcessTree(pid);
|
|
961
718
|
this.activeChildPids.clear();
|