stitchkit 0.70.0 → 0.70.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-runtime/coding-tool-files.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-paths.d.ts +0 -1
- package/dist/agent-runtime/coding-tool-paths.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
- package/dist/agent-runtime/contained-files.d.ts +30 -7
- package/dist/agent-runtime/contained-files.d.ts.map +1 -1
- package/dist/agent-runtime/harness-control.d.ts +2 -0
- package/dist/agent-runtime/harness-control.d.ts.map +1 -1
- package/dist/agent-runtime/history-chronology.d.ts +19 -0
- package/dist/agent-runtime/history-chronology.d.ts.map +1 -0
- package/dist/agent-runtime/history.d.ts.map +1 -1
- package/dist/agent-runtime/run-execution.d.ts.map +1 -1
- package/dist/agent-runtime/terminal-status.d.ts.map +1 -1
- package/dist/agent-runtime-browser.js +51 -51
- package/dist/agent-runtime-coding-tools.js +31 -34
- package/dist/agent-runtime-harness.js +61 -17
- package/dist/agent-runtime-openrouter.js +2 -2
- package/dist/agent-runtime-sqlite-bun.js +5 -5
- package/dist/agent-runtime-sqlite-node.js +5 -5
- package/dist/agent-runtime.js +110 -110
- package/dist/application/server-resource.d.ts +1 -0
- package/dist/application/server-resource.d.ts.map +1 -1
- package/dist/application-grammy.js +2 -2
- package/dist/application.js +68 -65
- package/dist/browser/live-state.d.ts +126 -0
- package/dist/browser/live-state.d.ts.map +1 -0
- package/dist/cli.js +5 -5
- package/dist/contract/index.js +20 -20
- package/dist/declaration.d.ts +4 -0
- package/dist/declaration.d.ts.map +1 -1
- package/dist/declaration.js +22 -22
- package/dist/files.js +3 -3
- package/dist/index-1z5xxfst.js +397 -0
- package/dist/{index-vy5bjy07.js → index-4qfqy0m6.js} +21 -31
- package/dist/{index-dk6e56g0.js → index-7wpgrqa8.js} +37 -2
- package/dist/{index-10gbbbaa.js → index-9sx8tbz2.js} +1 -1
- package/dist/{index-38hs3a58.js → index-a01jky8m.js} +73 -8
- package/dist/{index-hsabxjz0.js → index-jw81xr75.js} +1 -1
- package/dist/{index-6wzr93cg.js → index-w0445741.js} +1 -1
- package/dist/index-y2s6h5bf.js +83 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +667 -56
- package/dist/node.js +47 -27
- package/dist/observability/index.js +22 -22
- package/dist/react.js +2 -2
- package/dist/realtime/contract.d.ts +30 -11
- package/dist/realtime/contract.d.ts.map +1 -1
- package/dist/realtime/index.d.ts +1 -1
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/server/bun.d.ts.map +1 -1
- package/dist/server/index.js +88 -80
- package/dist/server/multipart.d.ts.map +1 -1
- package/dist/server/node.d.ts.map +1 -1
- package/dist/server/process-signals.d.ts.map +1 -1
- package/dist/server/shutdown.d.ts +2 -0
- package/dist/server/shutdown.d.ts.map +1 -1
- package/dist/testing/surface-conformance.d.ts +4 -2
- package/dist/testing/surface-conformance.d.ts.map +1 -1
- package/dist/testing.js +124 -113
- package/dist/tools.js +57 -57
- package/llms-full.txt +246 -17
- package/native/darwin-arm64.node +0 -0
- package/native/darwin-x64.node +0 -0
- package/package.json +3 -1
- package/dist/index-es0h4w26.js +0 -63
- package/dist/index-xbtcszs7.js +0 -202
package/llms-full.txt
CHANGED
|
@@ -953,21 +953,26 @@ const server = createServer({ services, socket })
|
|
|
953
953
|
|
|
954
954
|
const result = await server.shutdown({
|
|
955
955
|
gracePeriodMs: 30_000,
|
|
956
|
+
realtimeCloseTimeoutMs: 1_000,
|
|
956
957
|
forceTimeoutMs: 5_000,
|
|
957
958
|
retryAfterSeconds: 5,
|
|
958
959
|
signal: shutdownController.signal,
|
|
959
960
|
})
|
|
960
961
|
```
|
|
961
962
|
|
|
962
|
-
The first call closes HTTP and Socket.IO admission, then gives the
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
963
|
+
The first call closes HTTP and Socket.IO admission, then gives admitted HTTP/application work the
|
|
964
|
+
full `gracePeriodMs` budget. Once that work drains, `realtimeCloseTimeoutMs` (default `1_000`)
|
|
965
|
+
bounds WebSocket close handshakes inside the same outer deadline. Any upgraded sockets still open
|
|
966
|
+
at that boundary are terminated without shortening HTTP grace, and graceful runtime shutdown
|
|
967
|
+
continues. If the outer grace budget or external signal forces destructive teardown,
|
|
968
|
+
`forceTimeoutMs` bounds physical completion separately. Repeated calls return the same Promise;
|
|
966
969
|
the first options win. New
|
|
967
970
|
ordinary HTTP work receives `503`, `Retry-After` and `Connection: close` outside
|
|
968
971
|
`wrapFetch`. `result.outcome` is `clean` or `forced`; a forced result preserves
|
|
969
972
|
the pending snapshot and reason while final pending counters describe the
|
|
970
|
-
post-close transport state.
|
|
973
|
+
post-close transport state. `forcedWebSockets` counts both sockets terminated at the dedicated
|
|
974
|
+
realtime bound and sockets terminated by outer force; `pendingWebSocketsAtForce` is only the latter
|
|
975
|
+
snapshot, so a clean result can truthfully report a bounded realtime termination. A graceful phase error still runs forced cleanup and
|
|
971
976
|
then rejects with the original error; a forced transport that cannot confirm
|
|
972
977
|
completion before `forceTimeoutMs` rejects instead of reporting a false zero.
|
|
973
978
|
`runtime` is a diagnostics escape hatch, not a second canonical stop path.
|
|
@@ -1774,6 +1779,14 @@ for a custom raw transport. It uses the same descriptor and returns
|
|
|
1774
1779
|
`{ files, fields, rollback }`; contract endpoints should prefer the automatic
|
|
1775
1780
|
dispatcher path.
|
|
1776
1781
|
|
|
1782
|
+
Both delivery modes preserve UTF-8 `filename` metadata, including browser `FormData` names. For
|
|
1783
|
+
interoperability, a UTF-8 percent-encoded `filename*` parameter takes precedence over `filename`;
|
|
1784
|
+
unsupported charsets or malformed encoding are rejected rather than falling back silently. Literal
|
|
1785
|
+
percent sequences in ordinary `filename` are not decoded. Filenames remain untrusted metadata,
|
|
1786
|
+
not safe filesystem paths. Part headers have a 64 KiB byte limit, are case-insensitive and reject
|
|
1787
|
+
duplicates, folding, invalid header names and control characters. Disposition parameters reject
|
|
1788
|
+
duplicates and unsafe field names; declared part sizes must be nonnegative safe decimal integers.
|
|
1789
|
+
|
|
1777
1790
|
### Rate limiting
|
|
1778
1791
|
|
|
1779
1792
|
```ts
|
|
@@ -4063,13 +4076,21 @@ revalidates the signature/tool call/input before the original direct tool reache
|
|
|
4063
4076
|
fence. Reconnect and SQLite reopen require no promise registry. Remembered policy and a stronger
|
|
4064
4077
|
cross-crash exactly-once guarantee remain application concerns.
|
|
4065
4078
|
|
|
4079
|
+
Approval requests suspend a call; they do not settle its result. History carries exact call and
|
|
4080
|
+
approval identity across assistant/tool records, so an approved result can precede the next signed
|
|
4081
|
+
request in a successor run. Automatic decisions follow the same chronology. Unknown/duplicate
|
|
4082
|
+
responses and results with a different call or tool name are invalid; dropping an invalid active
|
|
4083
|
+
approval input fails the run with a private diagnostic rather than starting a fresh model turn.
|
|
4084
|
+
|
|
4066
4085
|
`stitchkit/agent-runtime/coding-tools` returns ordinary direct runtime tools named `read_file`,
|
|
4067
4086
|
`write_file`, `search_files`, `apply_patch`, `run_command` and optional `read_output`. Every call passes a
|
|
4068
4087
|
required host authorization callback. File paths are relative, bounded and contained after
|
|
4069
4088
|
descriptor-relative resolution: each ancestor is opened without following symlinks and remains
|
|
4070
4089
|
pinned through authorization and the filesystem effect. Reads revalidate the pinned file identity;
|
|
4071
4090
|
writes and patches revalidate the pinned parent identity; search and resource discovery descend
|
|
4072
|
-
only through opened directories. Linux
|
|
4091
|
+
only through opened directories. Linux traverses `/proc/self/fd`; macOS uses the package's
|
|
4092
|
+
architecture-specific Node-API `openat` backend. Unsupported platforms, including FreeBSD until a
|
|
4093
|
+
real backend is qualified, fail closed. The package needs no install-time compiler or script.
|
|
4073
4094
|
Other platforms fail these filesystem operations closed because Node exposes no equivalent
|
|
4074
4095
|
portable directory-handle-relative API. Writes/edits reject symlink targets, content is strict
|
|
4075
4096
|
UTF-8 and retained bytes are finite. Shell accepts a finite alias mapped by the host to an absolute executable plus an
|
|
@@ -6325,6 +6346,171 @@ The bound handle intentionally has no `connect()` or `disconnect()`. Its
|
|
|
6325
6346
|
`on`/`emit`/`request`, rejection and timeout semantics are exactly the path used
|
|
6326
6347
|
by `createRealtimeClient`; only transport construction/lifecycle differs.
|
|
6327
6348
|
|
|
6349
|
+
## Snapshot + event state synchronization
|
|
6350
|
+
|
|
6351
|
+
`createLiveStateController` is the optional browser-safe state machine between a
|
|
6352
|
+
validated transport binding and any renderer. It solves one problem: install a
|
|
6353
|
+
snapshot and every event after that snapshot's consistency point without a race.
|
|
6354
|
+
It does not create a socket, choose a cursor, retry a transport, store history or
|
|
6355
|
+
invent ordering for the application.
|
|
6356
|
+
|
|
6357
|
+
```ts
|
|
6358
|
+
import {
|
|
6359
|
+
createLiveStateController,
|
|
6360
|
+
type LiveStateEventDecision,
|
|
6361
|
+
type LiveStateSource,
|
|
6362
|
+
} from 'stitchkit'
|
|
6363
|
+
|
|
6364
|
+
type View = { revision: number; rows: readonly Row[] }
|
|
6365
|
+
type Change = { revision: number; row: Row }
|
|
6366
|
+
|
|
6367
|
+
const applyChange = (state: View, event: Change): LiveStateEventDecision<View> => {
|
|
6368
|
+
if (event.revision <= state.revision) return { outcome: 'duplicate' }
|
|
6369
|
+
if (event.revision !== state.revision + 1) return { outcome: 'gap' }
|
|
6370
|
+
return {
|
|
6371
|
+
outcome: 'applied',
|
|
6372
|
+
state: { revision: event.revision, rows: [...state.rows, event.row] },
|
|
6373
|
+
}
|
|
6374
|
+
}
|
|
6375
|
+
|
|
6376
|
+
const live = createLiveStateController({
|
|
6377
|
+
source,
|
|
6378
|
+
applyEvent: applyChange,
|
|
6379
|
+
maxBufferedEvents: 128,
|
|
6380
|
+
maxBufferedBytes: 256 * 1024,
|
|
6381
|
+
sizeOfEvent: encodedChangeBytes,
|
|
6382
|
+
})
|
|
6383
|
+
|
|
6384
|
+
const unsubscribe = live.subscribe(render)
|
|
6385
|
+
await live.start()
|
|
6386
|
+
// On a gap/overflow or source loss, choose when the UI should resync.
|
|
6387
|
+
const status = live.getSnapshot()
|
|
6388
|
+
if (status.phase === 'resync-required' || status.phase === 'unavailable') {
|
|
6389
|
+
await live.resync()
|
|
6390
|
+
}
|
|
6391
|
+
|
|
6392
|
+
unsubscribe()
|
|
6393
|
+
await live.close()
|
|
6394
|
+
```
|
|
6395
|
+
|
|
6396
|
+
The source boundary is the important part:
|
|
6397
|
+
|
|
6398
|
+
```ts
|
|
6399
|
+
interface LiveStateSource<State, Event> {
|
|
6400
|
+
open(input: {
|
|
6401
|
+
signal: AbortSignal
|
|
6402
|
+
onEvent(event: Event): void
|
|
6403
|
+
onUnavailable(): void
|
|
6404
|
+
}): Promise<{ snapshot: State; close(): void | Promise<void> }>
|
|
6405
|
+
}
|
|
6406
|
+
```
|
|
6407
|
+
|
|
6408
|
+
`onEvent` is available before `open()` begins asynchronous work. By the time
|
|
6409
|
+
`open()` resolves, the source guarantees that every event after the returned
|
|
6410
|
+
snapshot's consistency point has already been or will be passed to that callback.
|
|
6411
|
+
The controller buffers early events within both explicit limits, installs the
|
|
6412
|
+
snapshot, drains in order, then becomes `live`. A late result from an earlier
|
|
6413
|
+
`resync()` generation is fenced. Non-cooperative caller-owned cleanup is asked to
|
|
6414
|
+
stop but cannot hold controller settlement.
|
|
6415
|
+
|
|
6416
|
+
`subscribe()` listeners are synchronous external-store notifications: read the
|
|
6417
|
+
published snapshot and schedule rendering elsewhere. A listener that returns a
|
|
6418
|
+
Promise is removed after its first call, preventing unresolved UI work from
|
|
6419
|
+
accumulating per event. Source `close()` must be idempotent because an abort-aware
|
|
6420
|
+
binding may have started cleanup before the controller calls it.
|
|
6421
|
+
|
|
6422
|
+
At most two physical source `open()` / `close()` operations in total may remain
|
|
6423
|
+
unsettled. If a caller-owned source ignores cancellation beyond that operation
|
|
6424
|
+
bound, `resync()` returns
|
|
6425
|
+
`unavailable/controller-capacity` without opening another generation. When a slot
|
|
6426
|
+
settles, the controller publishes `resync-required/controller-capacity`; the host
|
|
6427
|
+
may retry explicitly. This bounds controller-retained work without inventing a
|
|
6428
|
+
transport retry loop.
|
|
6429
|
+
|
|
6430
|
+
### Socket.IO binding
|
|
6431
|
+
|
|
6432
|
+
Use an acknowledged operation whose server handler establishes the subscription
|
|
6433
|
+
before it captures/returns the snapshot. For example, the server can join the
|
|
6434
|
+
socket to the resource room, capture revision `N`, then acknowledge that snapshot;
|
|
6435
|
+
ordered Socket.IO frames after that point reach the already-installed handler:
|
|
6436
|
+
|
|
6437
|
+
```ts
|
|
6438
|
+
const source: LiveStateSource<View, Change> = {
|
|
6439
|
+
async open({ signal, onEvent, onUnavailable }) {
|
|
6440
|
+
const offEvent = socket.on('view:changed', onEvent)
|
|
6441
|
+
const offConnection = socket.onConnectionChange((connected) => {
|
|
6442
|
+
if (!connected) onUnavailable()
|
|
6443
|
+
})
|
|
6444
|
+
let closed = false
|
|
6445
|
+
const close = () => {
|
|
6446
|
+
if (closed) return
|
|
6447
|
+
closed = true
|
|
6448
|
+
offEvent()
|
|
6449
|
+
offConnection()
|
|
6450
|
+
}
|
|
6451
|
+
signal.addEventListener('abort', close, { once: true })
|
|
6452
|
+
|
|
6453
|
+
try {
|
|
6454
|
+
const snapshot = await socket.request('view:open', { timeoutMs: 5_000 })
|
|
6455
|
+
return { snapshot, close }
|
|
6456
|
+
} catch (error) {
|
|
6457
|
+
close()
|
|
6458
|
+
throw error
|
|
6459
|
+
}
|
|
6460
|
+
},
|
|
6461
|
+
}
|
|
6462
|
+
```
|
|
6463
|
+
|
|
6464
|
+
Socket.IO still owns physical reconnect. A reconnected transport only means the
|
|
6465
|
+
connection is open; call `resync()` when application state needs a fresh
|
|
6466
|
+
generation. If the application has replay, its source may resume from its opaque
|
|
6467
|
+
cursor and return an accepted consistency point. If history expired or a cursor is
|
|
6468
|
+
incompatible, the source must acquire a fresh authoritative snapshot or reject the
|
|
6469
|
+
open; the controller does not classify or compare opaque cursors itself.
|
|
6470
|
+
|
|
6471
|
+
### One-way HTTP stream binding
|
|
6472
|
+
|
|
6473
|
+
NDJSON/SSE can use the same receiver semantics when **one response generation**
|
|
6474
|
+
starts with a schema-validated snapshot frame and every later frame is a validated
|
|
6475
|
+
event. Attach `parseNDJSON` or the typed contract-stream reader, parse the first
|
|
6476
|
+
frame before resolving `open()`, and pump remaining frames into `onEvent`. Abort
|
|
6477
|
+
that response in `close()`.
|
|
6478
|
+
|
|
6479
|
+
A separate `GET /snapshot` followed by `GET /events` is not this boundary: a
|
|
6480
|
+
change can land between the two requests and disappear unless the application
|
|
6481
|
+
supplies a watermark/replay protocol. The controller intentionally cannot make
|
|
6482
|
+
that uncoordinated recipe safe.
|
|
6483
|
+
|
|
6484
|
+
### Rendering, cache and process lifecycle
|
|
6485
|
+
|
|
6486
|
+
For replaceable progress, let the reducer replace the absolute view at each
|
|
6487
|
+
accepted revision. For ordered records, append only the exact next revision and
|
|
6488
|
+
return `gap` otherwise. Both use the same controller; their ordering policy stays
|
|
6489
|
+
in their reducers. `getSnapshot()` + `subscribe()` works headlessly and with
|
|
6490
|
+
`useSyncExternalStore`. A React Query application can update its existing query
|
|
6491
|
+
cache from a subscriber after `phase === 'live'`; no second hook or store adapter
|
|
6492
|
+
is required. Cache `markFresh` windows suppress local echoes, while revision/cursor
|
|
6493
|
+
classification detects duplicates—those are different policies.
|
|
6494
|
+
|
|
6495
|
+
A server process that owns such a receiver can place `start()` and `close()` in
|
|
6496
|
+
an existing `defineManagedResource` and include it in `createApplication`.
|
|
6497
|
+
Readiness follows a successful `live` snapshot; shutdown calls `close()`. Stitchkit
|
|
6498
|
+
does not add another supervisor, reconnect loop or durable event database.
|
|
6499
|
+
|
|
6500
|
+
When migrating a hand-written receiver, remove only the superseded attach/snapshot
|
|
6501
|
+
race loop, retry timer and listener bookkeeping. Keep the application's schemas,
|
|
6502
|
+
authorization, reducer, cursor/replay policy and durable storage. Development
|
|
6503
|
+
proxying and Vite HMR remain frontend tooling; they are described in
|
|
6504
|
+
[frontend integrations](./frontend-integrations.md) and never travel through live
|
|
6505
|
+
application event envelopes.
|
|
6506
|
+
|
|
6507
|
+
The Agent harness control server follows the same ordering: it installs the
|
|
6508
|
+
conversation attachment before awaiting the authoritative snapshot and rolls the
|
|
6509
|
+
attachment back if that read fails. A host adapter installs its delivery callback,
|
|
6510
|
+
issues `attach`, and supplies the returned snapshot through its live-state source;
|
|
6511
|
+
the existing Agent cursor and view reducers still own runtime epochs, durable
|
|
6512
|
+
versions and transcript projection.
|
|
6513
|
+
|
|
6328
6514
|
### Request-response over realtime
|
|
6329
6515
|
|
|
6330
6516
|
For an event with an `ack` schema, `request()` is the Promise form of the same
|
|
@@ -8899,11 +9085,13 @@ current one *up to* your target, and apply each snippet.
|
|
|
8899
9085
|
### Descriptor-backed Agent filesystem containment
|
|
8900
9086
|
|
|
8901
9087
|
Built-in coding file/search tools and `createAgentHarnessFileResources` now require a runtime
|
|
8902
|
-
that can address an opened directory descriptor: Linux `/proc/self/fd`, or macOS
|
|
8903
|
-
|
|
9088
|
+
that can address an opened directory descriptor: Linux `/proc/self/fd`, or the packaged macOS
|
|
9089
|
+
Node-API backend added in 0.70.1. This is what keeps a mutable parent rename or outside-symlink replacement from changing
|
|
8904
9090
|
the authorized target between validation and the actual effect.
|
|
8905
9091
|
|
|
8906
|
-
No call-site change is needed on those platforms.
|
|
9092
|
+
No call-site change is needed on those platforms. The 0.70.0 notes incorrectly inferred macOS and
|
|
9093
|
+
FreeBSD support from `/dev/fd`; macOS is restored by 0.70.1 and FreeBSD remains unsupported. On
|
|
9094
|
+
Windows or another platform without that
|
|
8907
9095
|
boundary, move the built-in filesystem operations to a supported worker or replace them with
|
|
8908
9096
|
application-owned tools backed by an equivalent native handle API. They fail closed rather than
|
|
8909
9097
|
falling back to path spelling. `run_command` remains separately available under its explicit
|
|
@@ -11262,7 +11450,7 @@ description: One machine-readable statement a repository makes about itself —
|
|
|
11262
11450
|
type: architecture
|
|
11263
11451
|
status: active
|
|
11264
11452
|
created: 2026-08-25
|
|
11265
|
-
updated: 2026-08-
|
|
11453
|
+
updated: 2026-08-30
|
|
11266
11454
|
---
|
|
11267
11455
|
|
|
11268
11456
|
# Project declaration
|
|
@@ -11297,6 +11485,32 @@ mode that produces a running, wrong deployment rather than an error.
|
|
|
11297
11485
|
|
|
11298
11486
|
## Why declare yourself
|
|
11299
11487
|
|
|
11488
|
+
### Identity is not product membership
|
|
11489
|
+
|
|
11490
|
+
The exported names `ProjectDeclaration` and `ProjectIdentity` describe the buildable source/artifact
|
|
11491
|
+
declared by a repository. A singular `identity` does **not** make a product project and a repository
|
|
11492
|
+
the same entity, nor does it identify a local checkout or a harness session.
|
|
11493
|
+
|
|
11494
|
+
| Entity | Meaning and owner |
|
|
11495
|
+
| --- | --- |
|
|
11496
|
+
| Product project | A product boundary whose repository membership is explicitly maintained outside this declaration |
|
|
11497
|
+
| Repository | Versioned source; its declaration describes roles, build outputs and release requirements |
|
|
11498
|
+
| Checkout | A local working copy of a repository revision; local paths and credentials belong to its host |
|
|
11499
|
+
| Harness workspace | The host-selected working scope for a session, not an implied product or membership registry |
|
|
11500
|
+
|
|
11501
|
+
Membership is many-to-many. For example, an external registry may declare product A includes
|
|
11502
|
+
repositories `service-a` and `shared-library`, while product B includes `service-b` and the same
|
|
11503
|
+
`shared-library`. Both products can read the library's unchanged declaration. Installing that library
|
|
11504
|
+
as a dependency, placing a checkout beside another, or naming a harness workspace does not create
|
|
11505
|
+
membership. The embedding product/registry owns these explicit relationships and their access policy.
|
|
11506
|
+
|
|
11507
|
+
A private companion repository can be part of a product without becoming a separate product. Its
|
|
11508
|
+
relationship and working context stay in an authorized private registry, never in a potentially public
|
|
11509
|
+
library declaration. No registry or membership fields are required here; the declaration remains
|
|
11510
|
+
optional. Existing exports and schema version 1 are unchanged.
|
|
11511
|
+
|
|
11512
|
+
### One statement, several readers
|
|
11513
|
+
|
|
11300
11514
|
Because the statements exist either way, and without a schema they exist three
|
|
11301
11515
|
times. A repository already says how many roles it runs (in a process file),
|
|
11302
11516
|
which variables it needs (in a Zod schema), what it builds (in a script) and
|
|
@@ -11492,6 +11706,16 @@ The browser-and-server entrypoint. Re-exports everything from
|
|
|
11492
11706
|
| `defineRealtimeContract` | function | Zod-first shared Socket.IO event contract — [guide](../guide/realtime.md#zod-first-event-contract) |
|
|
11493
11707
|
| `createRealtimeClient` | function | inferred, runtime-validated Socket.IO client — [guide](../guide/realtime.md#client--createrealtimeclient) |
|
|
11494
11708
|
| `bindRealtimeClient` | function | bind contract validation and typed acknowledgements to an existing Stitchkit client transport without owning its lifecycle |
|
|
11709
|
+
| `createLiveStateController` | function | keep typed application state current across one source-owned snapshot/event generation with finite pre-snapshot buffering, generation fencing and explicit resync — [guide](../guide/realtime.md#snapshot--event-state-synchronization) |
|
|
11710
|
+
| `LiveStateController` | _type_ | renderer-neutral `start` / `resync` / `getSnapshot` / `subscribe` / `close` handle |
|
|
11711
|
+
| `LiveStateControllerConfig` | _type_ | typed source, reducer, explicit event/byte bounds, event sizing and isolated error hooks |
|
|
11712
|
+
| `LiveStateControllerSnapshot` / `LiveStateControllerStatus` | _types_ | current value plus phase, generation, buffer and application/duplicate/gap/refusal counters |
|
|
11713
|
+
| `LiveStateControllerStatusSchema` | schema | strict runtime validation for controller status metadata |
|
|
11714
|
+
| `LiveStatePhaseSchema` / `LiveStatePhase` | schema / _type_ | `idle`, `opening`, `live`, `resync-required`, `unavailable` or `closed` |
|
|
11715
|
+
| `LiveStateStopReasonSchema` / `LiveStateStopReason` | schema / _type_ | explicit gap, overflow, source loss, controller failure and bounded `controller-capacity` reasons |
|
|
11716
|
+
| `LiveStateEventDecision` | _type_ | provider-owned reducer result: applied state, duplicate or gap |
|
|
11717
|
+
| `LiveStateSource` / `LiveStateSourceOpenInput` / `LiveStateSourceOpenResult` | _types_ | host binding for one continuous snapshot/event boundary; transport retry and cursor semantics remain host-owned |
|
|
11718
|
+
| `LiveStateControllerError` / `LiveStateSubscriberError` | _types_ | isolated observer failure payloads that do not change source or subscriber truth |
|
|
11495
11719
|
| `createRetainedTopics` | function | retained last-value store for sticky events — [guide](../guide/realtime.md#sticky-events) |
|
|
11496
11720
|
| `parseSSE` | function | parse an SSE `Response` into an async generator — [guide](../guide/client.md#sse) |
|
|
11497
11721
|
| `parseNDJSON` | function | parse bounded fatal-UTF-8 NDJSON; blank keep-alives are skipped and `finalLine: 'require-newline'` can make the delimiter mandatory — [guide](../guide/client.md#ndjson) |
|
|
@@ -11531,7 +11755,7 @@ The browser-and-server entrypoint. Re-exports everything from
|
|
|
11531
11755
|
| `RealtimeEmitArguments` | _type_ | emit arguments including an inferred acknowledgement callback |
|
|
11532
11756
|
| `RealtimeEventHandler` | _type_ | handler inferred from an event definition |
|
|
11533
11757
|
| `InferRealtimeEventMap` | _type_ | inferred Socket.IO-compatible event map |
|
|
11534
|
-
| `RealtimeRejectDirection` |
|
|
11758
|
+
| `RealtimeRejectDirection` / `RealtimeRejectPhase` / `RealtimeRejectReason` / `RealtimeRejectFault` | _types_ | canonical inferred rejection direction, validation phase, reason and fault classification |
|
|
11535
11759
|
| `RealtimeRejectedEvent` | _type_ | structured rejected event with event, direction, phase, reason and fault |
|
|
11536
11760
|
| `RealtimeRejectedEventHook` | _type_ | sync/async observer for structured realtime rejections |
|
|
11537
11761
|
| `ValidatedRealtimeSocket` | _type_ | runtime-validating `on`/`emit` surface inferred from registries; `emit` returns "accepted by the transport" (`false` only for a client-side disconnected drop) |
|
|
@@ -11697,9 +11921,9 @@ Also re-exports the error helpers from `stitchkit/contract`.
|
|
|
11697
11921
|
| `UnixListenConfig` | _type_ | unix listener — a socket path, or `{ path, mode }` to tighten the file mode after listen |
|
|
11698
11922
|
| `BunServerHandle` | _type_ | managed Bun handle (`url`, `port`, `runtime`, `status`, `shutdown`) |
|
|
11699
11923
|
| `ManagedServerHandle` | _type_ | shared lifecycle shape generic over the runtime escape hatch |
|
|
11700
|
-
| `ShutdownOptionsSchema` / `ShutdownOptions` | schema / _type_ |
|
|
11924
|
+
| `ShutdownOptionsSchema` / `ShutdownOptions` | schema / _type_ | HTTP/application grace, a separate WebSocket close-handshake bound, bounded forced-completion timeout, retry hint and optional external abort signal |
|
|
11701
11925
|
| `ShutdownStatusSchema` / `ShutdownStatus` | schema / _type_ | live state and request/WebSocket counters |
|
|
11702
|
-
| `ShutdownResultSchema` / `ShutdownResult` | schema / _type_ | clean/forced result with final counters
|
|
11926
|
+
| `ShutdownResultSchema` / `ShutdownResult` | schema / _type_ | clean/forced result with final counters, outer-force snapshots and `forcedWebSockets` including bounded realtime terminations |
|
|
11703
11927
|
| `ShutdownStateSchema` / `ShutdownState` | schema / _type_ | managed lifecycle state machine |
|
|
11704
11928
|
| `ServiceDef` | _type_ | the result of `implement` |
|
|
11705
11929
|
| `MethodDef` | _type_ | one resolved endpoint inside a service |
|
|
@@ -11887,7 +12111,7 @@ cutovers are covered by the executable
|
|
|
11887
12111
|
| `ManagedResourceDependency` | _type_ | a dependency named by id or given as the resource itself — the second form is what `context.use(...)` can type |
|
|
11888
12112
|
| `ManagedResourcePublished` | _type_ | the value type `context.use(resource)` returns, recovered from that resource's own `start` |
|
|
11889
12113
|
| `ManagedResourcePublishesNoValue` | _type_ | what `context.use(...)` returns for a resource that publishes nothing — a branded refusal rather than `never`, so reading it does not silently compile |
|
|
11890
|
-
| `ManagedServerResourceConfig` | _type_ | the server or a sync/async factory receiving `ManagedResourceContext`, plus stable ID, dependencies and shutdown policy
|
|
12114
|
+
| `ManagedServerResourceConfig` | _type_ | the server or a sync/async factory receiving `ManagedResourceContext`, plus stable ID, dependencies and server shutdown policy (`retryAfterSeconds`, `realtimeCloseTimeoutMs`) |
|
|
11891
12115
|
| `ManagedServerResource` | _type_ | the resource `managedServerResource` returns, whose `start` publishes the `ManagedServerHandle` |
|
|
11892
12116
|
| `ApplicationHealthHandlerOptions` / `ApplicationHealthHandlerOptionsSchema` | _type_ / schema | liveness/readiness selection and sanitized `Retry-After` policy |
|
|
11893
12117
|
| `ApplicationOperationalHandlers` / `ApplicationOperationalHandlersOptions` / `ApplicationOperationalHandlersOptionsSchema` | _type_ / schema | conventional status/readiness/liveness route surface and shared retry policy |
|
|
@@ -12229,7 +12453,7 @@ and introduces no store, queue or model-provider implementation of its own.
|
|
|
12229
12453
|
| `AgentHarnessFileResources` | _type_ | loader plus direct `read_resource` definition for lazy exact content |
|
|
12230
12454
|
| `createAgentHarnessControlServer` | function | transport-neutral correlated requests, observer attachments and exclusive controller leases |
|
|
12231
12455
|
| `AgentHarnessControlServer` / `AgentHarnessControlConnection` | _type_ | host server and detachable connection lifecycle; `deliver` is serialized, while required out-of-band `onOverflow` closes/aborts a slow transport before reconnect |
|
|
12232
|
-
| `AgentHarnessControlServerConfig` | _type_ | explicit per-connection pending-event
|
|
12456
|
+
| `AgentHarnessControlServerConfig` | _type_ | explicit per-connection pending-event and server-wide concurrent attachment-snapshot bounds for failure-isolated control delivery |
|
|
12233
12457
|
| `AgentHarnessPendingApproval` / `AgentHarnessApprovalDecision` | _type_ | exact durable pending request and allow/deny successor input |
|
|
12234
12458
|
|
|
12235
12459
|
Resources default to at most 64 entries, 1 MiB of total UTF-8 text and 128 diagnostics. Duplicate
|
|
@@ -12244,7 +12468,7 @@ artifact store is supplied, `read_output`.
|
|
|
12244
12468
|
|
|
12245
12469
|
| Export | Kind | Summary |
|
|
12246
12470
|
|--------|------|---------|
|
|
12247
|
-
| `createAgentCodingTools` | function | construct direct host-authorized bounded file, search, guarded patch, shell and artifact runtime-tool definitions; filesystem operations
|
|
12471
|
+
| `createAgentCodingTools` | function | construct direct host-authorized bounded file, search, guarded patch, shell and artifact runtime-tool definitions; filesystem operations use Linux `/proc/self/fd` or the packaged macOS Node-API backend and otherwise fail closed |
|
|
12248
12472
|
| `AgentCodingToolDefinition` | _type_ | peer-free structural direct-tool shape accepted by the canonical runtime-tool surface |
|
|
12249
12473
|
| `AgentCodingToolConfig` | _type_ | absolute root, required authorization callback, finite executable alias map, exact child environment and optional limits |
|
|
12250
12474
|
| `AgentCodingToolAuthorizationSchema` / `AgentCodingToolAuthorization` | schema / _type_ | discriminated read/write/search/patch/shell/artifact decision presented to host policy before effect |
|
|
@@ -12724,7 +12948,7 @@ handler pipeline without opening a TCP port.
|
|
|
12724
12948
|
| `DefineRealtimeProbeConfig` | _type_ | name, canonical scenario, explicit fixture and expected realtime outcome |
|
|
12725
12949
|
| `CreateRealtimeProbeDriverConfig` | _type_ | per-scenario foreign-transport binder and optional handler-call counter |
|
|
12726
12950
|
| `RealtimeProbeAdapter` | _type_ | connected-state observation, scenario invocation and subscription-only cleanup |
|
|
12727
|
-
| `RealtimeProbeFixture` / `RealtimeProbeScenario` | _type_ | driver input and supported event/ack/invalid/disconnect/timeout scenario vocabulary |
|
|
12951
|
+
| `RealtimeProbeFixture` / `RealtimeProbeScenario` | _type_ | driver input and supported event/ack/local-invalid/peer-refusal/disconnect/timeout scenario vocabulary |
|
|
12728
12952
|
| `RealtimeRejectionObservation` | _type_ | parsed structured realtime rejection observation |
|
|
12729
12953
|
| `RealtimeDisconnectObservation` | _type_ | normalized physical timing of a realtime disconnect |
|
|
12730
12954
|
| `TransportObservation` | _type_ | validated normalized driver result |
|
|
@@ -12775,6 +12999,11 @@ by the scaffolder that writes the first copy, and by whatever builds a source an
|
|
|
12775
12999
|
binds the artifact into a deployment. It ships from the framework so those
|
|
12776
13000
|
readers cannot hold different copies of the same schema.
|
|
12777
13001
|
|
|
13002
|
+
`identity` identifies the repository-local buildable source/artifact, not a product project, checkout
|
|
13003
|
+
or harness workspace. Product↔repository membership is explicit and many-to-many, owned by an
|
|
13004
|
+
external registry; dependency edges do not establish membership. Private companion context is never
|
|
13005
|
+
required in this public schema. See [identity boundaries](../guide/declaration.md#identity-is-not-product-membership).
|
|
13006
|
+
|
|
12778
13007
|
**Declaring yourself is optional.** A project with no `project.json` is a
|
|
12779
13008
|
complete project: nothing else in the framework imports this entrypoint, no
|
|
12780
13009
|
build, test or start path looks for a declaration, and its absence is never an
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stitchkit",
|
|
3
|
-
"version": "0.70.
|
|
3
|
+
"version": "0.70.2",
|
|
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",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"types": "./dist/index.d.ts",
|
|
39
39
|
"files": [
|
|
40
40
|
"dist",
|
|
41
|
+
"native/*.node",
|
|
41
42
|
"llms.txt",
|
|
42
43
|
"llms-full.txt",
|
|
43
44
|
"README.md",
|
|
@@ -141,6 +142,7 @@
|
|
|
141
142
|
"access": "public"
|
|
142
143
|
},
|
|
143
144
|
"scripts": {
|
|
145
|
+
"build:native-contained-files": "node scripts/build-contained-files-native.mjs",
|
|
144
146
|
"check": "bun x tsc --noEmit",
|
|
145
147
|
"build:browser": "bun build src/index.ts src/react.ts src/contract/index.ts src/declaration.ts src/agent-runtime-browser.ts --outdir dist --target node --packages external --splitting --root src",
|
|
146
148
|
"build:server": "bun build src/server/index.ts src/node.ts src/tools.ts src/tool-invoker.ts src/cli.ts src/remote.ts src/files.ts src/testing.ts src/observability/index.ts src/agent-runtime.ts src/agent-runtime-harness.ts src/agent-runtime-coding-tools.ts src/agent-runtime-openrouter.ts src/agent-runtime-sqlite-bun.ts src/agent-runtime-sqlite-node.ts src/application.ts src/application-grammy.ts src/application-opentelemetry.ts --outdir dist --target node --packages external --splitting --root src",
|
package/dist/index-es0h4w26.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
// src/agent-runtime/terminal-status.ts
|
|
2
|
-
function isSpeakableAssistantStatus(status) {
|
|
3
|
-
return status === "completed" || status === "interrupted" || status === "committed";
|
|
4
|
-
}
|
|
5
|
-
function isAssistantHistoryEvidence(status, policy) {
|
|
6
|
-
return isSpeakableAssistantStatus(status) || status === "failed" && policy?.failedAssistant === "assistant-marked";
|
|
7
|
-
}
|
|
8
|
-
function isCompleteAgentHistoryTurn(messages, policy) {
|
|
9
|
-
if (messages[0]?.role !== "user")
|
|
10
|
-
return false;
|
|
11
|
-
const calls = new Set;
|
|
12
|
-
const completed = new Set;
|
|
13
|
-
const approvals = new Map;
|
|
14
|
-
let assistantCount = 0;
|
|
15
|
-
for (const message of messages) {
|
|
16
|
-
if (message.role === "assistant") {
|
|
17
|
-
if (!isAssistantHistoryEvidence(message.status, policy))
|
|
18
|
-
return false;
|
|
19
|
-
assistantCount += 1;
|
|
20
|
-
}
|
|
21
|
-
for (const part of message.parts) {
|
|
22
|
-
if (part.type === "tool-call") {
|
|
23
|
-
if (calls.has(part.callId))
|
|
24
|
-
return false;
|
|
25
|
-
calls.add(part.callId);
|
|
26
|
-
} else if (part.type === "tool-approval-request") {
|
|
27
|
-
if (!calls.has(part.callId) || completed.has(part.callId) || approvals.has(part.approvalId))
|
|
28
|
-
return false;
|
|
29
|
-
if ([...approvals.values()].some((approval) => approval.callId === part.callId))
|
|
30
|
-
return false;
|
|
31
|
-
approvals.set(part.approvalId, { callId: part.callId, answered: false });
|
|
32
|
-
} else if (part.type === "tool-approval-response") {
|
|
33
|
-
const approval = approvals.get(part.approvalId);
|
|
34
|
-
if (!approval || approval.answered)
|
|
35
|
-
return false;
|
|
36
|
-
approval.answered = true;
|
|
37
|
-
} else if (part.type === "tool-result") {
|
|
38
|
-
if (!calls.has(part.callId) || completed.has(part.callId))
|
|
39
|
-
return false;
|
|
40
|
-
const approval = [...approvals.values()].find((entry) => entry.callId === part.callId);
|
|
41
|
-
if (approval && !approval.answered)
|
|
42
|
-
return false;
|
|
43
|
-
completed.add(part.callId);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return assistantCount > 0 && calls.size === completed.size && [...approvals.values()].every((approval) => approval.answered);
|
|
48
|
-
}
|
|
49
|
-
function assistantStatus(reason) {
|
|
50
|
-
if (reason === "success" || reason === "policy_stop" || reason === "provider_stop") {
|
|
51
|
-
return "completed";
|
|
52
|
-
}
|
|
53
|
-
if (reason === "superseded")
|
|
54
|
-
return "superseded";
|
|
55
|
-
if (reason === "absorbed")
|
|
56
|
-
return "superseded";
|
|
57
|
-
if (reason === "interrupted" || reason === "cancelled" || reason === "shutdown") {
|
|
58
|
-
return "interrupted";
|
|
59
|
-
}
|
|
60
|
-
return "failed";
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export { isAssistantHistoryEvidence, isCompleteAgentHistoryTurn, assistantStatus };
|