@the-open-engine/zeroshot 6.38.0 → 6.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/event-copy.js +8 -7
- package/cli/event-copy.ts +12 -0
- package/cli/index.js +7 -31
- package/cli/json-export.js +61 -64
- package/cli/json-export.ts +112 -0
- package/cli/message-formatter-utils.js +68 -56
- package/cli/message-formatter-utils.ts +121 -0
- package/cli/message-formatters-normal.js +124 -259
- package/cli/message-formatters-normal.ts +250 -0
- package/cli/message-formatters-watch.js +81 -84
- package/cli/message-formatters-watch.ts +189 -0
- package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.js +3 -1
- package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
- package/lib/cluster/generated/protocol-schema.cjs +1 -1
- package/lib/cluster/generated/protocol-schema.mjs +1 -1
- package/lib/cluster/generated/protocol.d.cts +8 -0
- package/lib/cluster/generated/protocol.d.mts +8 -0
- package/lib/cluster/generated/protocol.d.ts +8 -0
- package/lib/clusters-registry.d.ts +23 -0
- package/lib/clusters-registry.js +17 -29
- package/lib/completion.d.ts +12 -0
- package/lib/completion.js +84 -94
- package/lib/compose-utils.d.ts +32 -0
- package/lib/compose-utils.js +57 -72
- package/lib/detached-startup.d.ts +83 -0
- package/lib/detached-startup.js +231 -302
- package/lib/docker-config.d.ts +43 -0
- package/lib/docker-config.js +150 -325
- package/lib/docker-env-auth.d.ts +17 -0
- package/lib/docker-env-auth.js +75 -0
- package/lib/git-remote-utils.d.ts +48 -0
- package/lib/git-remote-utils.js +147 -213
- package/lib/id-detector.d.ts +15 -0
- package/lib/id-detector.js +37 -41
- package/lib/path-check.d.ts +30 -0
- package/lib/path-check.js +42 -45
- package/lib/process-liveness.d.ts +16 -0
- package/lib/process-liveness.js +19 -12
- package/lib/provider-credential-path.d.ts +16 -0
- package/lib/provider-credential-path.js +31 -29
- package/lib/provider-defaults.d.ts +30 -0
- package/lib/provider-defaults.js +47 -42
- package/lib/provider-detection.d.ts +11 -0
- package/lib/provider-detection.js +91 -54
- package/lib/provider-names.d.ts +38 -0
- package/lib/provider-names.js +56 -64
- package/lib/repo-settings.d.ts +28 -0
- package/lib/repo-settings.js +83 -59
- package/lib/run-mode.d.ts +21 -0
- package/lib/run-mode.js +21 -20
- package/lib/run-plan.d.ts +28 -0
- package/lib/run-plan.js +17 -16
- package/lib/settings/claude-auth.d.ts +35 -0
- package/lib/settings/claude-auth.js +30 -47
- package/lib/settings-defaults.d.ts +20 -0
- package/lib/settings-defaults.js +149 -0
- package/lib/settings-error.d.ts +7 -0
- package/lib/settings-error.js +8 -0
- package/lib/settings-issue-providers.d.ts +10 -0
- package/lib/settings-issue-providers.js +12 -0
- package/lib/settings-models.d.ts +22 -0
- package/lib/settings-models.js +93 -0
- package/lib/settings-storage.d.ts +23 -0
- package/lib/settings-storage.js +205 -0
- package/lib/settings-validation.d.ts +7 -0
- package/lib/settings-validation.js +182 -0
- package/lib/settings.d.ts +29 -0
- package/lib/settings.js +41 -736
- package/lib/setup-apply-types.d.ts +66 -0
- package/lib/setup-apply-types.js +2 -0
- package/lib/setup-apply.d.ts +39 -0
- package/lib/setup-apply.js +267 -264
- package/lib/setup-journal.d.ts +41 -0
- package/lib/setup-journal.js +119 -76
- package/lib/setup-plan-types.d.ts +102 -0
- package/lib/setup-plan-types.js +2 -0
- package/lib/setup-plan.d.ts +30 -0
- package/lib/setup-plan.js +300 -324
- package/lib/setup-undo.d.ts +44 -0
- package/lib/setup-undo.js +61 -74
- package/lib/start-cluster-config.d.ts +26 -0
- package/lib/start-cluster-config.js +56 -0
- package/lib/start-cluster-environment.d.ts +40 -0
- package/lib/start-cluster-environment.js +134 -0
- package/lib/start-cluster-run-options.d.ts +53 -0
- package/lib/start-cluster-run-options.js +147 -0
- package/lib/start-cluster.d.ts +64 -0
- package/lib/start-cluster.js +98 -454
- package/lib/stream-json-parser.d.ts +17 -0
- package/lib/stream-json-parser.js +51 -52
- package/npm-shrinkwrap.json +2 -2
- package/package.json +12 -6
- package/scripts/postinstall.js +27 -0
- package/scripts/rust-distribution.js +23 -14
- package/src/agent/agent-command-proofs-context.js +35 -45
- package/src/agent/agent-command-proofs-context.ts +87 -0
- package/src/agent/agent-config-settings.js +19 -0
- package/src/agent/agent-config-settings.ts +41 -0
- package/src/agent/agent-config.js +122 -231
- package/src/agent/agent-config.ts +285 -0
- package/src/agent/agent-context-builder.js +38 -273
- package/src/agent/agent-context-builder.ts +51 -0
- package/src/agent/agent-context-environment-sections.js +105 -0
- package/src/agent/agent-context-environment-sections.ts +134 -0
- package/src/agent/agent-context-packs.js +165 -0
- package/src/agent/agent-context-packs.ts +296 -0
- package/src/agent/agent-context-prompt-sections.js +100 -0
- package/src/agent/agent-context-prompt-sections.ts +148 -0
- package/src/agent/agent-context-sections.js +25 -334
- package/src/agent/agent-context-sections.ts +36 -0
- package/src/agent/agent-context-sources.js +96 -149
- package/src/agent/agent-context-sources.ts +253 -0
- package/src/agent/agent-context-types.js +2 -0
- package/src/agent/agent-context-types.ts +132 -0
- package/src/agent/agent-context-validation-sections.js +73 -0
- package/src/agent/agent-context-validation-sections.ts +129 -0
- package/src/agent/agent-input-injector.js +99 -118
- package/src/agent/agent-input-injector.ts +195 -0
- package/src/agent/agent-liveness-poll.js +74 -78
- package/src/agent/agent-liveness-poll.ts +163 -0
- package/src/agent/agent-quality-gate-schema.js +77 -86
- package/src/agent/agent-quality-gate-schema.ts +135 -0
- package/src/agent/agent-quality-gates-context.js +44 -50
- package/src/agent/agent-quality-gates-context.ts +91 -0
- package/src/agent/agent-stuck-detector.js +171 -239
- package/src/agent/agent-stuck-detector.ts +288 -0
- package/src/agent/agent-trigger-evaluator.js +29 -46
- package/src/agent/agent-trigger-evaluator.ts +98 -0
- package/src/agent/context-metrics.js +110 -141
- package/src/agent/context-metrics.ts +261 -0
- package/src/agent/context-pack-builder.js +72 -358
- package/src/agent/context-pack-builder.ts +105 -0
- package/src/agent/context-pack-core.js +70 -0
- package/src/agent/context-pack-core.ts +96 -0
- package/src/agent/context-pack-selection.js +119 -0
- package/src/agent/context-pack-selection.ts +187 -0
- package/src/agent/context-pack-truncation.js +139 -0
- package/src/agent/context-pack-truncation.ts +208 -0
- package/src/agent/context-pack-types.js +2 -0
- package/src/agent/context-pack-types.ts +98 -0
- package/src/agent/context-replay-policy.js +30 -39
- package/src/agent/context-replay-policy.ts +71 -0
- package/src/agent/critical-agent-policy.js +6 -10
- package/src/agent/critical-agent-policy.ts +20 -0
- package/src/agent/guidance-queue.js +74 -87
- package/src/agent/guidance-queue.ts +166 -0
- package/src/agent/output-extraction-error-detail.js +45 -0
- package/src/agent/output-extraction-error-detail.ts +49 -0
- package/src/agent/output-extraction-failures.js +125 -0
- package/src/agent/output-extraction-failures.ts +149 -0
- package/src/agent/output-extraction-json.js +234 -0
- package/src/agent/output-extraction-json.ts +235 -0
- package/src/agent/output-extraction-pi.js +124 -0
- package/src/agent/output-extraction-pi.ts +137 -0
- package/src/agent/output-extraction-types.js +2 -0
- package/src/agent/output-extraction-types.ts +49 -0
- package/src/agent/output-extraction.js +17 -617
- package/src/agent/output-extraction.ts +30 -0
- package/src/agent/output-reformatter-errors.js +83 -0
- package/src/agent/output-reformatter-errors.ts +106 -0
- package/src/agent/output-reformatter-types.js +2 -0
- package/src/agent/output-reformatter-types.ts +86 -0
- package/src/agent/output-reformatter.js +140 -185
- package/src/agent/output-reformatter.ts +238 -0
- package/src/agent/pi-terminal-lifecycle-types.js +2 -0
- package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
- package/src/agent/pi-terminal-lifecycle.js +186 -206
- package/src/agent/pi-terminal-lifecycle.ts +297 -0
- package/src/agent/provider-control-plane.js +22 -21
- package/src/agent/provider-control-plane.ts +52 -0
- package/src/agent/provider-terminal-failure-types.js +2 -0
- package/src/agent/provider-terminal-failure-types.ts +60 -0
- package/src/agent/provider-terminal-failure.js +194 -191
- package/src/agent/provider-terminal-failure.ts +262 -0
- package/src/agent/rate-limit-backoff.js +31 -74
- package/src/agent/rate-limit-backoff.ts +71 -0
- package/src/agent/schema-utils.js +85 -125
- package/src/agent/schema-utils.ts +148 -0
- package/src/agent/structured-output-error.js +34 -33
- package/src/agent/structured-output-error.ts +105 -0
- package/src/agent/validation-platform.js +27 -27
- package/src/agent/validation-platform.ts +49 -0
- package/src/agent-cli-provider/adapters/codex.ts +3 -1
- package/src/attach/attach-client.js +232 -405
- package/src/attach/attach-client.ts +300 -0
- package/src/attach/attach-server-cleanup.js +43 -0
- package/src/attach/attach-server-cleanup.ts +39 -0
- package/src/attach/attach-server-clients.js +117 -0
- package/src/attach/attach-server-clients.ts +122 -0
- package/src/attach/attach-server-events.js +38 -0
- package/src/attach/attach-server-events.ts +36 -0
- package/src/attach/attach-server-pty.js +45 -0
- package/src/attach/attach-server-pty.ts +64 -0
- package/src/attach/attach-server-runtime.js +73 -0
- package/src/attach/attach-server-runtime.ts +62 -0
- package/src/attach/attach-server-socket.js +28 -0
- package/src/attach/attach-server-socket.ts +23 -0
- package/src/attach/attach-server-types.js +2 -0
- package/src/attach/attach-server-types.ts +82 -0
- package/src/attach/attach-server.js +106 -523
- package/src/attach/attach-server.ts +158 -0
- package/src/attach/index.js +18 -35
- package/src/attach/index.ts +18 -0
- package/src/attach/protocol.js +95 -184
- package/src/attach/protocol.ts +181 -0
- package/src/attach/ring-buffer.js +76 -102
- package/src/attach/ring-buffer.ts +109 -0
- package/src/attach/send-input.js +64 -75
- package/src/attach/send-input.ts +94 -0
- package/src/attach/socket-discovery.js +164 -218
- package/src/attach/socket-discovery.ts +230 -0
- package/src/attach/socket-paths.js +42 -61
- package/src/attach/socket-paths.ts +81 -0
- package/src/claude-credentials.js +51 -54
- package/src/claude-credentials.ts +89 -0
- package/src/cluster/generated/protocol-schema.ts +1 -1
- package/src/cluster/generated/protocol.ts +2 -1
- package/src/command-proofs.js +110 -141
- package/src/command-proofs.ts +216 -0
- package/src/config-router.js +81 -73
- package/src/config-router.ts +131 -0
- package/src/copy-worker.js +53 -29
- package/src/copy-worker.ts +75 -0
- package/src/darwin-keychain-boundary.js +80 -111
- package/src/darwin-keychain-boundary.ts +148 -0
- package/src/guidance-topics.js +4 -5
- package/src/guidance-topics.ts +10 -0
- package/src/input-helpers.js +33 -54
- package/src/input-helpers.ts +58 -0
- package/src/ledger-sequence.js +45 -48
- package/src/ledger-sequence.ts +63 -0
- package/src/legacy-lib/clusters-registry.ts +40 -0
- package/src/legacy-lib/completion.ts +148 -0
- package/src/legacy-lib/compose-utils.ts +102 -0
- package/src/legacy-lib/detached-startup.ts +449 -0
- package/src/legacy-lib/docker-config.ts +282 -0
- package/src/legacy-lib/docker-env-auth.ts +116 -0
- package/src/legacy-lib/git-remote-utils.ts +244 -0
- package/src/legacy-lib/id-detector.ts +57 -0
- package/src/legacy-lib/js-yaml.d.ts +3 -0
- package/src/legacy-lib/omelette.d.ts +15 -0
- package/src/legacy-lib/path-check.ts +89 -0
- package/src/legacy-lib/process-liveness.ts +36 -0
- package/src/legacy-lib/provider-credential-path.ts +57 -0
- package/src/legacy-lib/provider-defaults.ts +114 -0
- package/src/legacy-lib/provider-detection.ts +67 -0
- package/src/legacy-lib/provider-names.ts +126 -0
- package/src/legacy-lib/repo-settings.ts +88 -0
- package/src/legacy-lib/run-mode.ts +58 -0
- package/src/legacy-lib/run-plan.ts +49 -0
- package/src/legacy-lib/settings/claude-auth.ts +80 -0
- package/src/legacy-lib/settings-defaults.ts +212 -0
- package/src/legacy-lib/settings-error.ts +8 -0
- package/src/legacy-lib/settings-issue-providers.ts +18 -0
- package/src/legacy-lib/settings-models.ts +124 -0
- package/src/legacy-lib/settings-storage.ts +277 -0
- package/src/legacy-lib/settings-validation.ts +220 -0
- package/src/legacy-lib/settings.ts +87 -0
- package/src/legacy-lib/setup-apply-types.ts +70 -0
- package/src/legacy-lib/setup-apply.ts +456 -0
- package/src/legacy-lib/setup-journal.ts +185 -0
- package/src/legacy-lib/setup-plan-types.ts +96 -0
- package/src/legacy-lib/setup-plan.ts +500 -0
- package/src/legacy-lib/setup-undo.ts +142 -0
- package/src/legacy-lib/start-cluster-config.ts +124 -0
- package/src/legacy-lib/start-cluster-environment.ts +165 -0
- package/src/legacy-lib/start-cluster-run-options.ts +279 -0
- package/src/legacy-lib/start-cluster.ts +237 -0
- package/src/legacy-lib/stream-json-parser.ts +88 -0
- package/src/message-buffer.js +55 -71
- package/src/message-buffer.ts +107 -0
- package/src/message-bus-bridge.js +92 -133
- package/src/message-bus-bridge.ts +149 -0
- package/src/name-generator-shared.js +220 -0
- package/src/name-generator-shared.ts +231 -0
- package/src/name-generator.js +8 -217
- package/src/name-generator.ts +27 -0
- package/src/omp-blob-root.js +83 -64
- package/src/omp-blob-root.ts +116 -0
- package/src/omp-config-overlay.js +65 -38
- package/src/omp-config-overlay.ts +110 -0
- package/src/omp-execution-fingerprint.js +38 -43
- package/src/omp-execution-fingerprint.ts +92 -0
- package/src/omp-session-limits.js +10 -15
- package/src/omp-session-limits.ts +53 -0
- package/src/omp-session-partition.js +2 -2
- package/src/omp-session-verifier.js +1 -1
- package/src/orchestrator.js +19 -4
- package/src/providers/anthropic/index.js +3 -1
- package/src/providers/anthropic/index.ts +13 -0
- package/src/providers/capabilities.js +19 -27
- package/src/providers/capabilities.ts +44 -0
- package/src/providers/google/index.js +3 -1
- package/src/providers/google/index.ts +13 -0
- package/src/providers/openai/index.js +3 -1
- package/src/providers/openai/index.ts +13 -0
- package/src/providers/opencode/index.js +3 -1
- package/src/providers/opencode/index.ts +13 -0
- package/src/quality-gates.js +67 -127
- package/src/quality-gates.ts +149 -0
- package/src/repo-settings-access.js +40 -0
- package/src/repo-settings-access.ts +64 -0
- package/src/schemas/sub-cluster.js +127 -183
- package/src/schemas/sub-cluster.ts +238 -0
- package/src/state-snapshot-normalization.js +224 -0
- package/src/state-snapshot-normalization.ts +222 -0
- package/src/state-snapshot.js +192 -359
- package/src/state-snapshot.ts +291 -0
- package/src/state-snapshotter.js +118 -130
- package/src/state-snapshotter.ts +167 -0
- package/src/sub-cluster-wrapper.js +4 -13
- package/src/task-run-model-args.js +87 -124
- package/src/task-run-model-args.ts +204 -0
- package/src/task-runner.js +5 -25
- package/src/task-runner.ts +28 -0
- package/src/task-startup-error.js +73 -58
- package/src/task-startup-error.ts +126 -0
- package/src/template-validation/consensus-gate-contracts.js +2 -0
- package/src/template-validation/consensus-gate-contracts.ts +70 -0
- package/src/template-validation/consensus-gate-scenarios.js +76 -0
- package/src/template-validation/consensus-gate-scenarios.ts +130 -0
- package/src/template-validation/consensus-gate-stage.js +34 -0
- package/src/template-validation/consensus-gate-stage.ts +56 -0
- package/src/template-validation/random-topology-contracts.js +2 -0
- package/src/template-validation/random-topology-contracts.ts +54 -0
- package/src/template-validation/random-topology-dispatch.js +25 -0
- package/src/template-validation/random-topology-dispatch.ts +33 -0
- package/src/template-validation/random-topology-message-loop.js +53 -0
- package/src/template-validation/random-topology-message-loop.ts +73 -0
- package/src/template-validation/random-topology-operations.js +79 -0
- package/src/template-validation/random-topology-operations.ts +101 -0
- package/src/template-validation/random-topology-runtime.js +25 -0
- package/src/template-validation/random-topology-runtime.ts +43 -0
- package/src/template-validation/random-topology-scenario.js +52 -0
- package/src/template-validation/random-topology-scenario.ts +57 -0
- package/src/template-validation/random-topology-schema.js +159 -0
- package/src/template-validation/random-topology-schema.ts +190 -0
- package/src/template-validation/random-topology-state.js +28 -0
- package/src/template-validation/random-topology-state.ts +30 -0
- package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
- package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
- package/src/template-validation/random-topology-trigger.js +75 -0
- package/src/template-validation/random-topology-trigger.ts +88 -0
- package/src/template-validation/report-formatter.js +40 -46
- package/src/template-validation/report-formatter.ts +101 -0
- package/src/template-validation/simulate-consensus-gates.js +111 -302
- package/src/template-validation/simulate-consensus-gates.ts +196 -0
- package/src/template-validation/simulate-random-topology.js +26 -519
- package/src/template-validation/simulate-random-topology.ts +57 -0
- package/src/template-validation/simulate-two-stage-validation.js +41 -265
- package/src/template-validation/simulate-two-stage-validation.ts +55 -0
- package/src/template-validation/simulation-agent-runtime.js +25 -0
- package/src/template-validation/simulation-agent-runtime.ts +40 -0
- package/src/template-validation/simulation-agent.js +29 -0
- package/src/template-validation/simulation-agent.ts +73 -0
- package/src/template-validation/simulation-runtime.js +34 -0
- package/src/template-validation/simulation-runtime.ts +72 -0
- package/src/template-validation/two-stage-contracts.js +2 -0
- package/src/template-validation/two-stage-contracts.ts +41 -0
- package/src/template-validation/two-stage-inputs.js +21 -0
- package/src/template-validation/two-stage-inputs.ts +29 -0
- package/src/template-validation/two-stage-results.js +30 -0
- package/src/template-validation/two-stage-results.ts +40 -0
- package/src/template-validation/two-stage-scenario.js +86 -0
- package/src/template-validation/two-stage-scenario.ts +120 -0
- package/src/worktree-claude-config.js +182 -220
- package/src/worktree-claude-config.ts +272 -0
- package/src/worktree-tooling-env.js +103 -125
- package/src/worktree-tooling-env.ts +142 -0
- package/task-lib/completion.js +2 -3
- package/task-lib/completion.ts +9 -0
- package/task-lib/config.js +1 -4
- package/task-lib/config.ts +11 -0
- package/task-lib/name-generator.js +4 -226
- package/task-lib/name-generator.ts +11 -0
- package/task-lib/omp-session-cleanup.js +1 -1
- package/task-lib/omp-storage-root.js +8 -12
- package/task-lib/omp-storage-root.ts +62 -0
- package/task-lib/process-termination.js +143 -166
- package/task-lib/process-termination.ts +268 -0
|
@@ -1,164 +1,154 @@
|
|
|
1
1
|
import { execFile } from 'child_process';
|
|
2
2
|
import { promisify } from 'util';
|
|
3
|
-
|
|
4
3
|
const execFileAsync = promisify(execFile);
|
|
5
|
-
|
|
6
4
|
export function isProcessRunning(pid) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
if (!pid)
|
|
6
|
+
return false;
|
|
7
|
+
try {
|
|
8
|
+
process.kill(pid, 0);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
14
|
}
|
|
15
|
-
|
|
16
15
|
export function killTask(pid) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
if (!pid)
|
|
17
|
+
return false;
|
|
18
|
+
try {
|
|
19
|
+
process.kill(pid, 'SIGTERM');
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
24
25
|
}
|
|
25
|
-
|
|
26
26
|
function sleep(ms) {
|
|
27
|
-
|
|
27
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
28
28
|
}
|
|
29
|
-
|
|
30
29
|
function normalizeTerminationOwnership(pid, options) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return { terminationStrategy, processGroupId };
|
|
30
|
+
const terminationStrategy = options.terminationStrategy || 'process';
|
|
31
|
+
const processGroupId = Number(options.processGroupId) || null;
|
|
32
|
+
if (terminationStrategy === 'process-group') {
|
|
33
|
+
if (process.platform === 'win32') {
|
|
34
|
+
throw new Error('Process-group termination is unavailable on Windows; use terminationStrategy "process-tree"');
|
|
35
|
+
}
|
|
36
|
+
if (!processGroupId || processGroupId !== pid) {
|
|
37
|
+
throw new Error(`Refusing process-group termination for PID ${pid}: owned processGroupId must equal the provider root PID`);
|
|
38
|
+
}
|
|
39
|
+
return { terminationStrategy, processGroupId };
|
|
40
|
+
}
|
|
41
|
+
if (terminationStrategy === 'process-tree' && process.platform !== 'win32') {
|
|
42
|
+
throw new Error('Process-tree termination is only supported on Windows; use terminationStrategy ' +
|
|
43
|
+
`"process-group" on ${process.platform}`);
|
|
44
|
+
}
|
|
45
|
+
if (!['process', 'process-tree'].includes(terminationStrategy)) {
|
|
46
|
+
throw new Error(`Unsupported termination strategy: ${terminationStrategy}`);
|
|
47
|
+
}
|
|
48
|
+
return { terminationStrategy, processGroupId };
|
|
49
|
+
}
|
|
50
|
+
function errorHasCode(error, code) {
|
|
51
|
+
return typeof error === 'object' && error !== null && 'code' in error && error.code === code;
|
|
52
|
+
}
|
|
53
|
+
function errorMessage(error) {
|
|
54
|
+
return error instanceof Error ? error.message : String(error);
|
|
58
55
|
}
|
|
59
|
-
|
|
60
56
|
function isProcessGroupRunning(processGroupId) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
try {
|
|
58
|
+
process.kill(-processGroupId, 0);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
return errorHasCode(error, 'EPERM');
|
|
63
|
+
}
|
|
67
64
|
}
|
|
68
|
-
|
|
69
65
|
export function isOwnedProcessTreeRunning(pid, options = {}) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
66
|
+
if (!pid)
|
|
67
|
+
return false;
|
|
68
|
+
const ownership = normalizeTerminationOwnership(pid, options);
|
|
69
|
+
if (ownership.terminationStrategy === 'process-group') {
|
|
70
|
+
return isProcessGroupRunning(ownership.processGroupId);
|
|
71
|
+
}
|
|
72
|
+
return isProcessRunning(pid);
|
|
76
73
|
}
|
|
77
|
-
|
|
78
74
|
async function signalWindowsProcessTree(pid, force) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
const args = ['/PID', String(pid), '/T'];
|
|
76
|
+
if (force)
|
|
77
|
+
args.push('/F');
|
|
78
|
+
await execFileAsync('taskkill', args, { windowsHide: true });
|
|
82
79
|
}
|
|
83
|
-
|
|
84
80
|
async function signalOwnedProcessTree(pid, signal, ownership) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
81
|
+
if (ownership.terminationStrategy === 'process-group') {
|
|
82
|
+
process.kill(-ownership.processGroupId, signal);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (ownership.terminationStrategy === 'process-tree') {
|
|
86
|
+
await signalWindowsProcessTree(pid, signal === 'SIGKILL');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
process.kill(pid, signal);
|
|
94
90
|
}
|
|
95
|
-
|
|
96
91
|
async function waitForOwnedProcessTreeExit(pid, ownership, timeoutMs, pollMs) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
92
|
+
const deadline = Date.now() + timeoutMs;
|
|
93
|
+
const options = {
|
|
94
|
+
terminationStrategy: ownership.terminationStrategy,
|
|
95
|
+
processGroupId: ownership.processGroupId,
|
|
96
|
+
};
|
|
97
|
+
while (Date.now() < deadline) {
|
|
98
|
+
if (!isOwnedProcessTreeRunning(pid, options))
|
|
99
|
+
return true;
|
|
100
|
+
await sleep(pollMs);
|
|
101
|
+
}
|
|
102
|
+
return !isOwnedProcessTreeRunning(pid, options);
|
|
107
103
|
}
|
|
108
|
-
|
|
109
104
|
function terminationResult(ownership, overrides = {}) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
105
|
+
const degraded = ownership.terminationStrategy === 'process';
|
|
106
|
+
return {
|
|
107
|
+
terminated: false,
|
|
108
|
+
alreadyDead: false,
|
|
109
|
+
escalated: false,
|
|
110
|
+
signal: null,
|
|
111
|
+
scope: ownership.terminationStrategy,
|
|
112
|
+
degraded,
|
|
113
|
+
degradedReason: degraded
|
|
114
|
+
? 'Task has no process-tree ownership metadata; only the provider root PID can be terminated'
|
|
115
|
+
: null,
|
|
116
|
+
...overrides,
|
|
117
|
+
};
|
|
123
118
|
}
|
|
124
|
-
|
|
125
119
|
async function signalAndWait(pid, ownership, signal, timeoutMs, pollMs) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
} catch (error) {
|
|
130
|
-
if (
|
|
131
|
-
!isOwnedProcessTreeRunning(pid, {
|
|
132
|
-
terminationStrategy: ownership.terminationStrategy,
|
|
133
|
-
processGroupId: ownership.processGroupId,
|
|
134
|
-
})
|
|
135
|
-
) {
|
|
136
|
-
return terminationResult(ownership, {
|
|
137
|
-
terminated: true,
|
|
138
|
-
alreadyDead: signal === 'SIGTERM',
|
|
139
|
-
escalated,
|
|
140
|
-
signal: escalated ? signal : null,
|
|
141
|
-
});
|
|
120
|
+
const escalated = signal === 'SIGKILL';
|
|
121
|
+
try {
|
|
122
|
+
await signalOwnedProcessTree(pid, signal, ownership);
|
|
142
123
|
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
if (!isOwnedProcessTreeRunning(pid, {
|
|
126
|
+
terminationStrategy: ownership.terminationStrategy,
|
|
127
|
+
processGroupId: ownership.processGroupId,
|
|
128
|
+
})) {
|
|
129
|
+
return terminationResult(ownership, {
|
|
130
|
+
terminated: true,
|
|
131
|
+
alreadyDead: signal === 'SIGTERM',
|
|
132
|
+
escalated,
|
|
133
|
+
signal: escalated ? signal : null,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return terminationResult(ownership, {
|
|
137
|
+
escalated,
|
|
138
|
+
signal,
|
|
139
|
+
error: errorMessage(error),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
const terminated = await waitForOwnedProcessTreeExit(pid, ownership, timeoutMs, pollMs);
|
|
143
143
|
return terminationResult(ownership, {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
terminated,
|
|
145
|
+
escalated,
|
|
146
|
+
signal,
|
|
147
|
+
error: terminated || !escalated
|
|
148
|
+
? null
|
|
149
|
+
: `Owned ${ownership.terminationStrategy} for PID ${pid} survived ${signal}`,
|
|
147
150
|
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const terminated = await waitForOwnedProcessTreeExit(pid, ownership, timeoutMs, pollMs);
|
|
151
|
-
return terminationResult(ownership, {
|
|
152
|
-
terminated,
|
|
153
|
-
escalated,
|
|
154
|
-
signal,
|
|
155
|
-
error:
|
|
156
|
-
terminated || !escalated
|
|
157
|
-
? null
|
|
158
|
-
: `Owned ${ownership.terminationStrategy} for PID ${pid} survived ${signal}`,
|
|
159
|
-
});
|
|
160
151
|
}
|
|
161
|
-
|
|
162
152
|
/**
|
|
163
153
|
* Terminate an owned provider process tree. Watchers create a dedicated process
|
|
164
154
|
* group on POSIX and persist that ownership boundary; Windows uses taskkill /T.
|
|
@@ -166,37 +156,24 @@ async function signalAndWait(pid, ownership, signal, timeoutMs, pollMs) {
|
|
|
166
156
|
* and report the degraded scope explicitly.
|
|
167
157
|
*/
|
|
168
158
|
export async function terminateProcess(pid, options = {}) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
ownership,
|
|
189
|
-
'SIGTERM',
|
|
190
|
-
options.graceMs ?? 5000,
|
|
191
|
-
options.pollMs ?? 50
|
|
192
|
-
);
|
|
193
|
-
if (graceful.terminated || graceful.error) return graceful;
|
|
194
|
-
|
|
195
|
-
return signalAndWait(
|
|
196
|
-
pid,
|
|
197
|
-
ownership,
|
|
198
|
-
'SIGKILL',
|
|
199
|
-
options.hardKillWaitMs ?? 1000,
|
|
200
|
-
options.pollMs ?? 50
|
|
201
|
-
);
|
|
159
|
+
let ownership;
|
|
160
|
+
try {
|
|
161
|
+
ownership = normalizeTerminationOwnership(pid, options);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
return {
|
|
165
|
+
terminated: false,
|
|
166
|
+
alreadyDead: false,
|
|
167
|
+
escalated: false,
|
|
168
|
+
signal: null,
|
|
169
|
+
error: errorMessage(error),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (!isOwnedProcessTreeRunning(pid, options)) {
|
|
173
|
+
return terminationResult(ownership, { terminated: true, alreadyDead: true });
|
|
174
|
+
}
|
|
175
|
+
const graceful = await signalAndWait(pid, ownership, 'SIGTERM', options.graceMs ?? 5000, options.pollMs ?? 50);
|
|
176
|
+
if (graceful.terminated || graceful.error)
|
|
177
|
+
return graceful;
|
|
178
|
+
return signalAndWait(pid, ownership, 'SIGKILL', options.hardKillWaitMs ?? 1000, options.pollMs ?? 50);
|
|
202
179
|
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { execFile } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
|
|
4
|
+
const execFileAsync = promisify(execFile);
|
|
5
|
+
|
|
6
|
+
type TerminationStrategy = 'process' | 'process-group' | 'process-tree';
|
|
7
|
+
type TerminationSignal = 'SIGTERM' | 'SIGKILL';
|
|
8
|
+
|
|
9
|
+
type TerminationOwnership =
|
|
10
|
+
| { readonly terminationStrategy: 'process-group'; readonly processGroupId: number }
|
|
11
|
+
| {
|
|
12
|
+
readonly terminationStrategy: 'process' | 'process-tree';
|
|
13
|
+
readonly processGroupId: number | null;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
interface TerminationOptions {
|
|
17
|
+
readonly terminationStrategy?: TerminationStrategy;
|
|
18
|
+
readonly processGroupId?: number | null;
|
|
19
|
+
readonly graceMs?: number;
|
|
20
|
+
readonly hardKillWaitMs?: number;
|
|
21
|
+
readonly pollMs?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface TerminationResult {
|
|
25
|
+
readonly terminated: boolean;
|
|
26
|
+
readonly alreadyDead: boolean;
|
|
27
|
+
readonly escalated: boolean;
|
|
28
|
+
readonly signal: TerminationSignal | null;
|
|
29
|
+
readonly scope?: TerminationStrategy;
|
|
30
|
+
readonly degraded?: boolean;
|
|
31
|
+
readonly degradedReason?: string | null;
|
|
32
|
+
readonly error?: string | null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function isProcessRunning(pid: number | null | undefined): boolean {
|
|
36
|
+
if (!pid) return false;
|
|
37
|
+
try {
|
|
38
|
+
process.kill(pid, 0);
|
|
39
|
+
return true;
|
|
40
|
+
} catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function killTask(pid: number | null | undefined): boolean {
|
|
46
|
+
if (!pid) return false;
|
|
47
|
+
try {
|
|
48
|
+
process.kill(pid, 'SIGTERM');
|
|
49
|
+
return true;
|
|
50
|
+
} catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function sleep(ms: number): Promise<void> {
|
|
56
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function normalizeTerminationOwnership(
|
|
60
|
+
pid: number,
|
|
61
|
+
options: TerminationOptions
|
|
62
|
+
): TerminationOwnership {
|
|
63
|
+
const terminationStrategy = options.terminationStrategy || 'process';
|
|
64
|
+
const processGroupId = Number(options.processGroupId) || null;
|
|
65
|
+
|
|
66
|
+
if (terminationStrategy === 'process-group') {
|
|
67
|
+
if (process.platform === 'win32') {
|
|
68
|
+
throw new Error(
|
|
69
|
+
'Process-group termination is unavailable on Windows; use terminationStrategy "process-tree"'
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
if (!processGroupId || processGroupId !== pid) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`Refusing process-group termination for PID ${pid}: owned processGroupId must equal the provider root PID`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
return { terminationStrategy, processGroupId };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (terminationStrategy === 'process-tree' && process.platform !== 'win32') {
|
|
81
|
+
throw new Error(
|
|
82
|
+
'Process-tree termination is only supported on Windows; use terminationStrategy ' +
|
|
83
|
+
`"process-group" on ${process.platform}`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!['process', 'process-tree'].includes(terminationStrategy)) {
|
|
88
|
+
throw new Error(`Unsupported termination strategy: ${terminationStrategy}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { terminationStrategy, processGroupId };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function errorHasCode(error: unknown, code: string): boolean {
|
|
95
|
+
return typeof error === 'object' && error !== null && 'code' in error && error.code === code;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function errorMessage(error: unknown): string {
|
|
99
|
+
return error instanceof Error ? error.message : String(error);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function isProcessGroupRunning(processGroupId: number): boolean {
|
|
103
|
+
try {
|
|
104
|
+
process.kill(-processGroupId, 0);
|
|
105
|
+
return true;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
return errorHasCode(error, 'EPERM');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function isOwnedProcessTreeRunning(
|
|
112
|
+
pid: number | null | undefined,
|
|
113
|
+
options: TerminationOptions = {}
|
|
114
|
+
): boolean {
|
|
115
|
+
if (!pid) return false;
|
|
116
|
+
const ownership = normalizeTerminationOwnership(pid, options);
|
|
117
|
+
if (ownership.terminationStrategy === 'process-group') {
|
|
118
|
+
return isProcessGroupRunning(ownership.processGroupId);
|
|
119
|
+
}
|
|
120
|
+
return isProcessRunning(pid);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function signalWindowsProcessTree(pid: number, force: boolean): Promise<void> {
|
|
124
|
+
const args = ['/PID', String(pid), '/T'];
|
|
125
|
+
if (force) args.push('/F');
|
|
126
|
+
await execFileAsync('taskkill', args, { windowsHide: true });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function signalOwnedProcessTree(
|
|
130
|
+
pid: number,
|
|
131
|
+
signal: TerminationSignal,
|
|
132
|
+
ownership: TerminationOwnership
|
|
133
|
+
): Promise<void> {
|
|
134
|
+
if (ownership.terminationStrategy === 'process-group') {
|
|
135
|
+
process.kill(-ownership.processGroupId, signal);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (ownership.terminationStrategy === 'process-tree') {
|
|
139
|
+
await signalWindowsProcessTree(pid, signal === 'SIGKILL');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
process.kill(pid, signal);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function waitForOwnedProcessTreeExit(
|
|
146
|
+
pid: number,
|
|
147
|
+
ownership: TerminationOwnership,
|
|
148
|
+
timeoutMs: number,
|
|
149
|
+
pollMs: number
|
|
150
|
+
): Promise<boolean> {
|
|
151
|
+
const deadline = Date.now() + timeoutMs;
|
|
152
|
+
const options: TerminationOptions = {
|
|
153
|
+
terminationStrategy: ownership.terminationStrategy,
|
|
154
|
+
processGroupId: ownership.processGroupId,
|
|
155
|
+
};
|
|
156
|
+
while (Date.now() < deadline) {
|
|
157
|
+
if (!isOwnedProcessTreeRunning(pid, options)) return true;
|
|
158
|
+
await sleep(pollMs);
|
|
159
|
+
}
|
|
160
|
+
return !isOwnedProcessTreeRunning(pid, options);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function terminationResult(
|
|
164
|
+
ownership: TerminationOwnership,
|
|
165
|
+
overrides: Partial<TerminationResult> = {}
|
|
166
|
+
): TerminationResult {
|
|
167
|
+
const degraded = ownership.terminationStrategy === 'process';
|
|
168
|
+
return {
|
|
169
|
+
terminated: false,
|
|
170
|
+
alreadyDead: false,
|
|
171
|
+
escalated: false,
|
|
172
|
+
signal: null,
|
|
173
|
+
scope: ownership.terminationStrategy,
|
|
174
|
+
degraded,
|
|
175
|
+
degradedReason: degraded
|
|
176
|
+
? 'Task has no process-tree ownership metadata; only the provider root PID can be terminated'
|
|
177
|
+
: null,
|
|
178
|
+
...overrides,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async function signalAndWait(
|
|
183
|
+
pid: number,
|
|
184
|
+
ownership: TerminationOwnership,
|
|
185
|
+
signal: TerminationSignal,
|
|
186
|
+
timeoutMs: number,
|
|
187
|
+
pollMs: number
|
|
188
|
+
): Promise<TerminationResult> {
|
|
189
|
+
const escalated = signal === 'SIGKILL';
|
|
190
|
+
try {
|
|
191
|
+
await signalOwnedProcessTree(pid, signal, ownership);
|
|
192
|
+
} catch (error) {
|
|
193
|
+
if (
|
|
194
|
+
!isOwnedProcessTreeRunning(pid, {
|
|
195
|
+
terminationStrategy: ownership.terminationStrategy,
|
|
196
|
+
processGroupId: ownership.processGroupId,
|
|
197
|
+
})
|
|
198
|
+
) {
|
|
199
|
+
return terminationResult(ownership, {
|
|
200
|
+
terminated: true,
|
|
201
|
+
alreadyDead: signal === 'SIGTERM',
|
|
202
|
+
escalated,
|
|
203
|
+
signal: escalated ? signal : null,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
return terminationResult(ownership, {
|
|
207
|
+
escalated,
|
|
208
|
+
signal,
|
|
209
|
+
error: errorMessage(error),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const terminated = await waitForOwnedProcessTreeExit(pid, ownership, timeoutMs, pollMs);
|
|
214
|
+
return terminationResult(ownership, {
|
|
215
|
+
terminated,
|
|
216
|
+
escalated,
|
|
217
|
+
signal,
|
|
218
|
+
error:
|
|
219
|
+
terminated || !escalated
|
|
220
|
+
? null
|
|
221
|
+
: `Owned ${ownership.terminationStrategy} for PID ${pid} survived ${signal}`,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Terminate an owned provider process tree. Watchers create a dedicated process
|
|
227
|
+
* group on POSIX and persist that ownership boundary; Windows uses taskkill /T.
|
|
228
|
+
* Legacy tasks without ownership metadata fall back to root-only termination
|
|
229
|
+
* and report the degraded scope explicitly.
|
|
230
|
+
*/
|
|
231
|
+
export async function terminateProcess(
|
|
232
|
+
pid: number,
|
|
233
|
+
options: TerminationOptions = {}
|
|
234
|
+
): Promise<TerminationResult> {
|
|
235
|
+
let ownership: TerminationOwnership;
|
|
236
|
+
try {
|
|
237
|
+
ownership = normalizeTerminationOwnership(pid, options);
|
|
238
|
+
} catch (error) {
|
|
239
|
+
return {
|
|
240
|
+
terminated: false,
|
|
241
|
+
alreadyDead: false,
|
|
242
|
+
escalated: false,
|
|
243
|
+
signal: null,
|
|
244
|
+
error: errorMessage(error),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (!isOwnedProcessTreeRunning(pid, options)) {
|
|
249
|
+
return terminationResult(ownership, { terminated: true, alreadyDead: true });
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const graceful = await signalAndWait(
|
|
253
|
+
pid,
|
|
254
|
+
ownership,
|
|
255
|
+
'SIGTERM',
|
|
256
|
+
options.graceMs ?? 5000,
|
|
257
|
+
options.pollMs ?? 50
|
|
258
|
+
);
|
|
259
|
+
if (graceful.terminated || graceful.error) return graceful;
|
|
260
|
+
|
|
261
|
+
return signalAndWait(
|
|
262
|
+
pid,
|
|
263
|
+
ownership,
|
|
264
|
+
'SIGKILL',
|
|
265
|
+
options.hardKillWaitMs ?? 1000,
|
|
266
|
+
options.pollMs ?? 50
|
|
267
|
+
);
|
|
268
|
+
}
|