stitchkit 0.103.9 → 0.103.11

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
  3. package/dist/agent-runtime/sandbox-process-owner.d.ts.map +1 -1
  4. package/dist/entrypoints/agent-runtime/coding-tools.js +2 -1
  5. package/dist/entrypoints/agent-runtime/sandbox.js +28 -14
  6. package/dist/entrypoints/application/diagnostic-journal.js +2 -1
  7. package/dist/entrypoints/files.js +14 -4
  8. package/dist/entrypoints/process.d.ts +2 -1
  9. package/dist/entrypoints/process.d.ts.map +1 -1
  10. package/dist/entrypoints/process.js +9 -2
  11. package/dist/index-32jkwkdm.js +565 -0
  12. package/dist/{index-a4ajxwmb.js → index-g4jxe7ve.js} +113 -131
  13. package/dist/index-nybn2err.js +213 -0
  14. package/dist/index-ttf0y7b8.js +246 -0
  15. package/dist/internal/exclusive-lock-read.d.ts +20 -0
  16. package/dist/internal/exclusive-lock-read.d.ts.map +1 -0
  17. package/dist/internal/exclusive-lock.d.ts +3 -1
  18. package/dist/internal/exclusive-lock.d.ts.map +1 -1
  19. package/dist/internal/process-instance.d.ts +46 -9
  20. package/dist/internal/process-instance.d.ts.map +1 -1
  21. package/dist/internal/with-exclusive-lock.d.ts +4 -3
  22. package/dist/internal/with-exclusive-lock.d.ts.map +1 -1
  23. package/dist/process/command-owner.d.ts +7 -2
  24. package/dist/process/command-owner.d.ts.map +1 -1
  25. package/dist/process/contract.d.ts +22 -1
  26. package/dist/process/contract.d.ts.map +1 -1
  27. package/dist/process/group.d.ts +6 -1
  28. package/dist/process/group.d.ts.map +1 -1
  29. package/dist/process/launch.d.ts +65 -0
  30. package/dist/process/launch.d.ts.map +1 -0
  31. package/dist/process/leader-settlement.d.ts +6 -0
  32. package/dist/process/leader-settlement.d.ts.map +1 -0
  33. package/dist/process/start-failure.d.ts +7 -0
  34. package/dist/process/start-failure.d.ts.map +1 -0
  35. package/llms/agent-runtime.txt +7 -1
  36. package/llms/files.txt +1 -1
  37. package/llms/process.txt +115 -2
  38. package/llms-full.txt +123 -4
  39. package/llms.txt +3 -3
  40. package/native/darwin-arm64.node +0 -0
  41. package/native/darwin-x64.node +0 -0
  42. package/package.json +2 -2
  43. package/dist/index-7kxw1awn.js +0 -328
  44. package/dist/index-eeqmg7qm.js +0 -202
@@ -0,0 +1,565 @@
1
+ import {
2
+ raceAbort
3
+ } from "./index-mbnnw3f2.js";
4
+
5
+ // src/process/contract.ts
6
+ import { z } from "zod";
7
+ var NativeCommandSettlementSchema = z.discriminatedUnion("kind", [
8
+ z.object({
9
+ kind: z.literal("exit"),
10
+ exitCode: z.number().int().nullable(),
11
+ signal: z.string().nullable()
12
+ }),
13
+ z.object({ kind: z.literal("error"), cause: z.unknown() })
14
+ ]);
15
+ var NativeCommandOptionsSchema = z.strictObject({
16
+ executable: z.string().min(1),
17
+ args: z.array(z.string()).default([]),
18
+ cwd: z.string().optional(),
19
+ env: z.record(z.string(), z.string()).optional(),
20
+ envPolicy: z.enum(["declared-only", "ambient"]).default("declared-only"),
21
+ signal: z.custom((v) => v instanceof AbortSignal).optional(),
22
+ timeoutMs: z.number().int().positive().max(2147483647).optional(),
23
+ maxOutputBytes: z.number().int().positive().optional(),
24
+ capture: z.boolean().default(false),
25
+ stdin: z.custom((v) => v instanceof Uint8Array).optional(),
26
+ maxStdinBytes: z.number().int().positive().default(1024 * 1024),
27
+ onOutput: z.custom((v) => typeof v === "function").optional(),
28
+ onLeaderSettled: z.custom((v) => typeof v === "function").optional(),
29
+ killGraceMs: z.number().int().nonnegative().max(1e4).default(100),
30
+ cleanupTimeoutMs: z.number().int().positive().max(30000).default(2000)
31
+ }).superRefine((input, ctx) => {
32
+ if (!input.signal && input.timeoutMs === undefined)
33
+ ctx.addIssue({ code: "custom", message: "Declare a caller signal or a finite timeout" });
34
+ if (input.capture && input.maxOutputBytes === undefined)
35
+ ctx.addIssue({
36
+ code: "custom",
37
+ message: "Capture requires a finite combined output budget"
38
+ });
39
+ if (input.stdin && input.stdin.byteLength > input.maxStdinBytes)
40
+ ctx.addIssue({ code: "custom", message: "stdin exceeds maxStdinBytes" });
41
+ });
42
+ var NativeCommandResultSchema = z.object({
43
+ exitCode: z.number().int().nullable(),
44
+ signal: z.string().nullable(),
45
+ stdout: z.instanceof(Uint8Array),
46
+ stderr: z.instanceof(Uint8Array)
47
+ });
48
+ var NativeCommandLimitReasonSchema = z.enum(["deadline", "output-budget"]);
49
+
50
+ class NativeCommandError2 extends Error {
51
+ code;
52
+ reason;
53
+ constructor(code, message, options) {
54
+ super(message, options);
55
+ this.code = code;
56
+ if (options?.reason !== undefined && code !== "COMMAND_LIMIT")
57
+ throw new TypeError("Only COMMAND_LIMIT accepts a limit reason");
58
+ this.reason = options?.reason === undefined ? undefined : NativeCommandLimitReasonSchema.parse(options.reason);
59
+ this.name = "NativeCommandError";
60
+ }
61
+ }
62
+
63
+ // src/process/group.ts
64
+ function createCommandDeadline(timeoutMs, reason) {
65
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0)
66
+ throw new RangeError("Command deadline must be a positive safe integer");
67
+ const controller = new AbortController;
68
+ const deadline = performance.now() + timeoutMs;
69
+ let timer;
70
+ const schedule = () => {
71
+ const remaining = deadline - performance.now();
72
+ if (remaining <= 0)
73
+ controller.abort(reason);
74
+ else
75
+ timer = setTimeout(schedule, Math.min(remaining, 2147483647));
76
+ };
77
+ schedule();
78
+ return {
79
+ signal: controller.signal,
80
+ cancel() {
81
+ if (timer !== undefined)
82
+ clearTimeout(timer);
83
+ }
84
+ };
85
+ }
86
+ function deniedOnDarwin(error) {
87
+ return process.platform === "darwin" && error instanceof Error && "code" in error && error.code === "EPERM";
88
+ }
89
+ function signalGroup(pid, signal) {
90
+ if (pid === undefined)
91
+ return;
92
+ try {
93
+ process.kill(-pid, signal);
94
+ } catch (error) {
95
+ if (!(error instanceof Error && ("code" in error) && error.code === "ESRCH"))
96
+ throw error;
97
+ }
98
+ }
99
+ function exists(pid) {
100
+ if (pid === undefined)
101
+ return false;
102
+ try {
103
+ process.kill(-pid, 0);
104
+ return true;
105
+ } catch (error) {
106
+ if (error instanceof Error && "code" in error && error.code === "ESRCH")
107
+ return false;
108
+ if (deniedOnDarwin(error))
109
+ return true;
110
+ throw error;
111
+ }
112
+ }
113
+ async function signalUntilSettled(pid, signal, deadline) {
114
+ for (;; ) {
115
+ try {
116
+ signalGroup(pid, signal);
117
+ return;
118
+ } catch (error) {
119
+ if (!deniedOnDarwin(error) || Date.now() >= deadline)
120
+ throw error;
121
+ await new Promise((resolve) => setTimeout(resolve, Math.min(10, deadline - Date.now())));
122
+ }
123
+ }
124
+ }
125
+ async function stopCommandGroup(pid, graceMs, cleanupTimeoutMs = 2000, force = false) {
126
+ const deadline = Date.now() + graceMs + cleanupTimeoutMs;
127
+ if (force) {
128
+ await signalUntilSettled(pid, "SIGKILL", deadline);
129
+ return;
130
+ }
131
+ await signalUntilSettled(pid, "SIGTERM", deadline);
132
+ const until = Date.now() + graceMs;
133
+ while (Date.now() < until && exists(pid))
134
+ await new Promise((resolve) => setTimeout(resolve, Math.min(10, until - Date.now())));
135
+ await signalUntilSettled(pid, "SIGKILL", deadline);
136
+ }
137
+ function commandCleanupError(cause) {
138
+ return new NativeCommandError2("COMMAND_CLEANUP", "Command cleanup did not complete", {
139
+ cause
140
+ });
141
+ }
142
+ function waitForCommandClose(closed, timeoutMs) {
143
+ const deadline = createCommandDeadline(timeoutMs, new DOMException("Command settlement timed out", "TimeoutError"));
144
+ return raceAbort(closed, deadline.signal).finally(() => deadline.cancel());
145
+ }
146
+
147
+ // src/process/launch.ts
148
+ import { spawn } from "node:child_process";
149
+ import { Readable, Writable } from "node:stream";
150
+ function nativeCommandBudgets(options, driver) {
151
+ const cleanupTimeoutMs = driver?.cleanupTimeoutMs ?? options.cleanupTimeoutMs;
152
+ const timeoutMs = driver?.timeoutMs ?? options.timeoutMs;
153
+ for (const [name, value] of [
154
+ ["cleanup", cleanupTimeoutMs],
155
+ ["execution", timeoutMs],
156
+ ["close", driver?.closeTimeoutMs]
157
+ ])
158
+ if (value !== undefined && (!Number.isSafeInteger(value) || value <= 0))
159
+ throw new RangeError(`Command ${name} deadline must be a positive safe integer`);
160
+ return { cleanupTimeoutMs, timeoutMs };
161
+ }
162
+ var owners = new WeakMap;
163
+ function registerNativeCommandOwner(child, owner) {
164
+ owners.set(child, owner);
165
+ }
166
+ function nativeCommandOwner(child) {
167
+ return owners.get(child);
168
+ }
169
+ function outputStream(source, closed, maxBufferedBytes) {
170
+ if (source instanceof Readable)
171
+ return {
172
+ bytes: source,
173
+ released: new Promise((resolve) => source.closed ? resolve() : source.once("close", resolve)),
174
+ destroy() {
175
+ source.destroy();
176
+ }
177
+ };
178
+ const queue = [];
179
+ let buffered = 0;
180
+ let ended = false;
181
+ let failure;
182
+ let wake = Promise.withResolvers();
183
+ const notify = () => {
184
+ wake.resolve();
185
+ wake = Promise.withResolvers();
186
+ };
187
+ source.on("data", (chunk) => {
188
+ if (ended || failure)
189
+ return;
190
+ if (!(chunk instanceof Uint8Array)) {
191
+ failure = new TypeError("Expected binary command output");
192
+ notify();
193
+ return;
194
+ }
195
+ if (chunk.byteLength === 0)
196
+ return;
197
+ const available = maxBufferedBytes - buffered;
198
+ if (available > 0) {
199
+ const kept = Uint8Array.from(chunk.subarray(0, available));
200
+ queue.push(kept);
201
+ buffered += kept.byteLength;
202
+ }
203
+ if (chunk.byteLength > available)
204
+ failure = new NativeCommandError2("COMMAND_LIMIT", "Command output budget exceeded", {
205
+ reason: "output-budget"
206
+ });
207
+ notify();
208
+ });
209
+ closed.then(() => {
210
+ ended = true;
211
+ notify();
212
+ });
213
+ return {
214
+ bytes: {
215
+ async* [Symbol.asyncIterator]() {
216
+ for (;; ) {
217
+ const chunk = queue.shift();
218
+ if (chunk) {
219
+ buffered -= chunk.byteLength;
220
+ yield chunk;
221
+ } else if (failure)
222
+ throw failure;
223
+ else if (ended)
224
+ return;
225
+ else
226
+ await wake.promise;
227
+ }
228
+ }
229
+ },
230
+ released: closed.then(() => {
231
+ return;
232
+ }),
233
+ destroy() {
234
+ ended = true;
235
+ queue.length = 0;
236
+ buffered = 0;
237
+ notify();
238
+ source.destroy();
239
+ }
240
+ };
241
+ }
242
+ function launchNativeCommand(options, driver, onSpawn, onFailure, onInputFailure) {
243
+ let native;
244
+ const launch = driver?.launch;
245
+ if (!launch)
246
+ native = spawn(options.executable, options.args, {
247
+ cwd: options.cwd,
248
+ env: options.envPolicy === "ambient" ? { ...process.env, ...options.env } : options.env ?? {},
249
+ detached: driver?.group ?? true,
250
+ stdio: ["pipe", "pipe", "pipe"]
251
+ });
252
+ const child = launch ? launch() : native;
253
+ if (!child)
254
+ throw new Error("Native command launcher did not supply a process");
255
+ const pendingHandles = new Set(["leader"]);
256
+ const leader = new Promise((resolve) => {
257
+ child.on("exit", (exitCode, signal) => resolve({ kind: "exit", exitCode, signal }));
258
+ child.on("error", (cause) => resolve({ kind: "error", cause }));
259
+ if (child.exitCode !== null || child.signalCode !== null)
260
+ resolve({ kind: "exit", exitCode: child.exitCode, signal: child.signalCode });
261
+ });
262
+ const closed = new Promise((resolve) => {
263
+ child.on("error", onFailure);
264
+ child.on("close", (exitCode, signal) => resolve({ exitCode, signal }));
265
+ });
266
+ const stdout = outputStream(child.stdout, closed, driver?.maxBufferedBytes ?? 1024 * 1024);
267
+ const stderr = outputStream(child.stderr, closed, driver?.maxBufferedBytes ?? 1024 * 1024);
268
+ const stdin = "stdin" in child && child.stdin instanceof Writable ? child.stdin : undefined;
269
+ const handles = [
270
+ ["stdout", stdout.released],
271
+ ["stderr", stderr.released]
272
+ ];
273
+ if (stdin)
274
+ handles.push([
275
+ "stdin",
276
+ new Promise((resolve) => stdin.closed ? resolve() : stdin.once("close", resolve))
277
+ ]);
278
+ const released = Promise.all([
279
+ leader.then(() => pendingHandles.delete("leader")),
280
+ ...handles.map(([name, released]) => {
281
+ pendingHandles.add(name);
282
+ return released.then(() => pendingHandles.delete(name));
283
+ }),
284
+ ...child.stdout instanceof Readable && child.stderr instanceof Readable ? [] : [closed.then(() => pendingHandles.delete("launcher"))]
285
+ ]);
286
+ if (!(child.stdout instanceof Readable && child.stderr instanceof Readable))
287
+ pendingHandles.add("launcher");
288
+ stdin?.on("error", (error) => {
289
+ if (!(("code" in error) && error.code === "EPIPE"))
290
+ onInputFailure(error);
291
+ });
292
+ return {
293
+ child,
294
+ stdout: stdout.bytes,
295
+ stderr: stderr.bytes,
296
+ leader,
297
+ closed,
298
+ released,
299
+ pendingHandles,
300
+ start() {
301
+ if (native)
302
+ onSpawn?.(native);
303
+ stdin?.end(options.stdin);
304
+ },
305
+ destroy() {
306
+ const failures = [];
307
+ for (const handle of [stdin, stdout, stderr]) {
308
+ try {
309
+ handle?.destroy();
310
+ } catch (cause) {
311
+ failures.push(cause);
312
+ }
313
+ }
314
+ if (failures.length)
315
+ throw new AggregateError(failures, "Command pipe teardown failed");
316
+ }
317
+ };
318
+ }
319
+
320
+ // src/process/leader-settlement.ts
321
+ function createLeaderCloseDeadline(leader, timeoutMs, controller) {
322
+ let finished = false;
323
+ let deadline;
324
+ const expired = () => controller.abort(deadline?.signal.reason);
325
+ if (timeoutMs !== undefined)
326
+ leader.then(() => {
327
+ if (finished)
328
+ return;
329
+ deadline = createCommandDeadline(timeoutMs, commandCleanupError(new Error("Command close deadline exceeded after leader exit")));
330
+ deadline.signal.addEventListener("abort", expired, { once: true });
331
+ });
332
+ return () => {
333
+ finished = true;
334
+ deadline?.cancel();
335
+ deadline?.signal.removeEventListener("abort", expired);
336
+ };
337
+ }
338
+ function createLeaderSettlement(options, signal) {
339
+ let pending;
340
+ return (event) => {
341
+ if (pending)
342
+ return pending;
343
+ pending = (async () => {
344
+ if (!options.onLeaderSettled)
345
+ return;
346
+ const controller = new AbortController;
347
+ const deadline = createCommandDeadline(options.cleanupTimeoutMs, new Error("Leader settlement deadline exceeded"));
348
+ const expired = () => controller.abort(deadline.signal.reason);
349
+ if (deadline.signal.aborted)
350
+ expired();
351
+ else
352
+ deadline.signal.addEventListener("abort", expired, { once: true });
353
+ const abort = () => controller.abort(signal.reason);
354
+ if (!signal.aborted)
355
+ signal.addEventListener("abort", abort, { once: true });
356
+ try {
357
+ await raceAbort(Promise.resolve(options.onLeaderSettled(event, controller.signal)), controller.signal);
358
+ } catch (cause) {
359
+ if (signal.aborted && cause === signal.reason)
360
+ throw cause;
361
+ throw commandCleanupError(new AggregateError([event, cause], "Leader settlement failed"));
362
+ } finally {
363
+ deadline.cancel();
364
+ deadline.signal.removeEventListener("abort", expired);
365
+ signal.removeEventListener("abort", abort);
366
+ controller.abort(new Error("Leader settlement completed"));
367
+ }
368
+ })();
369
+ pending.catch(() => {
370
+ return;
371
+ });
372
+ return pending;
373
+ };
374
+ }
375
+
376
+ // src/process/start-failure.ts
377
+ function failedCommandStart(cause, settle) {
378
+ const error = new NativeCommandError2("COMMAND_UNAVAILABLE", "Command could not start", {
379
+ cause
380
+ });
381
+ const result = (async () => {
382
+ try {
383
+ await settle({ kind: "error", cause });
384
+ } catch (cleanup) {
385
+ throw commandCleanupError(new AggregateError([error, cleanup], "Command failed and cleanup failed"));
386
+ }
387
+ throw error;
388
+ })();
389
+ result.catch(() => {
390
+ return;
391
+ });
392
+ return {
393
+ result,
394
+ async stop() {
395
+ await result.catch((failure) => {
396
+ if (failure instanceof NativeCommandError2 && failure.code === "COMMAND_CLEANUP")
397
+ throw failure;
398
+ });
399
+ }
400
+ };
401
+ }
402
+
403
+ // src/process/command-owner.ts
404
+ function startNativeCommand(input, onSpawn, driver) {
405
+ const options = NativeCommandOptionsSchema.parse(input);
406
+ options.signal?.throwIfAborted();
407
+ if (process.platform === "win32" && driver?.group !== false)
408
+ throw new NativeCommandError2("COMMAND_UNAVAILABLE", "POSIX process groups are required");
409
+ const { cleanupTimeoutMs, timeoutMs } = nativeCommandBudgets(options, driver);
410
+ const controller = new AbortController;
411
+ const abort = () => controller.abort(options.signal?.reason);
412
+ options.signal?.addEventListener("abort", abort, { once: true });
413
+ if (options.signal?.aborted)
414
+ abort();
415
+ const deadline = timeoutMs === undefined ? undefined : createCommandDeadline(timeoutMs, new NativeCommandError2("COMMAND_LIMIT", "Command deadline exceeded", {
416
+ reason: "deadline"
417
+ }));
418
+ const expired = () => controller.abort(deadline?.signal.reason);
419
+ if (deadline?.signal.aborted)
420
+ expired();
421
+ else
422
+ deadline?.signal.addEventListener("abort", expired, { once: true });
423
+ const settle = createLeaderSettlement({ ...options, cleanupTimeoutMs }, controller.signal);
424
+ let spawnFailure;
425
+ let launched;
426
+ try {
427
+ launched = launchNativeCommand(options, driver, onSpawn, (error) => {
428
+ spawnFailure = new NativeCommandError2("COMMAND_UNAVAILABLE", "Command could not start", {
429
+ cause: error
430
+ });
431
+ controller.abort(spawnFailure);
432
+ }, (error) => controller.abort(error));
433
+ } catch (cause) {
434
+ deadline?.cancel();
435
+ deadline?.signal.removeEventListener("abort", expired);
436
+ options.signal?.removeEventListener("abort", abort);
437
+ controller.abort(cause);
438
+ return failedCommandStart(cause, settle);
439
+ }
440
+ const stdout = [];
441
+ const stderr = [];
442
+ let total = 0;
443
+ let finished = false;
444
+ const {
445
+ child,
446
+ stdout: output,
447
+ stderr: errorOutput,
448
+ leader,
449
+ closed,
450
+ released,
451
+ pendingHandles
452
+ } = launched;
453
+ const cancelCloseDeadline = createLeaderCloseDeadline(leader, driver?.closeTimeoutMs, controller);
454
+ const signalOwned = (force = driver?.force) => driver?.group === false || driver?.launch && child.pid === undefined ? Promise.resolve().then(() => {
455
+ if (child.exitCode === null && child.signalCode === null && !child.kill("SIGKILL"))
456
+ throw new Error("Command leader termination was refused");
457
+ }) : stopCommandGroup(child.pid, options.killGraceMs, cleanupTimeoutMs, force);
458
+ const drain = async (stream, channel, captured) => {
459
+ for await (const chunk of stream) {
460
+ controller.signal.throwIfAborted();
461
+ if (!(chunk instanceof Uint8Array))
462
+ throw new TypeError("Expected binary command output");
463
+ total += chunk.byteLength;
464
+ if (options.maxOutputBytes !== undefined && total > options.maxOutputBytes)
465
+ throw new NativeCommandError2("COMMAND_LIMIT", "Command output budget exceeded", {
466
+ reason: "output-budget"
467
+ });
468
+ if (options.capture)
469
+ captured.push(Uint8Array.from(chunk));
470
+ if (options.onOutput)
471
+ await raceAbort(Promise.resolve().then(() => {
472
+ controller.signal.throwIfAborted();
473
+ return options.onOutput?.(chunk, channel, controller.signal);
474
+ }), controller.signal);
475
+ }
476
+ };
477
+ const result = (async () => {
478
+ try {
479
+ launched.start();
480
+ const drains = Promise.all([
481
+ drain(output, "stdout", stdout),
482
+ drain(errorOutput, "stderr", stderr)
483
+ ]);
484
+ await raceAbort(Promise.all([drains, leader.then(settle)]), controller.signal);
485
+ const status = await raceAbort(closed, controller.signal);
486
+ if (spawnFailure !== undefined)
487
+ throw spawnFailure;
488
+ return { ...status, stdout: Buffer.concat(stdout), stderr: Buffer.concat(stderr) };
489
+ } catch (error) {
490
+ controller.abort(error);
491
+ const cleanup = await Promise.allSettled([
492
+ settle({ kind: "error", cause: error }),
493
+ Promise.resolve().then(() => launched.destroy()),
494
+ signalOwned().then(async () => {
495
+ try {
496
+ await waitForCommandClose(released, cleanupTimeoutMs);
497
+ } catch (cause) {
498
+ throw new Error(`Command handles remained open: ${[...pendingHandles].join(", ")}`, {
499
+ cause
500
+ });
501
+ }
502
+ })
503
+ ]);
504
+ const failures = cleanup.flatMap((item) => item.status === "rejected" && item.reason !== error ? [item.reason] : []);
505
+ if (failures.length) {
506
+ throw commandCleanupError(new AggregateError([error, ...failures], "Command failed and cleanup failed"));
507
+ }
508
+ throw error;
509
+ } finally {
510
+ finished = true;
511
+ cancelCloseDeadline();
512
+ deadline?.cancel();
513
+ deadline?.signal.removeEventListener("abort", expired);
514
+ options.signal?.removeEventListener("abort", abort);
515
+ controller.abort(new Error("Command completed"));
516
+ }
517
+ })();
518
+ result.catch(() => {
519
+ return;
520
+ });
521
+ const owner = {
522
+ result,
523
+ async terminate() {
524
+ let refused = false;
525
+ let refusal;
526
+ if (!finished) {
527
+ try {
528
+ await signalOwned(true);
529
+ } catch (error) {
530
+ refused = true;
531
+ refusal = error;
532
+ controller.abort(error);
533
+ }
534
+ try {
535
+ await waitForCommandClose(result, cleanupTimeoutMs);
536
+ } catch (error) {
537
+ if (!finished)
538
+ controller.abort(error);
539
+ }
540
+ }
541
+ await result.then(() => {
542
+ return;
543
+ }, (error) => {
544
+ if (error instanceof NativeCommandError2 && error.code === "COMMAND_CLEANUP")
545
+ throw error;
546
+ });
547
+ if (refused)
548
+ throw commandCleanupError(refusal);
549
+ },
550
+ async stop() {
551
+ if (!finished)
552
+ controller.abort(new DOMException("Command stopped", "AbortError"));
553
+ await result.then(() => {
554
+ return;
555
+ }, (error) => {
556
+ if (error instanceof NativeCommandError2 && error.code === "COMMAND_CLEANUP")
557
+ throw error;
558
+ });
559
+ }
560
+ };
561
+ registerNativeCommandOwner(child, owner);
562
+ return owner;
563
+ }
564
+
565
+ export { NativeCommandError2, stopCommandGroup, nativeCommandOwner, startNativeCommand };