@draht/agent-core 2026.7.30 → 2026.10.4-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-loop.d.ts +27 -2
- package/dist/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +181 -63
- package/dist/agent-loop.js.map +1 -1
- package/dist/agent.d.ts +14 -4
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +68 -19
- package/dist/agent.js.map +1 -1
- package/dist/harness/agent-harness.d.ts +713 -91
- package/dist/harness/agent-harness.d.ts.map +1 -1
- package/dist/harness/agent-harness.js +5 -950
- package/dist/harness/agent-harness.js.map +1 -1
- package/dist/harness/compaction/branch-summarization.d.ts +23 -10
- package/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/harness/compaction/branch-summarization.js +39 -36
- package/dist/harness/compaction/branch-summarization.js.map +1 -1
- package/dist/harness/compaction/compaction.d.ts +37 -18
- package/dist/harness/compaction/compaction.d.ts.map +1 -1
- package/dist/harness/compaction/compaction.js +74 -97
- package/dist/harness/compaction/compaction.js.map +1 -1
- package/dist/harness/config.d.ts +9 -0
- package/dist/harness/config.d.ts.map +1 -0
- package/dist/harness/config.js +35 -0
- package/dist/harness/config.js.map +1 -0
- package/dist/harness/context.d.ts +9 -0
- package/dist/harness/context.d.ts.map +1 -0
- package/dist/harness/context.js +13 -0
- package/dist/harness/context.js.map +1 -0
- package/dist/harness/env/nodejs.d.ts +25 -27
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +355 -110
- package/dist/harness/env/nodejs.js.map +1 -1
- package/dist/harness/events.d.ts +24 -0
- package/dist/harness/events.d.ts.map +1 -0
- package/dist/harness/events.js +233 -0
- package/dist/harness/events.js.map +1 -0
- package/dist/harness/execution/assistant.d.ts +42 -0
- package/dist/harness/execution/assistant.d.ts.map +1 -0
- package/dist/harness/execution/assistant.js +82 -0
- package/dist/harness/execution/assistant.js.map +1 -0
- package/dist/harness/execution/effect-gate.d.ts +22 -0
- package/dist/harness/execution/effect-gate.d.ts.map +1 -0
- package/dist/harness/execution/effect-gate.js +49 -0
- package/dist/harness/execution/effect-gate.js.map +1 -0
- package/dist/harness/execution/tools.d.ts +67 -0
- package/dist/harness/execution/tools.d.ts.map +1 -0
- package/dist/harness/execution/tools.js +119 -0
- package/dist/harness/execution/tools.js.map +1 -0
- package/dist/harness/hooks.d.ts +38 -0
- package/dist/harness/hooks.d.ts.map +1 -0
- package/dist/harness/hooks.js +406 -0
- package/dist/harness/hooks.js.map +1 -0
- package/dist/harness/messages.d.ts +4 -4
- package/dist/harness/messages.d.ts.map +1 -1
- package/dist/harness/messages.js +4 -3
- package/dist/harness/messages.js.map +1 -1
- package/dist/harness/pico3/bash.d.ts +10 -0
- package/dist/harness/pico3/bash.d.ts.map +1 -0
- package/dist/harness/pico3/bash.js +25 -0
- package/dist/harness/pico3/bash.js.map +1 -0
- package/dist/harness/pico3/bounded.d.ts +21 -0
- package/dist/harness/pico3/bounded.d.ts.map +1 -0
- package/dist/harness/pico3/bounded.js +98 -0
- package/dist/harness/pico3/bounded.js.map +1 -0
- package/dist/harness/pico3/chord.d.ts +41 -0
- package/dist/harness/pico3/chord.d.ts.map +1 -0
- package/dist/harness/pico3/chord.js +147 -0
- package/dist/harness/pico3/chord.js.map +1 -0
- package/dist/harness/pico3/context.d.ts +16 -0
- package/dist/harness/pico3/context.d.ts.map +1 -0
- package/dist/harness/pico3/context.js +88 -0
- package/dist/harness/pico3/context.js.map +1 -0
- package/dist/harness/pico3/harness.d.ts +198 -0
- package/dist/harness/pico3/harness.d.ts.map +1 -0
- package/dist/harness/pico3/harness.js +654 -0
- package/dist/harness/pico3/harness.js.map +1 -0
- package/dist/harness/pico3/hooks.d.ts +10 -0
- package/dist/harness/pico3/hooks.d.ts.map +1 -0
- package/dist/harness/pico3/hooks.js +33 -0
- package/dist/harness/pico3/hooks.js.map +1 -0
- package/dist/harness/pico3/index.d.ts +19 -0
- package/dist/harness/pico3/index.d.ts.map +1 -0
- package/dist/harness/pico3/index.js +15 -0
- package/dist/harness/pico3/index.js.map +1 -0
- package/dist/harness/pico3/jsonl.d.ts +58 -0
- package/dist/harness/pico3/jsonl.d.ts.map +1 -0
- package/dist/harness/pico3/jsonl.js +325 -0
- package/dist/harness/pico3/jsonl.js.map +1 -0
- package/dist/harness/pico3/kinds/collapse.d.ts +49 -0
- package/dist/harness/pico3/kinds/collapse.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/collapse.js +191 -0
- package/dist/harness/pico3/kinds/collapse.js.map +1 -0
- package/dist/harness/pico3/kinds/entries.d.ts +78 -0
- package/dist/harness/pico3/kinds/entries.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/entries.js +13 -0
- package/dist/harness/pico3/kinds/entries.js.map +1 -0
- package/dist/harness/pico3/kinds/frames.d.ts +9 -0
- package/dist/harness/pico3/kinds/frames.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/frames.js +75 -0
- package/dist/harness/pico3/kinds/frames.js.map +1 -0
- package/dist/harness/pico3/kinds/generation.d.ts +94 -0
- package/dist/harness/pico3/kinds/generation.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/generation.js +504 -0
- package/dist/harness/pico3/kinds/generation.js.map +1 -0
- package/dist/harness/pico3/kinds/job.d.ts +44 -0
- package/dist/harness/pico3/kinds/job.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/job.js +143 -0
- package/dist/harness/pico3/kinds/job.js.map +1 -0
- package/dist/harness/pico3/kinds/plugin.d.ts +15 -0
- package/dist/harness/pico3/kinds/plugin.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/plugin.js +35 -0
- package/dist/harness/pico3/kinds/plugin.js.map +1 -0
- package/dist/harness/pico3/kinds/post-tools.d.ts +22 -0
- package/dist/harness/pico3/kinds/post-tools.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/post-tools.js +145 -0
- package/dist/harness/pico3/kinds/post-tools.js.map +1 -0
- package/dist/harness/pico3/kinds/task-api.d.ts +3 -0
- package/dist/harness/pico3/kinds/task-api.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/task-api.js +45 -0
- package/dist/harness/pico3/kinds/task-api.js.map +1 -0
- package/dist/harness/pico3/kinds/tool.d.ts +43 -0
- package/dist/harness/pico3/kinds/tool.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/tool.js +373 -0
- package/dist/harness/pico3/kinds/tool.js.map +1 -0
- package/dist/harness/pico3/legacy-tracker.d.ts +11 -0
- package/dist/harness/pico3/legacy-tracker.d.ts.map +1 -0
- package/dist/harness/pico3/legacy-tracker.js +41 -0
- package/dist/harness/pico3/legacy-tracker.js.map +1 -0
- package/dist/harness/pico3/membrane.d.ts +23 -0
- package/dist/harness/pico3/membrane.d.ts.map +1 -0
- package/dist/harness/pico3/membrane.js +141 -0
- package/dist/harness/pico3/membrane.js.map +1 -0
- package/dist/harness/pico3/memory.d.ts +53 -0
- package/dist/harness/pico3/memory.d.ts.map +1 -0
- package/dist/harness/pico3/memory.js +264 -0
- package/dist/harness/pico3/memory.js.map +1 -0
- package/dist/harness/pico3/scheduler.d.ts +49 -0
- package/dist/harness/pico3/scheduler.d.ts.map +1 -0
- package/dist/harness/pico3/scheduler.js +438 -0
- package/dist/harness/pico3/scheduler.js.map +1 -0
- package/dist/harness/pico3/session.d.ts +264 -0
- package/dist/harness/pico3/session.d.ts.map +1 -0
- package/dist/harness/pico3/session.js +1348 -0
- package/dist/harness/pico3/session.js.map +1 -0
- package/dist/harness/pico3/system.d.ts +126 -0
- package/dist/harness/pico3/system.d.ts.map +1 -0
- package/dist/harness/pico3/system.js +244 -0
- package/dist/harness/pico3/system.js.map +1 -0
- package/dist/harness/pico3/types.d.ts +973 -0
- package/dist/harness/pico3/types.d.ts.map +1 -0
- package/dist/harness/pico3/types.js +106 -0
- package/dist/harness/pico3/types.js.map +1 -0
- package/dist/harness/pico3/view.d.ts +34 -0
- package/dist/harness/pico3/view.d.ts.map +1 -0
- package/dist/harness/pico3/view.js +411 -0
- package/dist/harness/pico3/view.js.map +1 -0
- package/dist/harness/prompt-templates.d.ts +3 -2
- package/dist/harness/prompt-templates.d.ts.map +1 -1
- package/dist/harness/prompt-templates.js +18 -23
- package/dist/harness/prompt-templates.js.map +1 -1
- package/dist/harness/result.d.ts +133 -0
- package/dist/harness/result.d.ts.map +1 -0
- package/dist/harness/result.js +81 -0
- package/dist/harness/result.js.map +1 -0
- package/dist/harness/runtime/drive/boundary.d.ts +28 -0
- package/dist/harness/runtime/drive/boundary.d.ts.map +1 -0
- package/dist/harness/runtime/drive/boundary.js +173 -0
- package/dist/harness/runtime/drive/boundary.js.map +1 -0
- package/dist/harness/runtime/drive/checkpoint.d.ts +8 -0
- package/dist/harness/runtime/drive/checkpoint.d.ts.map +1 -0
- package/dist/harness/runtime/drive/checkpoint.js +133 -0
- package/dist/harness/runtime/drive/checkpoint.js.map +1 -0
- package/dist/harness/runtime/drive/deferred.d.ts +15 -0
- package/dist/harness/runtime/drive/deferred.d.ts.map +1 -0
- package/dist/harness/runtime/drive/deferred.js +179 -0
- package/dist/harness/runtime/drive/deferred.js.map +1 -0
- package/dist/harness/runtime/drive/generation.d.ts +8 -0
- package/dist/harness/runtime/drive/generation.d.ts.map +1 -0
- package/dist/harness/runtime/drive/generation.js +205 -0
- package/dist/harness/runtime/drive/generation.js.map +1 -0
- package/dist/harness/runtime/drive/reconcile.d.ts +5 -0
- package/dist/harness/runtime/drive/reconcile.d.ts.map +1 -0
- package/dist/harness/runtime/drive/reconcile.js +140 -0
- package/dist/harness/runtime/drive/reconcile.js.map +1 -0
- package/dist/harness/runtime/drive/recovery.d.ts +8 -0
- package/dist/harness/runtime/drive/recovery.d.ts.map +1 -0
- package/dist/harness/runtime/drive/recovery.js +85 -0
- package/dist/harness/runtime/drive/recovery.js.map +1 -0
- package/dist/harness/runtime/drive/response.d.ts +23 -0
- package/dist/harness/runtime/drive/response.d.ts.map +1 -0
- package/dist/harness/runtime/drive/response.js +394 -0
- package/dist/harness/runtime/drive/response.js.map +1 -0
- package/dist/harness/runtime/drive/retry.d.ts +4 -0
- package/dist/harness/runtime/drive/retry.d.ts.map +1 -0
- package/dist/harness/runtime/drive/retry.js +34 -0
- package/dist/harness/runtime/drive/retry.js.map +1 -0
- package/dist/harness/runtime/drive/structural.d.ts +32 -0
- package/dist/harness/runtime/drive/structural.d.ts.map +1 -0
- package/dist/harness/runtime/drive/structural.js +929 -0
- package/dist/harness/runtime/drive/structural.js.map +1 -0
- package/dist/harness/runtime/drive/terminal.d.ts +7 -0
- package/dist/harness/runtime/drive/terminal.d.ts.map +1 -0
- package/dist/harness/runtime/drive/terminal.js +49 -0
- package/dist/harness/runtime/drive/terminal.js.map +1 -0
- package/dist/harness/runtime/drive/tool-placement.d.ts +14 -0
- package/dist/harness/runtime/drive/tool-placement.d.ts.map +1 -0
- package/dist/harness/runtime/drive/tool-placement.js +219 -0
- package/dist/harness/runtime/drive/tool-placement.js.map +1 -0
- package/dist/harness/runtime/drive/tools.d.ts +6 -0
- package/dist/harness/runtime/drive/tools.d.ts.map +1 -0
- package/dist/harness/runtime/drive/tools.js +449 -0
- package/dist/harness/runtime/drive/tools.js.map +1 -0
- package/dist/harness/runtime/drive.d.ts +6 -0
- package/dist/harness/runtime/drive.d.ts.map +1 -0
- package/dist/harness/runtime/drive.js +93 -0
- package/dist/harness/runtime/drive.js.map +1 -0
- package/dist/harness/runtime/harness.d.ts +59 -0
- package/dist/harness/runtime/harness.d.ts.map +1 -0
- package/dist/harness/runtime/harness.js +311 -0
- package/dist/harness/runtime/harness.js.map +1 -0
- package/dist/harness/runtime/index.d.ts +2 -0
- package/dist/harness/runtime/index.d.ts.map +1 -0
- package/dist/harness/runtime/index.js +2 -0
- package/dist/harness/runtime/index.js.map +1 -0
- package/dist/harness/runtime/lane.d.ts +118 -0
- package/dist/harness/runtime/lane.d.ts.map +1 -0
- package/dist/harness/runtime/lane.js +1575 -0
- package/dist/harness/runtime/lane.js.map +1 -0
- package/dist/harness/runtime/progress.d.ts +15 -0
- package/dist/harness/runtime/progress.d.ts.map +1 -0
- package/dist/harness/runtime/progress.js +66 -0
- package/dist/harness/runtime/progress.js.map +1 -0
- package/dist/harness/runtime/reducer.d.ts +5 -0
- package/dist/harness/runtime/reducer.d.ts.map +1 -0
- package/dist/harness/runtime/reducer.js +240 -0
- package/dist/harness/runtime/reducer.js.map +1 -0
- package/dist/harness/runtime/restore.d.ts +24 -0
- package/dist/harness/runtime/restore.d.ts.map +1 -0
- package/dist/harness/runtime/restore.js +117 -0
- package/dist/harness/runtime/restore.js.map +1 -0
- package/dist/harness/runtime/transcript.d.ts +21 -0
- package/dist/harness/runtime/transcript.d.ts.map +1 -0
- package/dist/harness/runtime/transcript.js +72 -0
- package/dist/harness/runtime/transcript.js.map +1 -0
- package/dist/harness/runtime/types.d.ts +105 -0
- package/dist/harness/runtime/types.d.ts.map +1 -0
- package/dist/harness/runtime/types.js +61 -0
- package/dist/harness/runtime/types.js.map +1 -0
- package/dist/harness/session/commit.d.ts +53 -0
- package/dist/harness/session/commit.d.ts.map +1 -0
- package/dist/harness/session/commit.js +57 -0
- package/dist/harness/session/commit.js.map +1 -0
- package/dist/harness/session/context.d.ts +10 -0
- package/dist/harness/session/context.d.ts.map +1 -0
- package/dist/harness/session/context.js +49 -0
- package/dist/harness/session/context.js.map +1 -0
- package/dist/harness/session/fork-policy.d.ts +21 -0
- package/dist/harness/session/fork-policy.d.ts.map +1 -0
- package/dist/harness/session/fork-policy.js +55 -0
- package/dist/harness/session/fork-policy.js.map +1 -0
- package/dist/harness/session/fork.d.ts +16 -0
- package/dist/harness/session/fork.d.ts.map +1 -0
- package/dist/harness/session/fork.js +79 -0
- package/dist/harness/session/fork.js.map +1 -0
- package/dist/harness/session/in-memory-storage-state.d.ts +39 -0
- package/dist/harness/session/in-memory-storage-state.d.ts.map +1 -0
- package/dist/harness/session/in-memory-storage-state.js +276 -0
- package/dist/harness/session/in-memory-storage-state.js.map +1 -0
- package/dist/harness/session/index.d.ts +11 -0
- package/dist/harness/session/index.d.ts.map +1 -0
- package/dist/harness/session/index.js +9 -0
- package/dist/harness/session/index.js.map +1 -0
- package/dist/harness/session/jsonl/codec.d.ts +21 -0
- package/dist/harness/session/jsonl/codec.d.ts.map +1 -0
- package/dist/harness/session/jsonl/codec.js +45 -0
- package/dist/harness/session/jsonl/codec.js.map +1 -0
- package/dist/harness/session/jsonl/fork.d.ts +38 -0
- package/dist/harness/session/jsonl/fork.d.ts.map +1 -0
- package/dist/harness/session/jsonl/fork.js +264 -0
- package/dist/harness/session/jsonl/fork.js.map +1 -0
- package/dist/harness/session/jsonl/index.d.ts +4 -0
- package/dist/harness/session/jsonl/index.d.ts.map +1 -0
- package/dist/harness/session/jsonl/index.js +4 -0
- package/dist/harness/session/jsonl/index.js.map +1 -0
- package/dist/harness/session/jsonl/io.d.ts +14 -0
- package/dist/harness/session/jsonl/io.d.ts.map +1 -0
- package/dist/harness/session/jsonl/io.js +86 -0
- package/dist/harness/session/jsonl/io.js.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts +44 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.js +462 -0
- package/dist/harness/session/jsonl/legacy-v3.js.map +1 -0
- package/dist/harness/session/jsonl/repo.d.ts +35 -0
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -0
- package/dist/harness/session/jsonl/repo.js +301 -0
- package/dist/harness/session/jsonl/repo.js.map +1 -0
- package/dist/harness/session/jsonl/storage.d.ts +41 -0
- package/dist/harness/session/jsonl/storage.d.ts.map +1 -0
- package/dist/harness/session/jsonl/storage.js +200 -0
- package/dist/harness/session/jsonl/storage.js.map +1 -0
- package/dist/harness/session/jsonl/types.d.ts +39 -0
- package/dist/harness/session/jsonl/types.d.ts.map +1 -0
- package/dist/harness/session/jsonl/types.js +3 -0
- package/dist/harness/session/jsonl/types.js.map +1 -0
- package/dist/harness/session/memory.d.ts +48 -0
- package/dist/harness/session/memory.d.ts.map +1 -0
- package/dist/harness/session/memory.js +369 -0
- package/dist/harness/session/memory.js.map +1 -0
- package/dist/harness/session/mutation-line.d.ts +8 -0
- package/dist/harness/session/mutation-line.d.ts.map +1 -0
- package/dist/harness/session/mutation-line.js +21 -0
- package/dist/harness/session/mutation-line.js.map +1 -0
- package/dist/harness/session/session.d.ts +79 -46
- package/dist/harness/session/session.d.ts.map +1 -1
- package/dist/harness/session/session.js +320 -220
- package/dist/harness/session/session.js.map +1 -1
- package/dist/harness/session/testing/benchmark/datasets.d.ts +12 -0
- package/dist/harness/session/testing/benchmark/datasets.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/datasets.js +24 -0
- package/dist/harness/session/testing/benchmark/datasets.js.map +1 -0
- package/dist/harness/session/testing/benchmark/session-repo.d.ts +42 -0
- package/dist/harness/session/testing/benchmark/session-repo.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/session-repo.js +127 -0
- package/dist/harness/session/testing/benchmark/session-repo.js.map +1 -0
- package/dist/harness/session/testing/benchmark/storage.d.ts +25 -0
- package/dist/harness/session/testing/benchmark/storage.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/storage.js +114 -0
- package/dist/harness/session/testing/benchmark/storage.js.map +1 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts +23 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance/session-repo.js +809 -0
- package/dist/harness/session/testing/conformance/session-repo.js.map +1 -0
- package/dist/harness/session/testing/conformance/storage.d.ts +4 -0
- package/dist/harness/session/testing/conformance/storage.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance/storage.js +600 -0
- package/dist/harness/session/testing/conformance/storage.js.map +1 -0
- package/dist/harness/session/testing/gating-storage.d.ts +26 -0
- package/dist/harness/session/testing/gating-storage.d.ts.map +1 -0
- package/dist/harness/session/testing/gating-storage.js +100 -0
- package/dist/harness/session/testing/gating-storage.js.map +1 -0
- package/dist/harness/session/testing/index.d.ts +10 -0
- package/dist/harness/session/testing/index.d.ts.map +1 -0
- package/dist/harness/session/testing/index.js +9 -0
- package/dist/harness/session/testing/index.js.map +1 -0
- package/dist/harness/session/testing/instrumented-storage.d.ts +11 -0
- package/dist/harness/session/testing/instrumented-storage.d.ts.map +1 -0
- package/dist/harness/session/testing/instrumented-storage.js +16 -0
- package/dist/harness/session/testing/instrumented-storage.js.map +1 -0
- package/dist/harness/session/testing/storage-decorator.d.ts +20 -0
- package/dist/harness/session/testing/storage-decorator.d.ts.map +1 -0
- package/dist/harness/session/testing/storage-decorator.js +41 -0
- package/dist/harness/session/testing/storage-decorator.js.map +1 -0
- package/dist/harness/session/testing/types.d.ts +12 -0
- package/dist/harness/session/testing/types.d.ts.map +1 -0
- package/dist/harness/session/testing/types.js +2 -0
- package/dist/harness/session/testing/types.js.map +1 -0
- package/dist/harness/session/types.d.ts +512 -0
- package/dist/harness/session/types.d.ts.map +1 -0
- package/dist/harness/session/types.js +9 -0
- package/dist/harness/session/types.js.map +1 -0
- package/dist/harness/session/values.d.ts +95 -0
- package/dist/harness/session/values.d.ts.map +1 -0
- package/dist/harness/session/values.js +81 -0
- package/dist/harness/session/values.js.map +1 -0
- package/dist/harness/skills.d.ts +6 -4
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +59 -44
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/telemetry.d.ts +1242 -0
- package/dist/harness/telemetry.d.ts.map +1 -0
- package/dist/harness/telemetry.js +527 -0
- package/dist/harness/telemetry.js.map +1 -0
- 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 +66 -93
- 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 +24 -11
- package/dist/harness/tools/edit.js.map +1 -1
- package/dist/harness/tools/file-mutation-queue.d.ts +2 -1
- 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/image.js +1 -1
- package/dist/harness/tools/image.js.map +1 -1
- package/dist/harness/tools/path-utils.d.ts +3 -2
- 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 +2 -1
- package/dist/harness/tools/read.d.ts.map +1 -1
- package/dist/harness/tools/read.js +4 -6
- 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 +7 -7
- package/dist/harness/tools/write.js.map +1 -1
- package/dist/harness/types.d.ts +126 -502
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js +10 -16
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/utils/adaptive-publisher.d.ts +24 -0
- package/dist/harness/utils/adaptive-publisher.d.ts.map +1 -0
- package/dist/harness/utils/adaptive-publisher.js +79 -0
- package/dist/harness/utils/adaptive-publisher.js.map +1 -0
- package/dist/harness/utils/output-capture.d.ts +31 -0
- package/dist/harness/utils/output-capture.d.ts.map +1 -0
- package/dist/harness/utils/output-capture.js +217 -0
- package/dist/harness/utils/output-capture.js.map +1 -0
- package/dist/harness/utils/shell-output.d.ts +12 -5
- package/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/dist/harness/utils/shell-output.js +64 -174
- package/dist/harness/utils/shell-output.js.map +1 -1
- package/dist/harness/utils/truncate.d.ts +1 -0
- 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/harness/utils/usage.d.ts +4 -0
- package/dist/harness/utils/usage.d.ts.map +1 -0
- package/dist/harness/utils/usage.js +33 -0
- package/dist/harness/utils/usage.js.map +1 -0
- package/dist/index.d.ts +13 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -13
- package/dist/index.js.map +1 -1
- package/dist/proxy.d.ts +6 -3
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +42 -10
- package/dist/proxy.js.map +1 -1
- package/dist/search/index.d.ts +29 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +2 -0
- package/dist/search/index.js.map +1 -0
- package/dist/types.d.ts +113 -31
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +50 -4
- package/dist/harness/session/jsonl-repo.d.ts +0 -26
- package/dist/harness/session/jsonl-repo.d.ts.map +0 -1
- package/dist/harness/session/jsonl-repo.js +0 -100
- package/dist/harness/session/jsonl-repo.js.map +0 -1
- package/dist/harness/session/jsonl-storage.d.ts +0 -42
- package/dist/harness/session/jsonl-storage.d.ts.map +0 -1
- package/dist/harness/session/jsonl-storage.js +0 -286
- package/dist/harness/session/jsonl-storage.js.map +0 -1
- package/dist/harness/session/memory-repo.d.ts +0 -18
- package/dist/harness/session/memory-repo.d.ts.map +0 -1
- package/dist/harness/session/memory-repo.js +0 -44
- package/dist/harness/session/memory-repo.js.map +0 -1
- package/dist/harness/session/memory-storage.d.ts +0 -33
- package/dist/harness/session/memory-storage.d.ts.map +0 -1
- package/dist/harness/session/memory-storage.js +0 -163
- package/dist/harness/session/memory-storage.js.map +0 -1
- package/dist/harness/session/repo-utils.d.ts +0 -11
- package/dist/harness/session/repo-utils.d.ts.map +0 -1
- package/dist/harness/session/repo-utils.js +0 -39
- package/dist/harness/session/repo-utils.js.map +0 -1
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
|
-
import { constants,
|
|
4
|
-
import { access, appendFile, lstat, mkdir, mkdtemp, readdir, readFile, realpath, rm, writeFile, } from "node:fs/promises";
|
|
5
|
-
import { homedir, tmpdir } from "node:os";
|
|
6
|
-
import { isAbsolute, join, resolve } from "node:path";
|
|
7
|
-
import { createInterface } from "node:readline";
|
|
3
|
+
import { constants, createWriteStream } from "node:fs";
|
|
4
|
+
import { access, appendFile, lstat, mkdir, mkdtemp, open as openFile, readdir, readFile, realpath, rename, rm, writeFile, } from "node:fs/promises";
|
|
5
|
+
import { homedir, constants as osConstants, tmpdir } from "node:os";
|
|
6
|
+
import { basename, isAbsolute, join, resolve } from "node:path";
|
|
8
7
|
import { fileURLToPath } from "node:url";
|
|
9
8
|
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;
|
|
13
14
|
function resolveTimeoutMs(timeout) {
|
|
14
15
|
if (timeout === undefined)
|
|
15
16
|
return ok(undefined);
|
|
@@ -54,7 +55,7 @@ function fileInfoFromStats(path, stats) {
|
|
|
54
55
|
if (!kind)
|
|
55
56
|
return err(new FileError("invalid", "Unsupported file type", path));
|
|
56
57
|
return ok({
|
|
57
|
-
name: path
|
|
58
|
+
name: basename(path),
|
|
58
59
|
path,
|
|
59
60
|
kind,
|
|
60
61
|
size: stats.size,
|
|
@@ -64,13 +65,15 @@ function fileInfoFromStats(path, stats) {
|
|
|
64
65
|
function isNodeError(error) {
|
|
65
66
|
return error instanceof Error && "code" in error;
|
|
66
67
|
}
|
|
67
|
-
function toFileError(error,
|
|
68
|
+
function toFileError(error, fallbackPath) {
|
|
68
69
|
if (error instanceof FileError)
|
|
69
70
|
return error;
|
|
70
71
|
const cause = toError(error);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
const nodeError = isNodeError(error) ? error : undefined;
|
|
73
|
+
const path = typeof nodeError?.path === "string" ? nodeError.path : fallbackPath;
|
|
74
|
+
if (nodeError) {
|
|
75
|
+
const message = nodeError.message;
|
|
76
|
+
switch (nodeError.code) {
|
|
74
77
|
case "ABORT_ERR":
|
|
75
78
|
return new FileError("aborted", message, path, cause);
|
|
76
79
|
case "ENOENT":
|
|
@@ -199,11 +202,13 @@ function getShellEnv(baseEnv, extraEnv, inheritEnv = true) {
|
|
|
199
202
|
function killProcessTree(pid) {
|
|
200
203
|
if (process.platform === "win32") {
|
|
201
204
|
try {
|
|
202
|
-
spawn("taskkill", ["/F", "/T", "/PID", String(pid)], {
|
|
205
|
+
const child = spawn(join(process.env.SystemRoot ?? "C:\\Windows", "System32", "taskkill.exe"), ["/F", "/T", "/PID", String(pid)], {
|
|
203
206
|
stdio: "ignore",
|
|
204
207
|
detached: true,
|
|
205
208
|
windowsHide: true,
|
|
206
209
|
});
|
|
210
|
+
// A failed spawn emits "error" asynchronously; consume it to avoid crashing Node.
|
|
211
|
+
child.once("error", () => { });
|
|
207
212
|
}
|
|
208
213
|
catch {
|
|
209
214
|
// Ignore errors.
|
|
@@ -222,11 +227,12 @@ function killProcessTree(pid) {
|
|
|
222
227
|
}
|
|
223
228
|
}
|
|
224
229
|
}
|
|
225
|
-
function waitForChildProcess(child) {
|
|
230
|
+
function waitForChildProcess(child, spillIsDraining) {
|
|
226
231
|
return new Promise((resolvePromise, reject) => {
|
|
227
232
|
let settled = false;
|
|
228
233
|
let exited = false;
|
|
229
234
|
let exitCode = null;
|
|
235
|
+
let exitSignal = null;
|
|
230
236
|
let postExitTimer;
|
|
231
237
|
let stdoutEnded = child.stdout === null;
|
|
232
238
|
let stderrEnded = child.stderr === null;
|
|
@@ -241,23 +247,28 @@ function waitForChildProcess(child) {
|
|
|
241
247
|
child.stdout?.removeListener("data", onData);
|
|
242
248
|
child.stderr?.removeListener("data", onData);
|
|
243
249
|
};
|
|
244
|
-
const finalize = (
|
|
250
|
+
const finalize = () => {
|
|
245
251
|
if (settled)
|
|
246
252
|
return;
|
|
247
253
|
settled = true;
|
|
248
254
|
cleanup();
|
|
249
255
|
child.stdout?.destroy();
|
|
250
256
|
child.stderr?.destroy();
|
|
251
|
-
resolvePromise(code);
|
|
257
|
+
resolvePromise({ code: exitCode, signal: exitSignal });
|
|
252
258
|
};
|
|
253
259
|
const maybeFinalizeAfterExit = () => {
|
|
254
260
|
if (exited && stdoutEnded && stderrEnded)
|
|
255
|
-
finalize(
|
|
261
|
+
finalize();
|
|
256
262
|
};
|
|
257
263
|
const armIdleTimer = () => {
|
|
258
264
|
if (postExitTimer)
|
|
259
265
|
clearTimeout(postExitTimer);
|
|
260
|
-
postExitTimer = setTimeout(() =>
|
|
266
|
+
postExitTimer = setTimeout(() => {
|
|
267
|
+
if (spillIsDraining())
|
|
268
|
+
armIdleTimer();
|
|
269
|
+
else
|
|
270
|
+
finalize();
|
|
271
|
+
}, EXIT_STDIO_GRACE_MS);
|
|
261
272
|
};
|
|
262
273
|
const onData = () => {
|
|
263
274
|
if (exited && !settled)
|
|
@@ -278,14 +289,19 @@ function waitForChildProcess(child) {
|
|
|
278
289
|
cleanup();
|
|
279
290
|
reject(error);
|
|
280
291
|
};
|
|
281
|
-
const onExit = (code) => {
|
|
292
|
+
const onExit = (code, signal) => {
|
|
282
293
|
exited = true;
|
|
283
294
|
exitCode = code;
|
|
295
|
+
exitSignal = signal;
|
|
284
296
|
maybeFinalizeAfterExit();
|
|
285
297
|
if (!settled)
|
|
286
298
|
armIdleTimer();
|
|
287
299
|
};
|
|
288
|
-
const onClose = (code) =>
|
|
300
|
+
const onClose = (code, signal) => {
|
|
301
|
+
exitCode = code;
|
|
302
|
+
exitSignal = signal;
|
|
303
|
+
finalize();
|
|
304
|
+
};
|
|
289
305
|
child.stdout?.once("end", onStdoutEnd);
|
|
290
306
|
child.stderr?.once("end", onStderrEnd);
|
|
291
307
|
child.stdout?.on("data", onData);
|
|
@@ -295,21 +311,92 @@ function waitForChildProcess(child) {
|
|
|
295
311
|
child.once("close", onClose);
|
|
296
312
|
});
|
|
297
313
|
}
|
|
314
|
+
/** Strict LF reader; Node readline does not report whether its final line was newline-terminated. */
|
|
315
|
+
class NodeTextLineReader {
|
|
316
|
+
file;
|
|
317
|
+
path;
|
|
318
|
+
decoder = new TextDecoder();
|
|
319
|
+
chunk = new Uint8Array(64 * 1024);
|
|
320
|
+
byteOffset = 0;
|
|
321
|
+
buffered = "";
|
|
322
|
+
ended = false;
|
|
323
|
+
closed = false;
|
|
324
|
+
constructor(file, path) {
|
|
325
|
+
this.file = file;
|
|
326
|
+
this.path = path;
|
|
327
|
+
}
|
|
328
|
+
async readLine(context) {
|
|
329
|
+
const aborted = abortResult(context.abortSignal, this.path);
|
|
330
|
+
if (aborted)
|
|
331
|
+
return aborted;
|
|
332
|
+
if (this.closed)
|
|
333
|
+
return err(new FileError("invalid", "Text line reader is closed", this.path));
|
|
334
|
+
try {
|
|
335
|
+
while (true) {
|
|
336
|
+
const newline = this.buffered.indexOf("\n");
|
|
337
|
+
if (newline !== -1) {
|
|
338
|
+
const text = this.buffered.slice(0, newline);
|
|
339
|
+
this.buffered = this.buffered.slice(newline + 1);
|
|
340
|
+
return ok({ text, terminated: true });
|
|
341
|
+
}
|
|
342
|
+
if (this.ended) {
|
|
343
|
+
if (this.buffered.length === 0)
|
|
344
|
+
return ok(undefined);
|
|
345
|
+
const text = this.buffered;
|
|
346
|
+
this.buffered = "";
|
|
347
|
+
return ok({ text, terminated: false });
|
|
348
|
+
}
|
|
349
|
+
// Explicit positions allow an aborted read to be retried without skipping bytes.
|
|
350
|
+
const { bytesRead } = await this.file.read(this.chunk, 0, this.chunk.length, this.byteOffset);
|
|
351
|
+
const afterReadAbort = abortResult(context.abortSignal, this.path);
|
|
352
|
+
if (afterReadAbort)
|
|
353
|
+
return afterReadAbort;
|
|
354
|
+
this.byteOffset += bytesRead;
|
|
355
|
+
if (bytesRead === 0) {
|
|
356
|
+
this.buffered += this.decoder.decode();
|
|
357
|
+
this.ended = true;
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
this.buffered += this.decoder.decode(this.chunk.subarray(0, bytesRead), { stream: true });
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
return err(toFileError(error, this.path));
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
async close(_context) {
|
|
369
|
+
if (this.closed)
|
|
370
|
+
return;
|
|
371
|
+
this.closed = true;
|
|
372
|
+
this.buffered = "";
|
|
373
|
+
try {
|
|
374
|
+
await this.file.close();
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
// Closing is best-effort, including after cancellation or an earlier I/O failure.
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
298
381
|
export class NodeExecutionEnv {
|
|
382
|
+
cwd;
|
|
383
|
+
shellPath;
|
|
384
|
+
shellEnv;
|
|
385
|
+
activeChildPids = new Set();
|
|
299
386
|
constructor(options) {
|
|
300
|
-
this.activeChildPids = new Set();
|
|
301
387
|
this.cwd = options.cwd;
|
|
302
388
|
this.shellPath = options.shellPath;
|
|
303
389
|
this.shellEnv = options.shellEnv;
|
|
304
390
|
}
|
|
305
|
-
async absolutePath(path) {
|
|
391
|
+
async absolutePath(path, _context) {
|
|
306
392
|
return ok(resolvePath(this.cwd, path));
|
|
307
393
|
}
|
|
308
|
-
async joinPath(parts) {
|
|
394
|
+
async joinPath(parts, _context) {
|
|
309
395
|
return ok(join(...parts));
|
|
310
396
|
}
|
|
311
|
-
async exec(command, options) {
|
|
312
|
-
|
|
397
|
+
async exec(command, options, context) {
|
|
398
|
+
const signal = context.abortSignal;
|
|
399
|
+
if (signal?.aborted)
|
|
313
400
|
return err(new ExecutionError("aborted", "aborted"));
|
|
314
401
|
const timeoutMsResult = resolveTimeoutMs(options?.timeout);
|
|
315
402
|
if (!timeoutMsResult.ok)
|
|
@@ -327,30 +414,119 @@ export class NodeExecutionEnv {
|
|
|
327
414
|
return err(new ExecutionError("spawn_error", `Working directory does not exist: ${cwd}\nCannot execute bash commands.`, cause));
|
|
328
415
|
}
|
|
329
416
|
return await new Promise((resolvePromise) => {
|
|
330
|
-
let stdout = "";
|
|
331
|
-
let stderr = "";
|
|
332
417
|
let settled = false;
|
|
333
418
|
let timedOut = false;
|
|
334
419
|
let callbackError;
|
|
420
|
+
let spillError;
|
|
335
421
|
let child;
|
|
336
422
|
let timeoutId;
|
|
423
|
+
const spillPrefix = [];
|
|
424
|
+
let spillPath;
|
|
425
|
+
const spillQueue = [];
|
|
426
|
+
let spillStart;
|
|
427
|
+
let spillStream;
|
|
428
|
+
let spillBackpressured = false;
|
|
337
429
|
const onAbort = () => {
|
|
338
|
-
if (child?.pid)
|
|
430
|
+
if (child?.pid)
|
|
339
431
|
killProcessTree(child.pid);
|
|
340
|
-
}
|
|
341
432
|
};
|
|
433
|
+
const failCallback = (error) => {
|
|
434
|
+
if (callbackError !== undefined)
|
|
435
|
+
return;
|
|
436
|
+
const cause = toError(error);
|
|
437
|
+
callbackError = new ExecutionError("callback_error", cause.message, cause);
|
|
438
|
+
onAbort();
|
|
439
|
+
};
|
|
440
|
+
let capture;
|
|
441
|
+
try {
|
|
442
|
+
capture = new OutputCapture(options?.capture, context, {
|
|
443
|
+
onUpdate: options?.onUpdate,
|
|
444
|
+
onError: failCallback,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
catch (error) {
|
|
448
|
+
const cause = toError(error);
|
|
449
|
+
resolvePromise(err(new ExecutionError("unknown", cause.message, cause)));
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
342
452
|
const settle = (result) => {
|
|
453
|
+
if (settled)
|
|
454
|
+
return;
|
|
455
|
+
settled = true;
|
|
343
456
|
if (timeoutId)
|
|
344
457
|
clearTimeout(timeoutId);
|
|
345
|
-
if (
|
|
346
|
-
|
|
458
|
+
if (signal)
|
|
459
|
+
signal.removeEventListener("abort", onAbort);
|
|
347
460
|
if (child?.pid)
|
|
348
461
|
this.activeChildPids.delete(child.pid);
|
|
349
|
-
|
|
350
|
-
return;
|
|
351
|
-
settled = true;
|
|
462
|
+
capture.dispose();
|
|
352
463
|
resolvePromise(result);
|
|
353
464
|
};
|
|
465
|
+
const pauseOutput = () => {
|
|
466
|
+
child?.stdout?.pause();
|
|
467
|
+
child?.stderr?.pause();
|
|
468
|
+
};
|
|
469
|
+
const resumeOutput = () => {
|
|
470
|
+
if (callbackError || spillError || timedOut || signal?.aborted || spillBackpressured)
|
|
471
|
+
return;
|
|
472
|
+
child?.stdout?.resume();
|
|
473
|
+
child?.stderr?.resume();
|
|
474
|
+
};
|
|
475
|
+
const failSpill = (error) => {
|
|
476
|
+
if (spillError !== undefined)
|
|
477
|
+
return;
|
|
478
|
+
const cause = toError(error);
|
|
479
|
+
spillError = new ExecutionError("unknown", `Failed to preserve complete shell output: ${cause.message}`, cause);
|
|
480
|
+
spillBackpressured = false;
|
|
481
|
+
onAbort();
|
|
482
|
+
};
|
|
483
|
+
const writeSpill = (chunk) => {
|
|
484
|
+
if (spillStream === undefined || chunk.length === 0)
|
|
485
|
+
return;
|
|
486
|
+
if (spillStream.write(chunk) || spillBackpressured)
|
|
487
|
+
return;
|
|
488
|
+
spillBackpressured = true;
|
|
489
|
+
pauseOutput();
|
|
490
|
+
spillStream.once("drain", () => {
|
|
491
|
+
spillBackpressured = false;
|
|
492
|
+
resumeOutput();
|
|
493
|
+
});
|
|
494
|
+
};
|
|
495
|
+
const startSpill = (chunk) => {
|
|
496
|
+
if (spillStream !== undefined) {
|
|
497
|
+
writeSpill(chunk);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
spillQueue.push(chunk);
|
|
501
|
+
if (spillStart !== undefined)
|
|
502
|
+
return;
|
|
503
|
+
pauseOutput();
|
|
504
|
+
spillStart = (async () => {
|
|
505
|
+
const created = await this.createTempFile({ prefix: "draht-output-", suffix: ".log" }, context);
|
|
506
|
+
if (!created.ok)
|
|
507
|
+
throw created.error;
|
|
508
|
+
spillPath = created.value;
|
|
509
|
+
capture.setSpillPath(spillPath);
|
|
510
|
+
spillStream = createWriteStream(spillPath, { flags: "a", highWaterMark: SPILL_HIGH_WATER_MARK });
|
|
511
|
+
spillStream.on("error", failSpill);
|
|
512
|
+
for (const queued of spillQueue)
|
|
513
|
+
writeSpill(queued);
|
|
514
|
+
spillQueue.length = 0;
|
|
515
|
+
})()
|
|
516
|
+
.catch(failSpill)
|
|
517
|
+
.finally(resumeOutput);
|
|
518
|
+
};
|
|
519
|
+
const finishSpill = async () => {
|
|
520
|
+
await spillStart;
|
|
521
|
+
const stream = spillStream;
|
|
522
|
+
if (stream === undefined || spillError !== undefined || stream.destroyed)
|
|
523
|
+
return;
|
|
524
|
+
await new Promise((resolveFinish) => {
|
|
525
|
+
stream.once("error", () => resolveFinish());
|
|
526
|
+
stream.once("finish", resolveFinish);
|
|
527
|
+
stream.end();
|
|
528
|
+
});
|
|
529
|
+
};
|
|
354
530
|
try {
|
|
355
531
|
const commandFromStdin = shellConfig.value.commandTransport === "stdin";
|
|
356
532
|
child = spawn(shellConfig.value.shell, commandFromStdin ? shellConfig.value.args : [...shellConfig.value.args, command], {
|
|
@@ -373,47 +549,54 @@ export class NodeExecutionEnv {
|
|
|
373
549
|
return;
|
|
374
550
|
}
|
|
375
551
|
timeoutId =
|
|
376
|
-
timeoutMs
|
|
377
|
-
?
|
|
552
|
+
timeoutMs === undefined
|
|
553
|
+
? undefined
|
|
554
|
+
: setTimeout(() => {
|
|
378
555
|
timedOut = true;
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
: undefined;
|
|
384
|
-
if (options?.abortSignal) {
|
|
385
|
-
if (options.abortSignal.aborted) {
|
|
556
|
+
onAbort();
|
|
557
|
+
}, timeoutMs);
|
|
558
|
+
if (signal) {
|
|
559
|
+
if (signal.aborted)
|
|
386
560
|
onAbort();
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
options.abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
390
|
-
}
|
|
561
|
+
else
|
|
562
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
391
563
|
}
|
|
392
|
-
|
|
393
|
-
child.stderr?.setEncoding("utf8");
|
|
394
|
-
child.stdout?.on("data", (chunk) => {
|
|
395
|
-
stdout += chunk;
|
|
564
|
+
const feed = (chunk) => {
|
|
396
565
|
try {
|
|
397
|
-
|
|
566
|
+
const wasTruncated = capture.truncated;
|
|
567
|
+
capture.push(chunk);
|
|
568
|
+
if (!options?.capture?.spill || chunk.length === 0)
|
|
569
|
+
return;
|
|
570
|
+
if (spillPath !== undefined || wasTruncated) {
|
|
571
|
+
startSpill(chunk);
|
|
572
|
+
}
|
|
573
|
+
else if (capture.truncated) {
|
|
574
|
+
for (const prefix of spillPrefix)
|
|
575
|
+
startSpill(prefix);
|
|
576
|
+
spillPrefix.length = 0;
|
|
577
|
+
startSpill(chunk);
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
spillPrefix.push(chunk);
|
|
581
|
+
}
|
|
398
582
|
}
|
|
399
583
|
catch (error) {
|
|
400
|
-
|
|
401
|
-
callbackError = new ExecutionError("callback_error", cause.message, cause);
|
|
402
|
-
onAbort();
|
|
584
|
+
failCallback(error);
|
|
403
585
|
}
|
|
404
|
-
}
|
|
405
|
-
child.
|
|
406
|
-
|
|
586
|
+
};
|
|
587
|
+
child.stdout?.on("data", feed);
|
|
588
|
+
child.stderr?.on("data", feed);
|
|
589
|
+
void waitForChildProcess(child, () => spillError === undefined &&
|
|
590
|
+
spillStart !== undefined &&
|
|
591
|
+
(spillStream === undefined || spillBackpressured)).then(async ({ code, signal: exitSignal }) => {
|
|
592
|
+
await finishSpill();
|
|
407
593
|
try {
|
|
408
|
-
|
|
594
|
+
capture.finish();
|
|
595
|
+
capture.flush();
|
|
409
596
|
}
|
|
410
597
|
catch (error) {
|
|
411
|
-
|
|
412
|
-
callbackError = new ExecutionError("callback_error", cause.message, cause);
|
|
413
|
-
onAbort();
|
|
598
|
+
failCallback(error);
|
|
414
599
|
}
|
|
415
|
-
});
|
|
416
|
-
void waitForChildProcess(child).then((code) => {
|
|
417
600
|
if (callbackError) {
|
|
418
601
|
settle(err(callbackError));
|
|
419
602
|
return;
|
|
@@ -422,102 +605,150 @@ export class NodeExecutionEnv {
|
|
|
422
605
|
settle(err(new ExecutionError("timeout", `timeout:${options?.timeout}`)));
|
|
423
606
|
return;
|
|
424
607
|
}
|
|
425
|
-
if (
|
|
608
|
+
if (signal?.aborted) {
|
|
426
609
|
settle(err(new ExecutionError("aborted", "aborted")));
|
|
427
610
|
return;
|
|
428
611
|
}
|
|
429
|
-
|
|
612
|
+
if (spillError) {
|
|
613
|
+
settle(err(spillError));
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
const output = capture.snapshot();
|
|
617
|
+
// A process killed by a signal (e.g. OOM killer) has no exit code; map it
|
|
618
|
+
// to the conventional 128 + signal number so callers do not mistake it
|
|
619
|
+
// for a successful exit.
|
|
620
|
+
const exitCode = code ?? (exitSignal ? 128 + (osConstants.signals[exitSignal] ?? 0) : 1);
|
|
621
|
+
settle(ok({
|
|
622
|
+
exitCode,
|
|
623
|
+
truncation: output.truncation,
|
|
624
|
+
...(output.spillPath === undefined ? {} : { spillPath: output.spillPath }),
|
|
625
|
+
...(output.lastLineBytes === undefined ? {} : { lastLineBytes: output.lastLineBytes }),
|
|
626
|
+
}));
|
|
430
627
|
}, (error) => settle(err(new ExecutionError("spawn_error", error.message, error))));
|
|
431
628
|
});
|
|
432
629
|
}
|
|
433
|
-
async
|
|
630
|
+
async openTextLineReader(path, context) {
|
|
434
631
|
const resolved = resolvePath(this.cwd, path);
|
|
435
|
-
const aborted = abortResult(abortSignal, resolved);
|
|
632
|
+
const aborted = abortResult(context.abortSignal, resolved);
|
|
436
633
|
if (aborted)
|
|
437
634
|
return aborted;
|
|
438
635
|
try {
|
|
439
|
-
|
|
636
|
+
const file = await openFile(resolved, "r");
|
|
637
|
+
const afterOpenAbort = abortResult(context.abortSignal, resolved);
|
|
638
|
+
if (afterOpenAbort) {
|
|
639
|
+
await file.close().catch(() => undefined);
|
|
640
|
+
return afterOpenAbort;
|
|
641
|
+
}
|
|
642
|
+
return ok(new NodeTextLineReader(file, resolved));
|
|
440
643
|
}
|
|
441
644
|
catch (error) {
|
|
442
645
|
return err(toFileError(error, resolved));
|
|
443
646
|
}
|
|
444
647
|
}
|
|
445
|
-
async
|
|
648
|
+
async readTextFile(path, context) {
|
|
446
649
|
const resolved = resolvePath(this.cwd, path);
|
|
447
|
-
const
|
|
650
|
+
const signal = context.abortSignal;
|
|
651
|
+
const aborted = abortResult(signal, resolved);
|
|
448
652
|
if (aborted)
|
|
449
653
|
return aborted;
|
|
654
|
+
try {
|
|
655
|
+
return ok(await readFile(resolved, { encoding: "utf8", signal }));
|
|
656
|
+
}
|
|
657
|
+
catch (error) {
|
|
658
|
+
return err(toFileError(error, resolved));
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
async readTextLines(path, options, context) {
|
|
450
662
|
if (options?.maxLines !== undefined && options.maxLines <= 0)
|
|
451
663
|
return ok([]);
|
|
452
|
-
|
|
453
|
-
|
|
664
|
+
const opened = await this.openTextLineReader(path, context);
|
|
665
|
+
if (!opened.ok)
|
|
666
|
+
return opened;
|
|
667
|
+
const lines = [];
|
|
454
668
|
try {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
if (loopAbort)
|
|
461
|
-
return loopAbort;
|
|
462
|
-
lines.push(line);
|
|
463
|
-
if (options?.maxLines !== undefined && lines.length >= options.maxLines)
|
|
669
|
+
while (options?.maxLines === undefined || lines.length < options.maxLines) {
|
|
670
|
+
const line = await opened.value.readLine(context);
|
|
671
|
+
if (!line.ok)
|
|
672
|
+
return line;
|
|
673
|
+
if (line.value === undefined)
|
|
464
674
|
break;
|
|
675
|
+
lines.push(line.value.text);
|
|
465
676
|
}
|
|
466
|
-
const afterReadAbort = abortResult(options?.abortSignal, resolved);
|
|
467
|
-
if (afterReadAbort)
|
|
468
|
-
return afterReadAbort;
|
|
469
677
|
return ok(lines);
|
|
470
678
|
}
|
|
471
|
-
catch (error) {
|
|
472
|
-
return err(toFileError(error, resolved));
|
|
473
|
-
}
|
|
474
679
|
finally {
|
|
475
|
-
|
|
476
|
-
stream?.destroy();
|
|
680
|
+
await opened.value.close(context);
|
|
477
681
|
}
|
|
478
682
|
}
|
|
479
|
-
async readBinaryFile(path,
|
|
683
|
+
async readBinaryFile(path, context) {
|
|
480
684
|
const resolved = resolvePath(this.cwd, path);
|
|
481
|
-
const
|
|
685
|
+
const signal = context.abortSignal;
|
|
686
|
+
const aborted = abortResult(signal, resolved);
|
|
482
687
|
if (aborted)
|
|
483
688
|
return aborted;
|
|
484
689
|
try {
|
|
485
|
-
return ok(await readFile(resolved, { signal
|
|
690
|
+
return ok(await readFile(resolved, { signal }));
|
|
486
691
|
}
|
|
487
692
|
catch (error) {
|
|
488
693
|
return err(toFileError(error, resolved));
|
|
489
694
|
}
|
|
490
695
|
}
|
|
491
|
-
async writeFile(path, content,
|
|
696
|
+
async writeFile(path, content, context) {
|
|
492
697
|
const resolved = resolvePath(this.cwd, path);
|
|
493
|
-
const
|
|
698
|
+
const signal = context.abortSignal;
|
|
699
|
+
const aborted = abortResult(signal, resolved);
|
|
494
700
|
if (aborted)
|
|
495
701
|
return aborted;
|
|
496
702
|
try {
|
|
497
703
|
await mkdir(resolve(resolved, ".."), { recursive: true });
|
|
498
|
-
const afterMkdirAbort = abortResult(
|
|
704
|
+
const afterMkdirAbort = abortResult(signal, resolved);
|
|
499
705
|
if (afterMkdirAbort)
|
|
500
706
|
return afterMkdirAbort;
|
|
501
|
-
await writeFile(resolved, content, { signal
|
|
707
|
+
await writeFile(resolved, content, { signal });
|
|
502
708
|
return ok(undefined);
|
|
503
709
|
}
|
|
504
710
|
catch (error) {
|
|
505
711
|
return err(toFileError(error, resolved));
|
|
506
712
|
}
|
|
507
713
|
}
|
|
508
|
-
async appendFile(path, content) {
|
|
714
|
+
async appendFile(path, content, context) {
|
|
509
715
|
const resolved = resolvePath(this.cwd, path);
|
|
716
|
+
const signal = context.abortSignal;
|
|
717
|
+
const aborted = abortResult(signal, resolved);
|
|
718
|
+
if (aborted)
|
|
719
|
+
return aborted;
|
|
510
720
|
try {
|
|
511
721
|
await mkdir(resolve(resolved, ".."), { recursive: true });
|
|
722
|
+
const afterMkdirAbort = abortResult(signal, resolved);
|
|
723
|
+
if (afterMkdirAbort)
|
|
724
|
+
return afterMkdirAbort;
|
|
512
725
|
await appendFile(resolved, content);
|
|
513
|
-
|
|
726
|
+
const afterAppendAbort = abortResult(signal, resolved);
|
|
727
|
+
return afterAppendAbort ?? ok(undefined);
|
|
514
728
|
}
|
|
515
729
|
catch (error) {
|
|
516
730
|
return err(toFileError(error, resolved));
|
|
517
731
|
}
|
|
518
732
|
}
|
|
519
|
-
async
|
|
733
|
+
async renameFile(sourcePath, destinationPath, context) {
|
|
734
|
+
const source = resolvePath(this.cwd, sourcePath);
|
|
735
|
+
const destination = resolvePath(this.cwd, destinationPath);
|
|
736
|
+
const aborted = abortResult(context.abortSignal, destination);
|
|
737
|
+
if (aborted)
|
|
738
|
+
return aborted;
|
|
739
|
+
try {
|
|
740
|
+
await rename(source, destination);
|
|
741
|
+
return ok(undefined);
|
|
742
|
+
}
|
|
743
|
+
catch (error) {
|
|
744
|
+
return err(toFileError(error, source));
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
async fileInfo(path, context) {
|
|
520
748
|
const resolved = resolvePath(this.cwd, path);
|
|
749
|
+
const aborted = abortResult(context.abortSignal, resolved);
|
|
750
|
+
if (aborted)
|
|
751
|
+
return aborted;
|
|
521
752
|
try {
|
|
522
753
|
return fileInfoFromStats(resolved, await lstat(resolved));
|
|
523
754
|
}
|
|
@@ -525,16 +756,17 @@ export class NodeExecutionEnv {
|
|
|
525
756
|
return err(toFileError(error, resolved));
|
|
526
757
|
}
|
|
527
758
|
}
|
|
528
|
-
async listDir(path,
|
|
759
|
+
async listDir(path, context) {
|
|
529
760
|
const resolved = resolvePath(this.cwd, path);
|
|
530
|
-
const
|
|
761
|
+
const signal = context.abortSignal;
|
|
762
|
+
const aborted = abortResult(signal, resolved);
|
|
531
763
|
if (aborted)
|
|
532
764
|
return aborted;
|
|
533
765
|
try {
|
|
534
766
|
const entries = await readdir(resolved, { withFileTypes: true });
|
|
535
767
|
const infos = [];
|
|
536
768
|
for (const entry of entries) {
|
|
537
|
-
const loopAbort = abortResult(
|
|
769
|
+
const loopAbort = abortResult(signal, resolved);
|
|
538
770
|
if (loopAbort)
|
|
539
771
|
return loopAbort;
|
|
540
772
|
const entryPath = resolve(resolved, entry.name);
|
|
@@ -553,8 +785,11 @@ export class NodeExecutionEnv {
|
|
|
553
785
|
return err(toFileError(error, resolved));
|
|
554
786
|
}
|
|
555
787
|
}
|
|
556
|
-
async canonicalPath(path) {
|
|
788
|
+
async canonicalPath(path, context) {
|
|
557
789
|
const resolved = resolvePath(this.cwd, path);
|
|
790
|
+
const aborted = abortResult(context.abortSignal, resolved);
|
|
791
|
+
if (aborted)
|
|
792
|
+
return aborted;
|
|
558
793
|
try {
|
|
559
794
|
return ok(await realpath(resolved));
|
|
560
795
|
}
|
|
@@ -562,16 +797,19 @@ export class NodeExecutionEnv {
|
|
|
562
797
|
return err(toFileError(error, resolved));
|
|
563
798
|
}
|
|
564
799
|
}
|
|
565
|
-
async exists(path) {
|
|
566
|
-
const result = await this.fileInfo(path);
|
|
800
|
+
async exists(path, context) {
|
|
801
|
+
const result = await this.fileInfo(path, context);
|
|
567
802
|
if (result.ok)
|
|
568
803
|
return ok(true);
|
|
569
804
|
if (result.error.code === "not_found")
|
|
570
805
|
return ok(false);
|
|
571
806
|
return err(result.error);
|
|
572
807
|
}
|
|
573
|
-
async createDir(path, options) {
|
|
808
|
+
async createDir(path, options, context) {
|
|
574
809
|
const resolved = resolvePath(this.cwd, path);
|
|
810
|
+
const aborted = abortResult(context.abortSignal, resolved);
|
|
811
|
+
if (aborted)
|
|
812
|
+
return aborted;
|
|
575
813
|
try {
|
|
576
814
|
await mkdir(resolved, { recursive: options?.recursive ?? true });
|
|
577
815
|
return ok(undefined);
|
|
@@ -580,8 +818,11 @@ export class NodeExecutionEnv {
|
|
|
580
818
|
return err(toFileError(error, resolved));
|
|
581
819
|
}
|
|
582
820
|
}
|
|
583
|
-
async remove(path, options) {
|
|
821
|
+
async remove(path, options, context) {
|
|
584
822
|
const resolved = resolvePath(this.cwd, path);
|
|
823
|
+
const aborted = abortResult(context.abortSignal, resolved);
|
|
824
|
+
if (aborted)
|
|
825
|
+
return aborted;
|
|
585
826
|
try {
|
|
586
827
|
await rm(resolved, { recursive: options?.recursive ?? false, force: options?.force ?? false });
|
|
587
828
|
return ok(undefined);
|
|
@@ -590,16 +831,20 @@ export class NodeExecutionEnv {
|
|
|
590
831
|
return err(toFileError(error, resolved));
|
|
591
832
|
}
|
|
592
833
|
}
|
|
593
|
-
async createTempDir(prefix
|
|
834
|
+
async createTempDir(prefix, context) {
|
|
835
|
+
const aborted = abortResult(context.abortSignal);
|
|
836
|
+
if (aborted)
|
|
837
|
+
return aborted;
|
|
594
838
|
try {
|
|
839
|
+
prefix ??= "tmp-";
|
|
595
840
|
return ok(await mkdtemp(join(tmpdir(), prefix)));
|
|
596
841
|
}
|
|
597
842
|
catch (error) {
|
|
598
843
|
return err(toFileError(error));
|
|
599
844
|
}
|
|
600
845
|
}
|
|
601
|
-
async createTempFile(options) {
|
|
602
|
-
const dir = await this.createTempDir("tmp-");
|
|
846
|
+
async createTempFile(options, context) {
|
|
847
|
+
const dir = await this.createTempDir("tmp-", context);
|
|
603
848
|
if (!dir.ok)
|
|
604
849
|
return dir;
|
|
605
850
|
const filePath = join(dir.value, `${options?.prefix ?? ""}${randomUUID()}${options?.suffix ?? ""}`);
|
|
@@ -611,7 +856,7 @@ export class NodeExecutionEnv {
|
|
|
611
856
|
return err(toFileError(error, filePath));
|
|
612
857
|
}
|
|
613
858
|
}
|
|
614
|
-
async cleanup() {
|
|
859
|
+
async cleanup(_context) {
|
|
615
860
|
for (const pid of this.activeChildPids)
|
|
616
861
|
killProcessTree(pid);
|
|
617
862
|
this.activeChildPids.clear();
|