stitchkit 0.108.1 → 0.108.3

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 +29 -0
  2. package/dist/entrypoints/agent-runtime/coding-tools.js +3 -2
  3. package/dist/entrypoints/agent-runtime/sandbox.js +5 -3
  4. package/dist/entrypoints/cli.js +1 -1
  5. package/dist/entrypoints/contract.js +1 -1
  6. package/dist/entrypoints/index.js +1 -1
  7. package/dist/entrypoints/node.js +1 -1
  8. package/dist/entrypoints/process/owner-loss.d.ts +3 -0
  9. package/dist/entrypoints/process/owner-loss.d.ts.map +1 -0
  10. package/dist/entrypoints/process/owner-loss.js +6 -0
  11. package/dist/entrypoints/process.js +4 -2
  12. package/dist/entrypoints/server.js +1 -1
  13. package/dist/entrypoints/tools.js +1 -1
  14. package/dist/{index-epg514ys.js → index-dasy32c8.js} +76 -328
  15. package/dist/index-dj1aycxw.js +639 -0
  16. package/dist/{index-4qh90tyw.js → index-fgq4w9bf.js} +23 -1
  17. package/dist/{index-e35py42g.js → index-tycmtxky.js} +6 -4
  18. package/dist/process/bun-child.d.ts +10 -0
  19. package/dist/process/bun-child.d.ts.map +1 -1
  20. package/dist/process/command-owner.d.ts.map +1 -1
  21. package/dist/process/contract.d.ts +5 -0
  22. package/dist/process/contract.d.ts.map +1 -1
  23. package/dist/process/launch.d.ts +1 -1
  24. package/dist/process/launch.d.ts.map +1 -1
  25. package/dist/process/owned-child.d.ts +3 -0
  26. package/dist/process/owned-child.d.ts.map +1 -1
  27. package/dist/process/owner-loss-control.d.ts +15 -0
  28. package/dist/process/owner-loss-control.d.ts.map +1 -0
  29. package/dist/process/owner-loss-guard.d.ts +12 -0
  30. package/dist/process/owner-loss-guard.d.ts.map +1 -0
  31. package/dist/process/owner-loss-protocol.d.ts +10 -0
  32. package/dist/process/owner-loss-protocol.d.ts.map +1 -0
  33. package/dist/process/owner-loss-socket.d.ts +4 -0
  34. package/dist/process/owner-loss-socket.d.ts.map +1 -0
  35. package/dist/tools/cli/args-fields.d.ts.map +1 -1
  36. package/llms/cli.2.txt +107 -0
  37. package/llms/cli.txt +8 -107
  38. package/llms/process-owner-loss.txt +18 -0
  39. package/llms/process.txt +43 -10
  40. package/llms/stitchkit.txt +2 -1
  41. package/llms-full.txt +61 -11
  42. package/llms.txt +4 -3
  43. package/package.json +5 -1
  44. /package/dist/{index-q4hjtyye.js → index-qd8x73e8.js} +0 -0
package/llms-full.txt CHANGED
@@ -61,7 +61,8 @@ own, recorded as an ADR.
61
61
  | `stitchkit/cli` | server | stable | `createCli` / `createCliInvoker` — runtime and strict NodeNext declarations without MCP SDK / `ai` |
62
62
  | `stitchkit/cli/publish` | build and release tooling (Bun or Node, POSIX) | evolving | `publishCli` — commit a verified CLI distribution and move its public manifest last; see [CLI guide](cli.md#publishing-a-complete-version) |
63
63
  | `stitchkit/remote` | browser **and** server | stable | peer-free `implementRemote` for thin HTTP proxy processes |
64
- | `stitchkit/process` | server (Bun or Node, POSIX) | evolving | finite native commands, byte sinks, bounded capture and process-group cancellation |
64
+ | `stitchkit/process` | server (Bun or Node, POSIX) | evolving | finite native commands, byte sinks, bounded capture, process-group cancellation and opt-in Linux/Darwin owner-loss cleanup |
65
+ | `stitchkit/process/owner-loss` | bundled server entry (Bun, POSIX) | evolving | narrow bootstrap that keeps the process runner lazy while carrying its owner-loss guard in a single-file bundle |
65
66
  | `stitchkit/files/packaging` | build time (Bun or Node) | evolving | installed native asset graph, integrity, Bun packaging plugin and the artifact loader check; no runtime install policy |
66
67
  | `stitchkit/files` | server (Bun or Node) | stable | peer-free managed local-file boundary |
67
68
  | `stitchkit/telegram` | server (Bun or Node) | evolving | peer-free Telegram platform primitives — Mini App `initData` verification, send-failure classification, resumable broadcasts, the operator channel with dedupe, a Bot API transport that separates a request that never left from an unknown outcome, local Bot API files, webhook ownership and durable webhook update intake |
@@ -8322,6 +8323,7 @@ console.log(captured.exitCode, new TextDecoder().decode(captured.stdout))
8322
8323
  const lifetime = new AbortController()
8323
8324
  await runNativeCommand({
8324
8325
  executable: '/usr/bin/git', args: ['status'], signal: lifetime.signal,
8326
+ ownerLoss: 'terminate', // also stop its group if this JavaScript process is SIGKILLed
8325
8327
  onOutput: async (bytes, channel, outputSignal) => {
8326
8328
  outputSignal.throwIfAborted()
8327
8329
  await output.write(bytes, channel, outputSignal) // application-owned bounded sink
@@ -8384,6 +8386,35 @@ sink cause is kept; a cleanup failure is a `NativeCommandError` with `COMMAND_CL
8384
8386
  refuses with `COMMAND_UNAVAILABLE`; a descendant that has left the group on its own with `setsid` is
8385
8387
  outside this capability. This is one-shot execution, not a PTY, a supervisor or a daemon host.
8386
8388
 
8389
+ `ownerLoss: 'terminate'` binds the command group to this JavaScript process even when it cannot run
8390
+ cleanup. A package-owned guard becomes the process-group leader, starts the requested executable in
8391
+ that group and holds one end of a private inherited kernel channel. The caller holds the other end.
8392
+ `SIGKILL`, a crash or any abrupt caller exit closes that end; EOF makes the guard KILL its own group.
8393
+ There is no liveness polling and no later PID lookup. Because the guard is still the group leader
8394
+ when it signals, its PGID cannot have been reused by a neighbour. The option is available on Linux
8395
+ and Darwin under Bun and Node, requires `group: 'own'`, and other platforms refuse it with
8396
+ `COMMAND_UNAVAILABLE`. It adds one short-lived process and one descriptor per guarded command, so it
8397
+ is opt-in. `onLeaderStarted({ pid })` reports the guard/group leader with this option; output, stdin,
8398
+ exit status, deadlines, cancellation and `onLeaderSettled` retain the requested command's behaviour.
8399
+
8400
+ An unbundled application already launches the package's own guard module. A single-file bundle
8401
+ whose application entry also owns argv routing must load the narrow bootstrap before its dispatcher
8402
+ and skip dispatch when it claims the private guard invocation. This is especially relevant when the
8403
+ full command runner stays behind a dynamic import:
8404
+
8405
+ ```ts
8406
+ import { bootstrapNativeCommandOwnerLoss } from 'stitchkit/process/owner-loss'
8407
+
8408
+ if (!bootstrapNativeCommandOwnerLoss()) {
8409
+ await dispatch(process.argv.slice(2)) // may lazy-import `stitchkit/process`
8410
+ }
8411
+ ```
8412
+
8413
+ The bootstrap carries the package-owned guard into the bundle. It returns `false` for application
8414
+ argv and `true` only for the private child started by `runNativeCommand`, so the application does
8415
+ not read a guard flag or filename. The built file is self-contained; no installed `node_modules`
8416
+ is needed beside it.
8417
+
8387
8418
  ### Stopping a command: the `stop` policy
8388
8419
 
8389
8420
  A caller abort, the `timeoutMs` deadline, an exceeded output budget and a failing sink all stop the
@@ -8418,13 +8449,13 @@ dropped, never passed to `onOutput` and never captured, so a leader that writes
8418
8449
  does not meet a broken pipe. The result rejects with the abort reason once the group is gone and the
8419
8450
  pipes are closed, so it can take `graceMs` plus `cleanupTimeoutMs` after the abort.
8420
8451
 
8421
- The grace is a timer inside the process that runs the command. If that process exits first, the
8422
- timer is gone and the group, which is detached into its own session, keeps running: nothing in this
8423
- package can bound it from outside. Abort `killOn` in your shutdown path, so the group is killed
8424
- before the process exits, and let the supervisor own the case where the process dies without a
8425
- shutdown. Under systemd, keep `KillMode=control-group` (the default) so the stop of the unit
8426
- reaches every process in its cgroup, whatever its process group; launchd only kills the job's own
8427
- process group, which a command's group is not.
8452
+ The grace is a timer inside the process that runs the command. Without `ownerLoss`, if that process
8453
+ exits first, the timer is gone and the group, which is detached into its own session, keeps running.
8454
+ Abort `killOn` in your shutdown path so a deliberate shutdown kills the group before exit. For an
8455
+ abrupt-exit guarantee, choose `ownerLoss: 'terminate'`; for all groups in a service, let the service
8456
+ supervisor own the wider boundary. Under systemd, keep `KillMode=control-group` (the default) so the
8457
+ stop of the unit reaches every process in its cgroup, whatever its process group; launchd only kills
8458
+ the job's own process group, which an unguarded detached command's group is not.
8428
8459
 
8429
8460
  ### Stopping a group and its descendants
8430
8461
 
@@ -8485,7 +8516,7 @@ becomes `runNativeCommand`; shell policy, command admission, logging, redaction,
8485
8516
  decoder and the operator sink stay with the application. Long signal-only commands stay streaming;
8486
8517
  bounded tar or capture commands get their own explicit limits.
8487
8518
 
8488
- A child the caller holds until it exits is the same call. A guardian that forwards its own SIGTERM
8519
+ A child the caller holds until it exits is the same call. A host that forwards its own SIGTERM
8489
8520
  passes an abort signal and `stop: { target: 'leader', signal: 'SIGTERM', graceMs }`. It records the
8490
8521
  pid in `onLeaderStarted({ pid })`, which runs once right after the leader exists (a throw stops the
8491
8522
  command with that error), and the leader's exit code and signal in `onLeaderSettled`: `'exit'`
@@ -8495,7 +8526,9 @@ long the output pipes may stay open after the leader exited: a holder that left
8495
8526
  `setsid` keeps them open, and without the option the command waits for it until `timeoutMs` or
8496
8527
  the signal; with it the command ends with `COMMAND_CLEANUP` (a holder inside the group is already
8497
8528
  stopped by `descendants`). A worker whose whole group must stop on abort is the default
8498
- `target: 'group'`. A command that uses the caller's terminal is the next section. Importing one leaf does not make
8529
+ `target: 'group'`. Add `ownerLoss: 'terminate'` when the worker must also die after an abrupt host
8530
+ loss; in that mode `onLeaderStarted` reports the package guard that leads the same group. A command
8531
+ that uses the caller's terminal is the next section. Importing one leaf does not make
8499
8532
  installing the whole npm package smaller; choose a dependency after measuring packed size and its
8500
8533
  dependency closure.
8501
8534
 
@@ -8529,6 +8562,7 @@ its own, so:
8529
8562
  because a group signal would reach the caller;
8530
8563
  - `descendants` does not apply and is refused: what the leader leaves behind belongs to the
8531
8564
  caller's group, and `descendantsStopped` is always `false`;
8565
+ - `ownerLoss` is refused: an owner-loss guard must lead a group that belongs only to the command;
8532
8566
  - a Ctrl-C reaches the caller too; handle `SIGINT` in the caller when it must outlive the command.
8533
8567
 
8534
8568
  The two options are independent: `stdio: 'inherit'` alone keeps colour and `isatty` for a command
@@ -9607,11 +9641,19 @@ string, the schema says what it should be:
9607
9641
  | `z.string()` | `--name "box"` or a positional |
9608
9642
  | `z.number()` | `--count 3` → `3` |
9609
9643
  | `z.boolean()` | `--active` (presence) / `--active false` / `--no-active` |
9644
+ | `z.literal(1)` / `z.literal([1, 2])` | `--level 1` → `1` |
9645
+ | `z.literal(true)` | `--enabled` / `--no-enabled` |
9646
+ | `z.literal('007')` | `--code 007` → `"007"` |
9610
9647
  | `z.enum([...])` | `--size large` |
9611
9648
  | `z.array(z.string())`| `--tag a --tag b` → `["a","b"]` |
9612
9649
  | `z.object({...})` | `--opts '{"k":"v"}'` (JSON) or `--opts.k v` |
9613
9650
  | `.optional()` / `.default()` | not required |
9614
9651
 
9652
+ Primitive literals use the same coercion through optional, nullable and default wrappers and as
9653
+ array elements. A literal set whose members have different primitive types stays lexical because
9654
+ argv has no type tag: for `z.literal([7, '007'])`, `--value 007` remains the string `"007"` rather
9655
+ than being guessed as the number `7`. The unchanged Zod schema makes the final admission decision.
9656
+
9615
9657
  After a bare boolean flag, the next token is its value when it is exactly
9616
9658
  `true` or `false` — `--active false` turns it off, as it reads. Any other word
9617
9659
  there stays a positional, and `--` makes a literal `false` one too. The same
@@ -23044,7 +23086,7 @@ Native POSIX Bun/Node one-shot command execution. See [native IO](../guide/nativ
23044
23086
  | Export | Kind | Purpose |
23045
23087
  |---|---|---|
23046
23088
  | `runNativeCommand` | function | caller-lifetime streaming or explicitly bounded binary capture |
23047
- | `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` and a group stop); `onLeaderStarted({ pid })` (once, after the leader exists), `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 |
23089
+ | `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 |
23048
23090
  | `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 }` |
23049
23091
  | `NativeCommandResult` | type | observed nullable exit code/signal, `descendantsStopped` (members left in the group after the leader exited were stopped) and captured stdout/stderr bytes |
23050
23092
  | `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 |
@@ -23054,6 +23096,14 @@ Native POSIX Bun/Node one-shot command execution. See [native IO](../guide/nativ
23054
23096
  | `ProcessInstanceSchema` / `ProcessInstance` | schema / type | platform, boot ID, namespace and process start identity from the shared native reader |
23055
23097
  | `probeProcessOwner` / `ProcessOwnerEvidence` | function / type | compare lifetimes on one caller-established machine; matched, boot change, reused PID, gone, legacy or unavailable with cause |
23056
23098
 
23099
+ ## `stitchkit/process/owner-loss`
23100
+
23101
+ Narrow startup entry for single-file applications that lazy-import `stitchkit/process`.
23102
+
23103
+ | Export | Kind | Purpose |
23104
+ |---|---|---|
23105
+ | `bootstrapNativeCommandOwnerLoss` | function | call before application argv routing; returns `true` only when the package guard owns this invocation, so the application skips its dispatcher while preserving a lazy import of the full command runner |
23106
+
23057
23107
  ## `stitchkit/files/packaging`
23058
23108
 
23059
23109
  `stitchkit/files/packaging` owns `createNativePackaging` and the types
package/llms.txt CHANGED
@@ -9,7 +9,7 @@ Build with stitchkit: define a contract once, then `implement` it and serve it (
9
9
  Load the slice for each entrypoint your code imports — `import … from 'stitchkit/server'` → `llms/server.txt`; the root `stitchkit` import → `llms/stitchkit.txt`. A slice holds that entrypoint's API reference section and the guide pages whose home it is; every guide lives in exactly one slice, and a slice that needs another's guide names it under "Also read". Each file is at most 50.0 KB; a longer one continues in numbered parts, each naming the next at its top. Moving across versions: load `llms/upgrading.txt` and the range slices it lists between your version and the target. `llms-full.txt` inlines everything; it is far larger than a context window, so do not read it whole.
10
10
 
11
11
  ## Entrypoint slices
12
- - **stitchkit**: [llms/stitchkit.txt](llms/stitchkit.txt) 46.5 KB → [llms/stitchkit.2.txt](llms/stitchkit.2.txt) 36.5 KB
12
+ - **stitchkit**: [llms/stitchkit.txt](llms/stitchkit.txt) 46.7 KB → [llms/stitchkit.2.txt](llms/stitchkit.2.txt) 36.5 KB
13
13
  - **stitchkit/live**: [llms/live.txt](llms/live.txt) 21.2 KB
14
14
  - **stitchkit/react**: [llms/react.txt](llms/react.txt) 8.6 KB
15
15
  - **stitchkit/react/keyboard**: [llms/react-keyboard.txt](llms/react-keyboard.txt) 9.2 KB
@@ -18,7 +18,7 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
18
18
  - **stitchkit/tools/contract**: [llms/tools-contract.txt](llms/tools-contract.txt) 0.2 KB
19
19
  - **stitchkit/tools/invoker**: [llms/tools-invoker.txt](llms/tools-invoker.txt) 0.2 KB
20
20
  - **stitchkit/tools/connections**: [llms/tools-connections.txt](llms/tools-connections.txt) 3.7 KB
21
- - **stitchkit/cli**: [llms/cli.txt](llms/cli.txt) 47.0 KB → [llms/cli.2.txt](llms/cli.2.txt) 15.4 KB
21
+ - **stitchkit/cli**: [llms/cli.txt](llms/cli.txt) 42.8 KB → [llms/cli.2.txt](llms/cli.2.txt) 20.1 KB
22
22
  - **stitchkit/cli/publish**: [llms/cli-publish.txt](llms/cli-publish.txt) 1.5 KB
23
23
  - **stitchkit/remote**: [llms/remote.txt](llms/remote.txt) 1.0 KB
24
24
  - **stitchkit/contract**: [llms/contract.txt](llms/contract.txt) 31.9 KB
@@ -56,7 +56,8 @@ 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) 43.3 KB
59
+ - **stitchkit/process**: [llms/process.txt](llms/process.txt) 45.8 KB
60
+ - **stitchkit/process/owner-loss**: [llms/process-owner-loss.txt](llms/process-owner-loss.txt) 0.9 KB
60
61
  - **stitchkit/files/packaging**: [llms/files-packaging.txt](llms/files-packaging.txt) 3.5 KB
61
62
 
62
63
  ## Upgrading slices
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.108.1",
3
+ "version": "0.108.3",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",
@@ -249,6 +249,10 @@
249
249
  "types": "./dist/entrypoints/process.d.ts",
250
250
  "import": "./dist/entrypoints/process.js"
251
251
  },
252
+ "./process/owner-loss": {
253
+ "types": "./dist/entrypoints/process/owner-loss.d.ts",
254
+ "import": "./dist/entrypoints/process/owner-loss.js"
255
+ },
252
256
  "./files/packaging": {
253
257
  "types": "./dist/entrypoints/files/packaging.d.ts",
254
258
  "import": "./dist/entrypoints/files/packaging.js"
File without changes