stitchkit 0.111.1 → 0.111.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/CHANGELOG.md +6 -0
- package/dist/entrypoints/process.d.ts +1 -0
- package/dist/entrypoints/process.d.ts.map +1 -1
- package/dist/entrypoints/process.js +76 -1
- package/dist/process/stream.d.ts +27 -0
- package/dist/process/stream.d.ts.map +1 -0
- package/llms/process.2.txt +32 -0
- package/llms/process.txt +26 -23
- package/llms-full.txt +24 -0
- package/llms.txt +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,12 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
|
|
|
15
15
|
|
|
16
16
|
## [Unreleased]
|
|
17
17
|
|
|
18
|
+
## [0.111.2] - 2026-10-17
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- `stitchkit/process`: `streamNativeCommand` starts a command like `runNativeCommand` and returns its stdout and stderr as `ReadableStream<Uint8Array>` while it runs, with `result` and `stop()`. It uses the same owner, so a stream keeps the group ownership, the `stop` policy, the bounds and every group-stop fix of `runNativeCommand`; a slow reader slows the child through pipe backpressure. The `stitchkit/process` surface ceiling rises from 12 to 15 for `streamNativeCommand` and its two types.
|
|
23
|
+
|
|
18
24
|
## [0.111.1] - 2026-10-17
|
|
19
25
|
|
|
20
26
|
### Fixed
|
|
@@ -2,4 +2,5 @@
|
|
|
2
2
|
export { observeProcessInstance, type ProcessInstance, type ProcessInstanceObservation, ProcessInstanceSchema, type ProcessOwnerEvidence, probeProcessOwner, } from '../internal/process-instance.js';
|
|
3
3
|
export { runNativeCommand } from '../process/command.js';
|
|
4
4
|
export { NativeCommandError, type NativeCommandOptions, type NativeCommandResult, type NativeCommandSettlement, type NativeCommandStopPolicy, } from '../process/contract.js';
|
|
5
|
+
export { type NativeCommandStream, type NativeCommandStreamOptions, streamNativeCommand, } from '../process/stream.js';
|
|
5
6
|
//# sourceMappingURL=process.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/entrypoints/process.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAE/E,OAAO,EACL,sBAAsB,EACtB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,iBAAiB,GAClB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EACL,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/entrypoints/process.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAE/E,OAAO,EACL,sBAAsB,EACtB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,iBAAiB,GAClB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EACL,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAC/B,mBAAmB,GACpB,MAAM,mBAAmB,CAAC"}
|
|
@@ -10,14 +10,89 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
startNativeCommand
|
|
12
12
|
} from "../index-7r4knwf8.js";
|
|
13
|
+
import {
|
|
14
|
+
untilAborted
|
|
15
|
+
} from "../index-a5qr2rj6.js";
|
|
13
16
|
// src/process/command.ts
|
|
14
17
|
function runNativeCommand(input) {
|
|
15
18
|
return startNativeCommand(input).result;
|
|
16
19
|
}
|
|
20
|
+
// src/process/stream.ts
|
|
21
|
+
function streamNativeCommand(input) {
|
|
22
|
+
for (const owned of ["capture", "onOutput", "stdio"])
|
|
23
|
+
if (owned in input)
|
|
24
|
+
throw new TypeError(`streamNativeCommand owns ${owned}`);
|
|
25
|
+
const channels = { stdout: channel(), stderr: channel() };
|
|
26
|
+
const owner = startNativeCommand({
|
|
27
|
+
...input,
|
|
28
|
+
onOutput: async (bytes, name, signal) => {
|
|
29
|
+
await channels[name].push(Uint8Array.from(bytes), signal);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
owner.result.then(() => {
|
|
33
|
+
channels.stdout.close();
|
|
34
|
+
channels.stderr.close();
|
|
35
|
+
}, (error) => {
|
|
36
|
+
channels.stdout.fail(error);
|
|
37
|
+
channels.stderr.fail(error);
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
stdout: channels.stdout.stream,
|
|
41
|
+
stderr: channels.stderr.stream,
|
|
42
|
+
result: owner.result,
|
|
43
|
+
stop: () => owner.stop()
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
var QUEUED_BYTES = 1024 * 1024;
|
|
47
|
+
function channel() {
|
|
48
|
+
let controller;
|
|
49
|
+
let cancelled = false;
|
|
50
|
+
let settled = false;
|
|
51
|
+
let resume = Promise.withResolvers();
|
|
52
|
+
const stream = new ReadableStream({
|
|
53
|
+
start(c) {
|
|
54
|
+
controller = c;
|
|
55
|
+
},
|
|
56
|
+
pull() {
|
|
57
|
+
resume.resolve();
|
|
58
|
+
},
|
|
59
|
+
cancel() {
|
|
60
|
+
cancelled = true;
|
|
61
|
+
resume.resolve();
|
|
62
|
+
}
|
|
63
|
+
}, new ByteLengthQueuingStrategy({ highWaterMark: QUEUED_BYTES }));
|
|
64
|
+
return {
|
|
65
|
+
stream,
|
|
66
|
+
async push(bytes, signal) {
|
|
67
|
+
if (cancelled || settled)
|
|
68
|
+
return;
|
|
69
|
+
controller.enqueue(bytes);
|
|
70
|
+
while (!cancelled && !signal.aborted && (controller.desiredSize ?? 0) <= 0) {
|
|
71
|
+
resume = Promise.withResolvers();
|
|
72
|
+
await untilAborted(resume.promise, signal).catch(() => {
|
|
73
|
+
return;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
close() {
|
|
78
|
+
if (cancelled || settled)
|
|
79
|
+
return;
|
|
80
|
+
settled = true;
|
|
81
|
+
controller.close();
|
|
82
|
+
},
|
|
83
|
+
fail(error) {
|
|
84
|
+
if (cancelled || settled)
|
|
85
|
+
return;
|
|
86
|
+
settled = true;
|
|
87
|
+
controller.error(error);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
17
91
|
export {
|
|
18
92
|
NativeCommandError2 as NativeCommandError,
|
|
19
93
|
ProcessInstanceSchema2 as ProcessInstanceSchema,
|
|
20
94
|
observeProcessInstance2 as observeProcessInstance,
|
|
21
95
|
probeProcessOwner2 as probeProcessOwner,
|
|
22
|
-
runNativeCommand
|
|
96
|
+
runNativeCommand,
|
|
97
|
+
streamNativeCommand
|
|
23
98
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { NativeCommandOptions, NativeCommandResult } from './contract.js';
|
|
2
|
+
/** Options the stream owns: its readers are the capture, the sink and the pipes. */
|
|
3
|
+
export type NativeCommandStreamOptions = Omit<NativeCommandOptions, 'capture' | 'onOutput' | 'stdio'>;
|
|
4
|
+
/** A started command whose output is read as it appears. */
|
|
5
|
+
export interface NativeCommandStream {
|
|
6
|
+
/** The leader's stdout; closes once the command finished and every byte was queued. */
|
|
7
|
+
readonly stdout: ReadableStream<Uint8Array>;
|
|
8
|
+
readonly stderr: ReadableStream<Uint8Array>;
|
|
9
|
+
/**
|
|
10
|
+
* Settles like `runNativeCommand` once the command ended and both streams were read to the end
|
|
11
|
+
* or cancelled: a stream nobody reads holds the child back, and with it this result. Its
|
|
12
|
+
* `stdout` and `stderr` are empty, the streams hold the bytes.
|
|
13
|
+
*/
|
|
14
|
+
readonly result: Promise<NativeCommandResult>;
|
|
15
|
+
/** Stops the command with its stop policy and resolves once its resources are proven closed. */
|
|
16
|
+
stop(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Starts one command directly (no shell) like `runNativeCommand`, with the same group ownership,
|
|
20
|
+
* stop policy and bounds, and hands its output over as `ReadableStream`s instead of buffering it
|
|
21
|
+
* for the end. A slow reader slows the child (pipe backpressure); a cancelled stream drops what
|
|
22
|
+
* follows without stopping the command. When the command fails or is stopped, both streams error and
|
|
23
|
+
* the bytes still queued are dropped. A stream nobody reads holds the child back
|
|
24
|
+
* once it queued 1 MiB, so read large outputs concurrently or cancel the stream.
|
|
25
|
+
*/
|
|
26
|
+
export declare function streamNativeCommand(input: NativeCommandStreamOptions): NativeCommandStream;
|
|
27
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/process/stream.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE5E,oFAAoF;AACpF,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,oBAAoB,EACpB,SAAS,GAAG,UAAU,GAAG,OAAO,CACjC,CAAC;AAEF,4DAA4D;AAC5D,MAAM,WAAW,mBAAmB;IAClC,uFAAuF;IACvF,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9C,gGAAgG;IAChG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,0BAA0B,GAAG,mBAAmB,CA0B1F"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# stitchkit/process — stitchkit docs slice, part 2 of 2
|
|
2
|
+
|
|
3
|
+
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
|
+
> `llms.txt` in this package.
|
|
5
|
+
|
|
6
|
+
Parts of this slice:
|
|
7
|
+
- `llms/process.txt`: Guide: Native IO (docs/guide/native-io.md)
|
|
8
|
+
- `llms/process.2.txt`: API reference: `stitchkit/process` (docs/api/reference.md)
|
|
9
|
+
|
|
10
|
+
==============================================================================
|
|
11
|
+
# API reference: `stitchkit/process` (docs/api/reference.md)
|
|
12
|
+
==============================================================================
|
|
13
|
+
|
|
14
|
+
## `stitchkit/process`
|
|
15
|
+
|
|
16
|
+
Native POSIX Bun/Node one-shot command execution. See [native IO](../guide/native-io.md).
|
|
17
|
+
|
|
18
|
+
| Export | Kind | Purpose |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `runNativeCommand` | function | caller-lifetime streaming or explicitly bounded binary capture |
|
|
21
|
+
| `streamNativeCommand` | function | starts a command under the same group ownership, stop policy and bounds as `runNativeCommand` and returns `stdout` / `stderr` as `ReadableStream<Uint8Array>`, `result` and `stop()`; a slow reader slows the child, a cancelled stream drops its bytes, a failed command errors both streams |
|
|
22
|
+
| `NativeCommandStream` | type | what `streamNativeCommand` returns: `stdout`, `stderr`, `result` (its buffers are empty) and `stop()` |
|
|
23
|
+
| `NativeCommandStreamOptions` | type | `NativeCommandOptions` without `capture`, `onOutput` and `stdio`, which the streams own |
|
|
24
|
+
| `NativeCommandOptions` | type | executable/args, env policy, signal/deadline, bytes sink, finite cleanup limits, the `stop` policy and `descendants` (`'terminate-after-leader'`, the default: stop the group after the leader exits, or `'leave'`); `stdio` (`'pipe'`, or `'inherit'` for the caller's descriptors, refusing the pipe-only options) and `group` (`'own'`, or `'caller'`: joins the caller's process group, stops only the leader, refuses `descendants`, `ownerLoss` and a group stop); `ownerLoss: 'terminate'` (optional Linux/Darwin Bun/Node guard: kernel channel EOF after abrupt caller death KILLs its owned group, unsupported platforms refuse); `onLeaderStarted({ pid })` (once after the group leader exists; the package guard's PID under `ownerLoss`), `drainTimeoutMs` (bound on the pipes staying open after the leader exited, `COMMAND_CLEANUP`); an unknown key is refused by name, a removed one (`killGraceMs`) with its replacement |
|
|
25
|
+
| `NativeCommandStopPolicy` | type | how a cancelled command stops: `target` `'group'` (signal every member) or `'leader'` (signal only the leader; its exit ends the grace), `signal` (default `SIGTERM`), `graceMs` (at most one hour) before KILL to the group, and `killOn`, an `AbortSignal` that skips the grace; default `{ target: 'group', signal: 'SIGTERM', graceMs: 100 }` |
|
|
26
|
+
| `NativeCommandResult` | type | observed nullable exit code/signal, `descendantsStopped` (members left in the group after the leader exited were stopped) and captured stdout/stderr bytes |
|
|
27
|
+
| `NativeCommandError` | class | COMMAND_LIMIT with machine reason `deadline` or `output-budget`; COMMAND_UNAVAILABLE / COMMAND_CLEANUP have no limit reason; COMMAND_CLEANUP means the command's resources were not proven closed, either past `cleanupTimeoutMs` after a stop or past `drainTimeoutMs` after the leader exited, and `cause` holds that bound's failure. Preserves internal cause and existing constructor; caller-created limits without supplied reason remain unclassified |
|
|
28
|
+
|
|
29
|
+
| `NativeCommandSettlement` | type | `exit` (the leader ended on its own), `stopped` (the command was stopped and the leader's exit after the stop observed: the stop's `cause` with `exitCode`/`signal`) or `error` (no exit observed), including synchronous native launch failure; `onLeaderSettled` runs once before drain, bounded by cleanupTimeoutMs, with a cancellable settlement signal; schema/pre-abort refusal creates no settlement obligation |
|
|
30
|
+
| `observeProcessInstance` / `ProcessInstanceObservation` | function / type | Linux/Darwin lifetime observation; observed identity or unavailable with its original cause, never guessed absence |
|
|
31
|
+
| `ProcessInstanceSchema` / `ProcessInstance` | schema / type | platform, boot ID, namespace and process start identity from the shared native reader |
|
|
32
|
+
| `probeProcessOwner` / `ProcessOwnerEvidence` | function / type | compare lifetimes on one caller-established machine; matched, boot change, reused PID, gone, legacy or unavailable with cause |
|
package/llms/process.txt
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
# stitchkit/process — stitchkit docs slice
|
|
1
|
+
# stitchkit/process — stitchkit docs slice, part 1 of 2
|
|
2
2
|
|
|
3
3
|
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
4
|
> `llms.txt` in this package.
|
|
5
|
+
> Continues in `llms/process.2.txt`.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Parts of this slice:
|
|
8
|
+
- `llms/process.txt`: Guide: Native IO (docs/guide/native-io.md)
|
|
9
|
+
- `llms/process.2.txt`: API reference: `stitchkit/process` (docs/api/reference.md)
|
|
7
10
|
|
|
8
11
|
==============================================================================
|
|
9
12
|
# Guide: Native IO (docs/guide/native-io.md)
|
|
@@ -147,6 +150,27 @@ await runNativeCommand({
|
|
|
147
150
|
})
|
|
148
151
|
```
|
|
149
152
|
|
|
153
|
+
To read output as it appears, use `streamNativeCommand`: the same owner, group ownership, `stop`
|
|
154
|
+
policy and bounds, with the output as `ReadableStream<Uint8Array>`.
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import { streamNativeCommand } from 'stitchkit/process'
|
|
158
|
+
|
|
159
|
+
const lifetime = new AbortController()
|
|
160
|
+
const command = streamNativeCommand({
|
|
161
|
+
executable: '/usr/bin/tail', args: ['-f', '/var/log/app.log'], signal: lifetime.signal,
|
|
162
|
+
})
|
|
163
|
+
void command.stderr.cancel() // not interested: dropped, the command keeps running
|
|
164
|
+
for await (const bytes of command.stdout) handle(bytes) // a slow reader slows the child
|
|
165
|
+
await command.result // settles like `runNativeCommand`; `stop()` ends the group and waits for it
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The streams own `capture`, `onOutput` and `stdio`; passing one is refused. Each stream queues up to 1 MiB, so
|
|
169
|
+
a small output can be read in any order, even after `result`; past that an unread stream fills its pipe
|
|
170
|
+
and holds the command, and its `result`, until the signal or `timeoutMs`, so read large outputs
|
|
171
|
+
concurrently or cancel the stream you ignore. Cancelling a stream drops its later bytes and leaves the command running. When the
|
|
172
|
+
command fails or is stopped, both streams error and the bytes still queued are dropped.
|
|
173
|
+
|
|
150
174
|
A command needs a caller `signal` or a finite `timeoutMs` (1 to 2147483647 ms, the native timer
|
|
151
175
|
range; a larger value is refused, never turned into 1 ms). Streaming runs for the caller's lifetime,
|
|
152
176
|
with no hidden 60-second timeout or 1 MiB output limit. `capture` defaults to false; `true` requires
|
|
@@ -698,24 +722,3 @@ A sandbox admission slot is released once a direct command's pipes have closed a
|
|
|
698
722
|
A `COMMAND_CLEANUP` outcome means the death of its group was not proven, so the slot stays
|
|
699
723
|
occupied, `stop` keeps rejecting with the cleanup error, and the sandbox session is recreated to
|
|
700
724
|
recover.
|
|
701
|
-
|
|
702
|
-
==============================================================================
|
|
703
|
-
# API reference: `stitchkit/process` (docs/api/reference.md)
|
|
704
|
-
==============================================================================
|
|
705
|
-
|
|
706
|
-
## `stitchkit/process`
|
|
707
|
-
|
|
708
|
-
Native POSIX Bun/Node one-shot command execution. See [native IO](../guide/native-io.md).
|
|
709
|
-
|
|
710
|
-
| Export | Kind | Purpose |
|
|
711
|
-
|---|---|---|
|
|
712
|
-
| `runNativeCommand` | function | caller-lifetime streaming or explicitly bounded binary capture |
|
|
713
|
-
| `NativeCommandOptions` | type | executable/args, env policy, signal/deadline, bytes sink, finite cleanup limits, the `stop` policy and `descendants` (`'terminate-after-leader'`, the default: stop the group after the leader exits, or `'leave'`); `stdio` (`'pipe'`, or `'inherit'` for the caller's descriptors, refusing the pipe-only options) and `group` (`'own'`, or `'caller'`: joins the caller's process group, stops only the leader, refuses `descendants`, `ownerLoss` and a group stop); `ownerLoss: 'terminate'` (optional Linux/Darwin Bun/Node guard: kernel channel EOF after abrupt caller death KILLs its owned group, unsupported platforms refuse); `onLeaderStarted({ pid })` (once after the group leader exists; the package guard's PID under `ownerLoss`), `drainTimeoutMs` (bound on the pipes staying open after the leader exited, `COMMAND_CLEANUP`); an unknown key is refused by name, a removed one (`killGraceMs`) with its replacement |
|
|
714
|
-
| `NativeCommandStopPolicy` | type | how a cancelled command stops: `target` `'group'` (signal every member) or `'leader'` (signal only the leader; its exit ends the grace), `signal` (default `SIGTERM`), `graceMs` (at most one hour) before KILL to the group, and `killOn`, an `AbortSignal` that skips the grace; default `{ target: 'group', signal: 'SIGTERM', graceMs: 100 }` |
|
|
715
|
-
| `NativeCommandResult` | type | observed nullable exit code/signal, `descendantsStopped` (members left in the group after the leader exited were stopped) and captured stdout/stderr bytes |
|
|
716
|
-
| `NativeCommandError` | class | COMMAND_LIMIT with machine reason `deadline` or `output-budget`; COMMAND_UNAVAILABLE / COMMAND_CLEANUP have no limit reason; COMMAND_CLEANUP means the command's resources were not proven closed, either past `cleanupTimeoutMs` after a stop or past `drainTimeoutMs` after the leader exited, and `cause` holds that bound's failure. Preserves internal cause and existing constructor; caller-created limits without supplied reason remain unclassified |
|
|
717
|
-
|
|
718
|
-
| `NativeCommandSettlement` | type | `exit` (the leader ended on its own), `stopped` (the command was stopped and the leader's exit after the stop observed: the stop's `cause` with `exitCode`/`signal`) or `error` (no exit observed), including synchronous native launch failure; `onLeaderSettled` runs once before drain, bounded by cleanupTimeoutMs, with a cancellable settlement signal; schema/pre-abort refusal creates no settlement obligation |
|
|
719
|
-
| `observeProcessInstance` / `ProcessInstanceObservation` | function / type | Linux/Darwin lifetime observation; observed identity or unavailable with its original cause, never guessed absence |
|
|
720
|
-
| `ProcessInstanceSchema` / `ProcessInstance` | schema / type | platform, boot ID, namespace and process start identity from the shared native reader |
|
|
721
|
-
| `probeProcessOwner` / `ProcessOwnerEvidence` | function / type | compare lifetimes on one caller-established machine; matched, boot change, reused PID, gone, legacy or unavailable with cause |
|
package/llms-full.txt
CHANGED
|
@@ -8586,6 +8586,27 @@ await runNativeCommand({
|
|
|
8586
8586
|
})
|
|
8587
8587
|
```
|
|
8588
8588
|
|
|
8589
|
+
To read output as it appears, use `streamNativeCommand`: the same owner, group ownership, `stop`
|
|
8590
|
+
policy and bounds, with the output as `ReadableStream<Uint8Array>`.
|
|
8591
|
+
|
|
8592
|
+
```ts
|
|
8593
|
+
import { streamNativeCommand } from 'stitchkit/process'
|
|
8594
|
+
|
|
8595
|
+
const lifetime = new AbortController()
|
|
8596
|
+
const command = streamNativeCommand({
|
|
8597
|
+
executable: '/usr/bin/tail', args: ['-f', '/var/log/app.log'], signal: lifetime.signal,
|
|
8598
|
+
})
|
|
8599
|
+
void command.stderr.cancel() // not interested: dropped, the command keeps running
|
|
8600
|
+
for await (const bytes of command.stdout) handle(bytes) // a slow reader slows the child
|
|
8601
|
+
await command.result // settles like `runNativeCommand`; `stop()` ends the group and waits for it
|
|
8602
|
+
```
|
|
8603
|
+
|
|
8604
|
+
The streams own `capture`, `onOutput` and `stdio`; passing one is refused. Each stream queues up to 1 MiB, so
|
|
8605
|
+
a small output can be read in any order, even after `result`; past that an unread stream fills its pipe
|
|
8606
|
+
and holds the command, and its `result`, until the signal or `timeoutMs`, so read large outputs
|
|
8607
|
+
concurrently or cancel the stream you ignore. Cancelling a stream drops its later bytes and leaves the command running. When the
|
|
8608
|
+
command fails or is stopped, both streams error and the bytes still queued are dropped.
|
|
8609
|
+
|
|
8589
8610
|
A command needs a caller `signal` or a finite `timeoutMs` (1 to 2147483647 ms, the native timer
|
|
8590
8611
|
range; a larger value is refused, never turned into 1 ms). Streaming runs for the caller's lifetime,
|
|
8591
8612
|
with no hidden 60-second timeout or 1 MiB output limit. `capture` defaults to false; `true` requires
|
|
@@ -23566,6 +23587,9 @@ Native POSIX Bun/Node one-shot command execution. See [native IO](../guide/nativ
|
|
|
23566
23587
|
| Export | Kind | Purpose |
|
|
23567
23588
|
|---|---|---|
|
|
23568
23589
|
| `runNativeCommand` | function | caller-lifetime streaming or explicitly bounded binary capture |
|
|
23590
|
+
| `streamNativeCommand` | function | starts a command under the same group ownership, stop policy and bounds as `runNativeCommand` and returns `stdout` / `stderr` as `ReadableStream<Uint8Array>`, `result` and `stop()`; a slow reader slows the child, a cancelled stream drops its bytes, a failed command errors both streams |
|
|
23591
|
+
| `NativeCommandStream` | type | what `streamNativeCommand` returns: `stdout`, `stderr`, `result` (its buffers are empty) and `stop()` |
|
|
23592
|
+
| `NativeCommandStreamOptions` | type | `NativeCommandOptions` without `capture`, `onOutput` and `stdio`, which the streams own |
|
|
23569
23593
|
| `NativeCommandOptions` | type | executable/args, env policy, signal/deadline, bytes sink, finite cleanup limits, the `stop` policy and `descendants` (`'terminate-after-leader'`, the default: stop the group after the leader exits, or `'leave'`); `stdio` (`'pipe'`, or `'inherit'` for the caller's descriptors, refusing the pipe-only options) and `group` (`'own'`, or `'caller'`: joins the caller's process group, stops only the leader, refuses `descendants`, `ownerLoss` and a group stop); `ownerLoss: 'terminate'` (optional Linux/Darwin Bun/Node guard: kernel channel EOF after abrupt caller death KILLs its owned group, unsupported platforms refuse); `onLeaderStarted({ pid })` (once after the group leader exists; the package guard's PID under `ownerLoss`), `drainTimeoutMs` (bound on the pipes staying open after the leader exited, `COMMAND_CLEANUP`); an unknown key is refused by name, a removed one (`killGraceMs`) with its replacement |
|
|
23570
23594
|
| `NativeCommandStopPolicy` | type | how a cancelled command stops: `target` `'group'` (signal every member) or `'leader'` (signal only the leader; its exit ends the grace), `signal` (default `SIGTERM`), `graceMs` (at most one hour) before KILL to the group, and `killOn`, an `AbortSignal` that skips the grace; default `{ target: 'group', signal: 'SIGTERM', graceMs: 100 }` |
|
|
23571
23595
|
| `NativeCommandResult` | type | observed nullable exit code/signal, `descendantsStopped` (members left in the group after the leader exited were stopped) and captured stdout/stderr bytes |
|
package/llms.txt
CHANGED
|
@@ -56,7 +56,7 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
|
|
|
56
56
|
- **stitchkit/node**: [llms/node.txt](llms/node.txt) 3.1 KB
|
|
57
57
|
- **stitchkit/agent-runtime/react**: [llms/agent-runtime-react.txt](llms/agent-runtime-react.txt) 1.0 KB
|
|
58
58
|
- **stitchkit/agent-runtime/realtime**: [llms/agent-runtime-realtime.txt](llms/agent-runtime-realtime.txt) 2.6 KB
|
|
59
|
-
- **stitchkit/process**: [llms/process.txt](llms/process.txt)
|
|
59
|
+
- **stitchkit/process**: [llms/process.txt](llms/process.txt) 43.7 KB → [llms/process.2.txt](llms/process.2.txt) 4.3 KB
|
|
60
60
|
- **stitchkit/process/owner-loss**: [llms/process-owner-loss.txt](llms/process-owner-loss.txt) 0.9 KB
|
|
61
61
|
- **stitchkit/files/packaging**: [llms/files-packaging.txt](llms/files-packaging.txt) 3.5 KB
|
|
62
62
|
- **stitchkit/http**: [llms/http.txt](llms/http.txt) 0.9 KB
|
package/package.json
CHANGED