API reference
Every public export of stitchkit, grouped by entrypoint. Each entry links to the guide page that explains it in context. Types are marked type; everything else is a value (a function, a class, a constant).
The root stitchkit entrypoint is browser-safe; stitchkit/server and
stitchkit/tools are server-only. See
Getting started → entrypoints.
stitchkit
The browser-and-server entrypoint. Re-exports everything from
stitchkit/contract, plus the client and browser realtime.
Client
| Export | Kind | Summary |
|---|---|---|
createClient |
function | build a typed client from a contract — guide |
createClients |
function | build one exact typed client per contract from a registry; accepts the same scoped config and transports as createClient |
createScopedClients |
function | build one registry routed by contract scope; arrays compose contracts into one namespace |
createScopedUrlBuilders |
function | build one URL registry routed by contract scope; arrays compose contracts into one namespace |
ScopeClientConfigs |
type | per-scope routing configuration consumed by scoped clients and URL builders |
ScopedClientRegistry |
type | exact composed registry returned by createScopedClients |
ScopedUrlBuilderRegistry |
type | exact composed registry returned by createScopedUrlBuilders |
ClientRegistryValue |
type | one contract or a contract array composing one client namespace |
ClientContract |
type | HTTP-client-compatible contract value used by scoped registries |
RegistryScope |
type | contract-scope union inferred from a scoped client registry value |
createUrlBuilder |
function | build synchronous browser-native URLs for all HTTP endpoints; body methods accept URL-bound args only — guide |
createUrlBuilders |
function | build one exact URL builder per contract in a registry |
UrlBuilderConfig |
type | explicit { baseUrl } source for a URL builder |
ClientConfig |
type | config for createClient’s bare-fetch mode (2nd arg, no HttpClient) |
ClientFetch |
type | injectable Fetch-compatible transport used by framework and application-owned adapters |
ClientRequestOptions |
type | per-call { signal?, onUploadProgress? } passed through an endpoint callable’s .withOptions(...); caller abort is distinct from timeout — guide |
UploadProgress |
type | { sentBytes, totalBytes, attempt } heard by onUploadProgress: bytes of the encoded body handed to the network, first 0, last totalBytes, counted again on each transport retry — guide |
uploadInChunks |
function | send a file larger than one request as init → parts → finalize through three calls the app owns; client-minted id, repeats of a part on a failure that may pass, finalize never repeated, cancel checked between parts, progress in file bytes — guide |
ChunkedUploadConfig / ChunkedUploadStart / ChunkedUploadPart / ChunkedUploadProgress |
type | the driver’s file, part size, retries and three calls; what init declares; one part; progress { sentBytes, totalBytes, index, chunkCount, attempt } |
ChunkSource |
type | what the driver reads a file through — size and slice(start, end); a Blob is one, so is a platform file that is not (an Expo File), and a part’s bytes is what its slice returns |
ContractClientConfig |
type | per-tenant / resource-scoped client config — dynamic pathPrefix + stripPrefixKeys (guide) |
contractEndpointMatchers |
function | compile exact pathname matchers for selected HTTP contract operations and expected-401 policy |
PathPrefixArgs |
type | required string-valued keys exposed to a typed dynamic pathPrefix callback |
createHttpClient |
function | the Ky-based HTTP transport; on Next.js SSR its first attempt stays request-memoizable while every retry is a distinct transport attempt — guide |
ApiError |
class | a non-2xx or client failure, with code / status / details / hint, optional readonly traceId from x-request-id, and standard cause preserving an injected transport failure |
zodIssues |
function | a ZodError → structured { path, code, message }[] — the exact projection a VALIDATION_ERROR carries in ApiError.details.issues, so a caller renders one shape. Also on stitchkit/server; same name, one definition |
ZodIssueSummary |
type | one structured validation issue ({ path, code, message }) — the element type of details.issues. Also on stitchkit/server |
formatZodError |
function | a ZodError → a readable, field-summarised string. Also on stitchkit/server |
HttpClient |
type | the transport interface createClient builds on |
ConfiguredHttpClient |
type | a framework-created HttpClient carrying its readonly baseUrl for URL builders |
HttpClientConfig |
type | config for createHttpClient; retry limit counts retries after the initial attempt (default 2 = at most 3 GET attempts), with statusCodes: [] by default; fetch installs an explicit transport and is mutually exclusive with the legacy Bun-only unix option — details |
UnauthorizedMatcher |
type | exact (pathname) => boolean policy accepted by suppressUnauthorizedFor |
RequestOptions |
type | per-call options — params, timeout, response type, onUploadProgress |
HeaderProvider |
type | static or per-request headers |
ApiEvent |
type | a client event — unauthorized / network_error / logout |
ApiEventListener |
type | an ApiEvent handler |
Realtime (client) & streaming
| Export | Kind | Summary |
|---|---|---|
createSocketIOClient |
function | low-level typed Socket.IO transport primitive — guide |
defineRealtimeContract |
function | Zod-first shared Socket.IO event contract — guide |
createRealtimeClient |
function | inferred, runtime-validated Socket.IO client — guide |
bindRealtimeClient |
function | bind contract validation and typed acknowledgements to an existing Stitchkit client transport without owning its lifecycle |
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 |
LiveStateController |
type | renderer-neutral start / resync / getSnapshot / subscribe / close handle |
LiveStateControllerConfig |
type | typed source, reducer, explicit event/byte bounds, event sizing and isolated error hooks |
LiveStateControllerSnapshot / LiveStateControllerStatus |
types | current value plus phase, generation, buffer and application/duplicate/gap/refusal counters |
LiveStateControllerStatusSchema |
schema | strict runtime validation for controller status metadata |
LiveStatePhaseSchema / LiveStatePhase |
schema / type | idle, opening, live, resync-required, unavailable or closed |
LiveStateStopReasonSchema / LiveStateStopReason |
schema / type | explicit gap, overflow, source loss, controller failure and bounded controller-capacity reasons |
LiveStateEventDecision |
type | provider-owned reducer result: applied state, duplicate or gap |
LiveStateSource / LiveStateSourceOpenInput / LiveStateSourceOpenResult |
types | host binding for one continuous snapshot/event boundary; transport retry and cursor semantics remain host-owned |
LiveStateControllerError / LiveStateSubscriberError |
types | isolated observer failure payloads that do not change source or subscriber truth |
createRetainedTopics |
function | retained last-value store for sticky events — guide |
parseSSE |
function | parse SSE from a Response, a web stream or an async byte iterable into an async generator — guide |
parseNDJSON |
function | parse bounded fatal-UTF-8 NDJSON from a Response, a ReadableStream<Uint8Array> or an AsyncIterable<Uint8Array> (a child’s stdout); blank keep-alives are skipped, finalLine: 'require-newline' makes the delimiter mandatory and signal cancels the source — guide |
createNDJSONDecoder / NDJSONDecoder |
function / type | the same bounded NDJSON reading driven by push(chunk) / end(), for a socket data callback |
readBoundedBody / BoundedBodyOptions |
function / type | the whole body of a ReadableStream<Uint8Array> or async byte iterable as bytes, never reading past maxBytes plus one chunk; limitError(observedBytes) and abortError(reason) choose the two errors, the source is cancelled on both, a null body is empty — guide |
StreamByteSource |
type | Response | ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>, what the NDJSON and SSE readers accept |
StreamLineLimitError / StreamTruncatedLineError |
class | a line past maxLineBytes (limitBytes, lineBytes; a RangeError) and a source ended inside a line under require-newline (lineBytes; a SyntaxError) |
resumableIterator |
function | re-open a long-lived stream from the last delivered cursor, with jittered backoff, a caller-owned terminal item and prompt abort — guide |
createBackoff |
function | exponential backoff with subtractive jitter as a value: next() / reset() |
ContractStreamFrameSchema / ContractStreamFrame |
schema / type | default on-the-wire data / safe error / end envelope of a contract-first stream |
ContractStreamFraming / ContractStreamCompletion |
types | opt-in item-vs-envelope framing and terminal-vs-stream-end completion policies |
StreamFinalLinePolicy |
type | permissive or newline-required final NDJSON line policy |
DEFAULT_CONTRACT_STREAM_FRAME_BYTES |
const | default maximum encoded contract-stream frame: 256 KiB |
SocketIOClient |
type | low-level client handle; emit reports disconnected drops and emitWithAck exposes the native Promise primitive used by validated request() |
SocketIOClientPeerLoaders |
type | inject socket.io-client so a bundler can put it in a self-contained artifact |
SocketIOClientConfig |
type | config for createSocketIOClient (incl. retain, onConnectError, onDroppedEmit) |
SocketEventMap |
type | the shape of an event map |
RealtimeClient |
type | validated client inferred from a realtime contract |
RealtimeClientOptions |
type | transport options plus rejected-event and metadata-only acknowledged-request phase hooks for createRealtimeClient |
BoundRealtimeClient |
type | validated non-owning on/emit/request client with no connect/disconnect |
RealtimeClientTransport |
type | minimal existing transport capability accepted by bindRealtimeClient |
BindRealtimeClientOptions |
type | rejection/logger options for a bound existing transport |
RealtimeAcknowledgedEvent |
type | event-name union restricted to definitions with an ack schema |
RealtimeAcknowledgement |
type | validated acknowledgement output inferred from an event definition |
RealtimeRequestArguments |
type | request arguments inferred from an acknowledged event tuple |
RealtimeRequestOptions |
type | finite positive native acknowledgement timeoutMs plus an optional invocation-scoped onPhase observer |
RealtimeRequestPhaseSchema / RealtimeRequestPhase |
schema / type | closed engine-handoff / engine-ack-received / settled / timeout / disconnected lifecycle |
RealtimeRequestPhaseEventSchema / RealtimeRequestPhaseEvent |
schema / type | strict metadata-only { requestId, event, phase, elapsedMs } observation |
RealtimeRequestPhaseHook |
type | isolated sync/async observer accepted globally by RealtimeClientOptions.onRequestPhase or per invocation by RealtimeRequestOptions.onPhase |
RealtimeRequestTimeoutError |
class | stable REALTIME_REQUEST_TIMEOUT rejection |
RealtimeRequestDisconnectedError |
class | stable REALTIME_REQUEST_DISCONNECTED rejection, including an immediate disconnected call |
RealtimeRequestInvalidAcknowledgementError |
class | invalid ack was reported through onRejected and the request rejected |
RealtimeRequestRejectedError |
class | the peer refused the frame against its own contract and said so — reason, issues — instead of leaving the sender to time out (ADR 0106) |
REALTIME_REJECTION_KEY |
const | the reserved acknowledgement key a refusal travels under |
RealtimeRejectionEnvelope |
type | the wire shape of a refusal |
RealtimeRejectionReport |
type | what the sender is told: event, reason, message, issues |
RealtimeRejectionIssue |
type | one refused field, already flattened (path: '0.v') |
asRealtimeRejection |
function | recognise a refusal in an acknowledgement value, validating it |
RealtimeContract |
type | shared server-to-client and client-to-server event registries |
RealtimeEventRegistry |
type | string-keyed registry of event definitions |
RealtimeEventDefinition |
type | one tuple-shaped event and optional acknowledgement schema |
RealtimeEventArguments |
type | tuple inferred from an event definition |
RealtimeEmitArguments |
type | emit arguments including an inferred acknowledgement callback |
RealtimeEventHandler |
type | handler inferred from an event definition |
InferRealtimeEventMap |
type | inferred Socket.IO-compatible event map |
RealtimeRejectDirection / RealtimeRejectPhase / RealtimeRejectReason / RealtimeRejectFault |
types | canonical inferred rejection direction, validation phase, reason and fault classification |
RealtimeRejectedEvent |
type | structured rejected event with event, direction, phase, reason and fault |
RealtimeRejectedEventHook |
type | sync/async observer for structured realtime rejections |
ValidatedRealtimeSocket |
type | runtime-validating on/emit surface inferred from registries; emit returns “accepted by the transport” (false only for a client-side disconnected drop) |
RetainedTopics |
type | the createRetainedTopics handle |
ParseSSEOptions |
type | options for parseSSE |
ParseNDJSONOptions |
type | options for parseNDJSON |
BackoffPolicySchema / BackoffPolicy |
schema / type | minDelayMs, maxDelayMs and a 0–1 jitter fraction; a ceiling below the floor is refused |
Backoff |
type | the backoff handle returned by createBackoff |
ResumableIteratorConfig |
type | caller-owned open / advance / isTerminal, retry policy, abort signal and onAttempt observer |
ResumableAttempt |
type | attempt number, the delay about to be waited and the error that caused it |
Trace (client)
Browser-safe W3C trace helpers — the same functions as on
stitchkit/observability, re-exported so a client
can emit / propagate a traceparent (see HttpClientConfig.trace).
| Export | Kind | Summary |
|---|---|---|
createTraceContext |
function | a fresh root trace |
formatTraceparent |
function | render a traceparent header value |
parseTraceparent |
function | parse a traceparent header |
childSpan |
function | a child span of a parent trace |
TraceContext |
type | { traceId, spanId, parentSpanId?, tracestate?, baggage? } |
Session lifetime and credential coordination
createSessionScope (stitchkit) returns the generic SessionScope: replace(context)
creates a new login lifetime (including same-account relogin), capture() returns
its SessionOperation<T>, clear() invalidates it, stop() permanently closes
the host, and owns(operation) answers whether an operation is this scope’s current
one — current() alone cannot tell an operation of another scope. Operations expose id, generation, context, signal, current() and
assertCurrent(). run(callback) checks both success and failure across an await;
deliver(callback) admits a synchronous final send/state change or returns false.
bindFetch(fetch, headers?) guards every attempt and scopes its abort signal. Wrap
the complete client call in run too: headers are not the response body boundary.
Expired work throws SessionExpiredError, not a refresh instruction; when the work
itself failed, that failure is its cause.
createSessionCredentials accepts SessionCredentialsConfig:
scope, refresh(credentials, signal), storage.write(session, credentials),
storage.clear(), maxPendingWrites (128), refreshTimeoutMs (30000, at most one
hour) and storageTimeoutMs (30000, at most one hour): a storage call past it
rejects and frees the queue, so logout() still clears; when the late call settles,
storage is written again from memory, or cleared when nobody is logged in. SessionCredentials provides login, logout, read(operation) and
refresh(operation). Concurrent refresh calls in one generation share the same
promise. Logout invalidates memory before its returned persistence promise settles.
Storage errors and queue-capacity refusals reject; callers must handle them. All
writes must pass through the same instance. There is no cross-process/tab lock,
provider error classifier or automatic retry of arbitrary application callbacks.
stitchkit/contract
The contract layer alone — browser-and-server safe. All of this is also exported
from the root stitchkit.
Contract
| Export | Kind | Summary |
|---|---|---|
defineContract |
function | declare a contract — guide |
createContractFactory |
function | a defineContract whose scope — on the contract and on any endpoint override — is required and held to your union, retaining each concrete literal — guide |
ContractFactoryConfig |
type | optional scoped-factory policy, including explicit tool exposure |
ContractFactoryToolExposure |
type | 'explicit' — omitted endpoint exposure materializes as HTTP-only |
ExplicitScopedDefineContract |
type | scoped factory authoring with explicit tool opt-in |
ExplicitToolExposureEndpoints |
type | endpoint map after missing exposure is materialized as ['HTTP'] |
FactoryScopedEndpoint |
type | an endpoint authored through the factory — its own scope override is held to the same union |
ScopedContractDef |
type | a factory-defined contract whose meta.scope is the required concrete literal |
ScopedDefineContract |
type | the defineContract createContractFactory returns — endpoint scope overrides join the union |
ALL_TRANSPORTS |
constant | ['HTTP', 'MCP', 'AGENT', 'CLI'] |
TOOL_TRANSPORTS / ToolTransport |
constant / type | ['MCP', 'AGENT', 'CLI'] — the transports a model or tool client reads; the one name for a tool surface everywhere (runtime-tool transports, invoker, collector, connections) |
ContractDef |
type | a defined contract |
PathParams |
type | infer named :segments and a terminal *wildcard from a path literal as string params |
ContractMeta |
type | a contract’s prefix + optional scope and meta (a default every endpoint shallow-merges over) |
EndpointDef |
type | a single endpoint definition; output declares JSON response presence (null is data, undefined is invalid); safelistedBody: true admits the JSON body as text/plain from an allow-listed Origin — guide |
withToolView |
function | declare an endpoint’s call and answer on the tool surface (MCP, AGENT, CLI): input defaults, and optionally a view output and a project, typed against the endpoint’s own schemas; HTTP keeps the full answer — guide |
EndpointToolOptions |
type | an endpoint’s tool group — name, view, ui, annotations, mcp: what the tool surfaces read that HTTP does not |
EndpointToolView |
type | the stored shape of a tool view (MethodDef.toolView) |
DeclaredToolView |
type | a tool view as withToolView produces it — the only form tool.view accepts |
WithToolView |
type | the endpoint withToolView returns: its own tool options plus the declared view in tool.view — name it when a helper returns such an endpoint |
DefaultsOnlyToolView / ProjectedToolView / ReshapedToolView / SlicedToolView |
type | the four forms withToolView accepts: input defaults alone with the full answer, own schema + project, project inside the full schema, a slice by output |
ToolViewCall |
type | what project is told besides the full result: the parsed input and the source |
ToolViewSliceMismatch |
type | the compile-time refusal of a slice whose schema does not accept the full output |
ToolViewNeedsToolTransport |
type | the compile-time refusal of a view on an expose: ['HTTP'] endpoint |
EndpointStreamDescriptor |
type | HTTP-only schema-derived stream declaration: item schema, envelope/item framing, stream-end/terminal completion, NDJSON/SSE encoding and frame/lifetime/heartbeat/idle bounds — guide |
HeadEndpointDef |
type | explicit HTTP-only, bodyless HEAD endpoint definition |
EndpointResponseMeta |
type | static success metadata declared by an HTTP-only typed-data endpoint |
ResponseMetadata |
type | per-request outbound collector exposed as ctx.response only for a responseMeta endpoint |
HttpSuccessStatus |
type | supported declared 2xx success statuses |
BodyHttpSuccessStatus |
type | supported 2xx statuses excluding bodyless 204/205 |
HttpMethod |
type | GET | HEAD | POST | PUT | PATCH | DELETE |
Transport |
type | HTTP | MCP | AGENT | CLI |
TransportSource |
type | http | mcp | agent | cli — the value of ctx.source |
RuntimeContext |
type | the loose context seen by transport and hooks, including optional typed mcp metadata |
HandlerContext |
type | the typed context seen by a handler, including optional typed mcp metadata |
McpCallContext |
type | validated metadata for the active managed MCP call (era, method, tool, client and multi-round fields) |
McpClientInfo |
type | self-reported MCP host name/version; attribution only, never application identity |
McpInputRequiredCall |
type | the parsed params / input an elicitation resolver chooses its questions from |
McpInputRequiredResolver |
type | mcp.inputRequired as a function of the parsed arguments — returns the rounds for this call, or none |
McpProgressUpdate |
type | one mid-call progress update — message, and progress/total when the operation knows a scale |
McpReportProgress |
type | ctx.reportProgress — sends one update to the host that asked for progress; a no-op when none did, and never throws |
McpRoundOutcome |
type | managed multi-round attempt outcome |
EndpointHandlerContext |
type | one endpoint handler’s fully inferred params, input, files and runtime context |
EndpointFn |
type | the call signature of one client method |
TypedClient |
type | the full typed client for a contract |
TypedHttpClient |
type | the typed client, HTTP endpoints only (= ScopedHttpClient<C, unknown>) |
ScopedHttpClient |
type | a client whose stripPrefixKeys become required args (guide) |
ScopedEndpointFn |
type | one method’s signature with the consumed keys folded in |
TypedUrlBuilder |
type | one contract’s HTTP endpoints as synchronous, method-aware URL functions |
ScopedUrlBuilder |
type | a URL builder whose scoped-prefix keys are required method arguments |
ScopedUrlFn |
type | one URL method’s signature with scoped-prefix keys folded in |
MultipartFile |
type | a multipart file field — Blob | FileDescriptor |
FileDescriptor |
type | a React Native / Expo file — { uri, name, type } |
MultipartDescriptor |
type | file fields, cardinality, delivery and request/text limits |
MultipartFilePolicy |
type | required/multiple, per-file bytes/count and declared MIME policy |
MultipartBufferedFiles |
type | File map inferred from a multipart descriptor |
EndpointToolAnnotations |
type | MCP behavioural hints on an endpoint (readOnlyHint / destructiveHint / title) |
EndpointUiMeta |
type | MCP Apps widget metadata on an endpoint |
EndpointMcpInputRequired |
type | typed MCP multi-round input request (key, message and Zod object schema) |
EndpointMcpPolicy |
type | MCP-only endpoint policy containing inputRequired |
Errors
| ErrorVocabularyCode / ErrorVocabularyMapping / VocabularyCodeMap | type | application-code union, partial/exhaustive framework mapping input and resolved wire map returned by defineErrors |
| Export | Kind | Summary |
|---|---|---|
AppError |
class | the framework error — code / status / details / hint |
ErrorEnvelope |
type | the JSON shape of an error response, preserving optional declared boolean error.retryable without changing HTTP retry policy |
notFound |
function | throw 404 NOT_FOUND — guide |
badRequest |
function | throw 400 BAD_REQUEST |
unauthorized |
function | throw 401 UNAUTHORIZED |
forbidden |
function | throw 403 FORBIDDEN |
conflict |
function | throw 409 CONFLICT |
rateLimited |
function | throw 429 RATE_LIMITED |
appError |
function | throw an AppError for any code |
defineErrors |
function | declare immutable domain error definitions → typed AppError constructors, codes and schemas — guide |
DefinedErrors |
type | the { errors, codes, definitions, isCode, codeMap } handle defineErrors returns |
DefinedAppError |
type | literal-code error instance with schema-refined details |
ErrorDefinition |
type | { status, message?, details? } definition for one domain code |
ErrorDefinitions |
type | string-keyed domain error definition registry |
ErrorDetailsSchema |
type | required or optional Zod object accepted for structured details |
ErrorDetailsOutput |
type | parsed details inferred from one definition |
ErrorFactoryArguments |
type | options tuple with forbidden/required/optional details inferred per code |
ErrorFactory |
type | one typed AppError constructor |
ErrorFactories |
type | mapped constructor registry derived from all definitions |
FrozenErrorDefinitions |
type | read-only definition registry returned to consumers |
STITCH_ERROR_STATUS |
const | code → HTTP status map for stitchkit’s own error codes — guide |
StitchErrorCode |
type | a code stitchkit itself emits (keyof STITCH_ERROR_STATUS) |
isStitchErrorCode |
function | type guard — is a code one of stitchkit’s own? |
isRetryableStatus |
function | whether a status class means “the same call could work later” — 408, 429, 502, 503, 504, and deliberately not every 5xx |
Pagination
| Export | Kind | Summary |
|---|---|---|
paginatedSchema |
function | the { items, nextCursor } Zod schema — guide |
Paginated |
type | the cursor-pagination envelope |
encodeCursor |
function | encode a keyset value into an opaque nextCursor string (base64url, UTF-8-safe) |
decodeCursor |
function | decode + Zod-validate a cursor back to its value (null if missing/invalid) |
stitchkit/live
Evolving. Browser-and-server-safe declarations for the things that change while a caller is
watching: announcements, and reads the server re-runs. It owns no transport — the wire is the
realtime contract from stitchkit, and the server halves live in stitchkit/application.
→ ADR 0150,
ADR 0153.
| Export | Kind | Summary |
|---|---|---|
defineEvents |
function | declare topics: a wire name, one payload schema and how the topic is delivered to in-process listeners |
toRealtimeContract |
function | project a declaration onto RealtimeContract, so the existing validated socket carries it |
EventDeliveryMode |
type | emit / serial / decision — how a topic reaches its in-process listeners |
PolicyDecision / UndecidedOutcome |
types | one voter’s allow / deny / defer, and what a run settles on when every voter defers — the same two types the decision pipeline in stitchkit/application uses, because a listener voting on an event and a policy voting on a request are answering the same question |
EventTopicDeclaration / EventTopicRegistry / EventsConfig / EventsDeclaration |
types | one topic’s schema, mode, whenAllDefer and listenerTimeoutMs, and the declaration they compose into |
EventPayloads / EventTopicsOfMode / WireTopic |
types | payload map keyed by wire topic, the topics of one mode, and the prefix.name a topic is addressed by |
createWatchClient |
function | contract-shaped watch client: watch.action(args) returns a ref-counted handle sharing one subscription |
WatchHandle / WatchListeners / WatchClientConfig / WatchTransport / TypedWatchClient |
types | subscribe/close, the value and state listeners, hold window and open deadline, and the bound realtime client it rides |
watchTransport / RealtimeClientLike / WatchInboundEvents |
function / types | hands a bound realtime client to a watch client — two generic signatures TypeScript will not relate, converted once here |
watchContract |
const | the four-event realtime contract a watched read travels on |
WATCH_OPEN / WATCH_CLOSE / WATCH_VALUE / WATCH_STATE |
const | the event names of that contract |
WatchKey / WatchKeySchema / watchKeyString |
type / schema / function | (service, action, arguments digest) — the identity both ends compute the same way |
WatchValueFrame / WatchValueSchema / WatchStateFrame / WatchStateSchema |
types | one answer — full, delta or unchanged, with its monotonic revision and fingerprint — and a phase from LiveStatePhase with the read’s own code and message |
WatchHave / WatchHaveSchema |
type / schema | what a reconnecting subscriber already holds, offered on open: a revision and the fingerprint that proves it |
WatchDelta / WatchDeltaSchema / WatchArrayOp / WatchArrayOpSchema |
types / schemas | a structural difference over parsed JSON — objects by changed and dropped key, arrays by runs copied from the previous value |
watchDiff / applyWatchDelta / watchDeltaWins |
functions | build a difference (undefined when equal), rebuild the value from one (throws rather than inventing), and whether it is actually smaller than the value |
Session-scoped watch lifetime
WatchClientConfig.session captures a SessionOperation; maxKeys (1024) and
maxListenersPerKey (128) bound retained subscriptions; a handle takes its key on
subscribe, which is where capacity refuses. Its lifetime nonce travels
in optional WatchKey.instance, preventing old-session frames from matching a new
client on the same socket. This is routing identity, never authorization.
stitchkit/primitives
Browser-and-server-safe declarations for facts an application wants to define once. See the primitives guide. Storage, transactions, data-adapter predicates, schedules, transports and file generation remain application-owned.
| Export | Kind | Summary |
|---|---|---|
defineLifecycle |
function | immutable finite-state transition declaration, role/payload validation, available-action projection and transition event |
LifecycleState / LifecycleTransitionDefinition / LifecycleDefinition |
types | branded state value and the declaration inferred from application strings |
LifecycleTransitionInput / LifecycleTransitionResult / LifecycleTransitionSuccess / LifecycleTransitionFailure |
types | typed execution input and distinct transition/state, role and payload outcomes |
LifecycleTransitionEventSchema / LifecycleTransitionEvent |
schema / type | canonical event returned for application-atomic persistence |
defineOwnerScope |
function | resolve one owner from identity or require the explicit acrossAllOwners capability |
OwnerScope / OwnerScopeDefinition / OwnerScopeResolution |
types | branded adapter input and its resolved/refused outcomes |
definePermissionMatrix |
function | exhaustive role × operation decisions with server check and client capability projection |
PermissionGrantMatrix / PermissionCheckResult |
types | compile-time complete matrix and unknown/allowed/denied runtime result |
defineMoney / createMoneySchema |
functions | fixed-currency JSON-safe minor-unit value and Zod schema |
addMoney / subtractMoney / multiplyMoney / shareMoney / splitMoney |
functions | exact same-currency arithmetic with explicit indivisible remainder |
Money / MoneyShare / MoneySplit |
types | currency-literal value and remainder-bearing operation results |
defineUnitSystem / createQuantitySchema / addQuantity |
functions | exact decimal quantities and caller-declared finite conversions |
Quantity / UnitConversion / QuantityProjection |
types | unit-literal value, rational conversion and recorded/derived provenance |
QuantityProjectionSchema |
schema | transport-safe recorded/derived quantity union |
defineDeadlinePolicy |
function | elapsed- or calendar-day projection with explicit timezone, threshold, current time and caller category keys |
DeadlineResultSchema / DeadlineResult |
schema / type | due instant, remaining/overdue days and projected category |
audit |
constant | constructors for explicit record(changeSchema) or omit(reason) endpoint metadata |
assertAuditDeclared |
function | refuse a contract operation with no audit decision |
createAuditRecord |
function | validate one declared change and return the canonical event value |
AuditPolicy / AuditRecordPolicy / AuditOmitPolicy / CreateAuditRecordInput |
types | audit declaration and record input contracts |
AuditRecordSchema / AuditRecord |
schema / type | domain-event-shaped audit record |
createDomainEventSchema |
function | wrap a typed payload in the canonical event envelope |
DomainEventSchema / DomainEvent |
schema / type | generic event with stable id, time, subject and optional actor |
DomainEventActorSchema / DomainEventActor |
schema / type | structured actor identity and application role |
DomainEventSubjectSchema / DomainEventSubject |
schema / type | generic subject type/id pair |
defineDomainEventDelivery |
function | plan routes and dispatch only application-outbox claims by committed event id |
DomainEventDestinationSchema / DomainEventDestination |
schema / type | transport-neutral destination identity |
DomainEventDeliveryOutcomeSchema / DomainEventDeliveryOutcome |
schema / type | delivered, retryable, terminal or unknown transport result |
DomainEventDeliveryClaimSchema / DomainEventDeliveryClaim |
schema / type | application-owned atomic outbox claim |
DomainEventOutbox / DomainEventRoute / DomainEventTransport |
types | host capabilities composed by process-local delivery |
DomainEventDeliveryPlan / DomainEventDispatchResult |
types | transaction input and bounded dispatch summary |
defineExportOperation / createExportResultSchema |
functions | one typed contract operation returning a ready managed file or pending operation id |
scanMoneyNumberRisks / scanOwnerFilterRisks |
functions | source-text migration diagnostics with caller-owned identifiers |
SourceText / SourceRisk |
types | migration scanner input and exact path/line evidence |
| Export | Kind | Purpose |
|---|---|---|
canonicalJson |
function | bounded plain JSON, UTF-16 key sort, optional object members omitted |
CanonicalJsonOptions |
type | inferred depth/node/UTF-8 bytes limits |
CanonicalJsonError / CanonicalJsonRefusal |
class / type | the TypeError of a refusal and its reason: cycle, negative-zero, depth, nodes, bytes or not-json |
stitchkit/server
Server-only. Builds and runs the HTTP server, and carries the server primitives.
Also re-exports the error helpers from stitchkit/contract.
Server & handlers
| Export | Kind | Summary |
|---|---|---|
createServer |
function | build the router and start Bun.serve — guide |
createHandler |
function | the router as a bare (req) => Response — guide |
implement |
function | bind a contract to typed handlers — guide |
createImplement |
function | fix the handler context type once |
createScopedImplement |
function | fix one scope→context map, then type every handler by its endpoint’s effective scope; .declare(contract)(handlers) types without binding for the registry path, .stream(scope, …) covers streaming multipart — guide |
ScopedHandlers |
type | handler map typed per endpoint by its effective scope |
ScopeContexts |
type | scope → extra context fields map accepted by createScopedImplement |
EffectiveScope |
type | an endpoint’s own scope, else its contract’s group scope |
createScopedImplementRegistry |
function | the registry form of createScopedImplement — one contract registry, handlers still typed per endpoint scope |
ScopedRegistryHandlers |
type | scoped handler registry inferred from a contract registry |
ScopedImplementationRegistry |
type | contract registry whose every group scope is a key of the scope map |
StreamScope |
type | the scope createScopedImplement(...).stream accepts for one endpoint |
ExactScopedRegistryHandlers |
type | fail-first scoped registry shape that rejects extra registry and endpoint keys |
implementRegistry |
function | bind one exact contract registry to one exact backend handler registry |
createImplementRegistry |
function | context-typed factory for implementRegistry |
ImplementationRegistry |
type | flat literal registry of concrete contracts accepted by implementRegistry |
ImplementOptions |
type | { onMissingHandler } — how a binding treats a contract endpoint with no handler |
MissingHandlerPolicy |
type | 'throw' (default) or 'stub', the dev-stand policy that mounts a 501 instead of refusing to start |
KeyedServices |
type | registry result: the mount-ordered ServiceDef[] carrying the same services under .byKey |
RegistryHandlers |
type | exact backend handler registry inferred from a contract registry |
ExactRegistryHandlers |
type | fail-first handler shape that rejects extra registry and endpoint keys |
staticRoute |
function | a raw route that serves a directory |
serveFile |
function | serve a file with Range / 304 / HEAD — guide |
parseByteRange |
function | parse a single Range header → range / unsatisfiable / null |
isWithinDir |
function | path containment — (root, resolvedTarget) => boolean; call it before serveFile on any URL-derived path |
weakETag |
function | a weak ETag from size + mtime |
ServeFileOptions |
type | options for serveFile |
ByteRange |
type | an inclusive { start, end } byte range |
respondJson |
function | a raw route’s JSON response (204 for null/undefined) |
errorResponse |
function | any thrown value → the framework error envelope + x-request-id |
normalizeError |
function | any thrown value → an AppError (ZodError → VALIDATION_ERROR 400 with structured details.issues, else generic 500) — the framework’s canonical classification, for a bespoke onError |
NormalizeErrorOptions |
type | logUnexpected defaults to logging the raw server-side cause; tool adapters disable process dumps while their existing observers retain that cause |
errorCode |
function | the stable error code for a thrown value (side-effect-free — for log attribution) |
formatZodError |
function | a ZodError → a readable, field-summarised string |
zodIssues |
function | a ZodError → structured { path, code, message }[] — the machine-readable sibling of formatZodError |
ZodIssueSummary |
type | one structured validation issue ({ path, code, message }) |
parseBody |
function | parse + Zod-validate a JSON body → data or null (no throw); reads at most options.maxBytes (1 MiB by default) and is null for a larger body |
HandlerConfig |
type | config for createHandler, including optional maxJsonBodyBytes; bound to BunServer on this entrypoint |
BunServerConfig |
type | config for createServer (Bun); unix listens on a unix domain socket (mutually exclusive with port/hostname) — details |
defineRequestIngress / RequestIngress / RequestIngressSource |
function / type | a typed key the code that builds a Request attaches a value to (attach(request, value)) and an endpoint, authorize, beforeHandle or onError reads from its ctx (from(ctx)); a header, clone() and new Request(request) carry nothing, a second attach is refused, and ctx.req is the very request the handler received — guide |
ProxyOriginConfig |
type | explicit real-peer trust for Bun createServer({ proxyOrigin }); strict external-scheme normalization before composition — details |
UnixListenConfig |
type | unix listener — a socket path, or { path, mode } to tighten the file mode after listen |
BunServerHandle |
type | managed Bun handle (url, port, runtime, status, shutdown) |
ManagedServerHandle |
type | shared lifecycle shape generic over the runtime escape hatch |
ShutdownOptionsSchema / ShutdownOptions |
schema / type | HTTP/application grace, a separate WebSocket close-handshake bound, bounded forced-completion timeout, retry hint and optional external abort signal |
ShutdownStatusSchema / ShutdownStatus |
schema / type | live state and request/WebSocket counters; owned streams remain pending through source cleanup |
ShutdownResultSchema / ShutdownResult |
schema / type | clean/forced result with final counters, outer-force snapshots and forcedWebSockets including bounded realtime terminations |
ShutdownStateSchema / ShutdownState |
schema / type | managed lifecycle state machine |
ServiceDef |
type | the result of implement |
MethodDef |
type | one resolved endpoint inside a service |
OperationIdentity |
type | path-free service/action/scope/method identity shared by contract and native tool operations |
Handlers |
type | the typed handler map implement expects |
LifecycleHooks |
type | onRequest / pre-body authorize / beforeHandle / afterHandle / onError |
composeLifecycleHooks |
function | compose HTTP lifecycle phases in declaration order with short-circuit/fallthrough semantics |
AuthorizationContext |
type | HTTP pre-body context with validated params, input: undefined and no files |
RouteGroup |
type | a prefixed group of services with its own hooks; matched errors try group onError → global onError → standard envelope, keeping the original error on fallback — precedence |
RawRoute |
type | a non-contract Request → Response route with a concrete BunServer context and optional stable serviceName / action observability identity |
RawRouteContext |
type | the Bun-bound routing context a raw handler receives |
BunServer |
type | the Bun.serve instance type |
ServerPassthrough |
type | extra Bun.serve options |
StitchLogger |
type | the custom-logger interface |
LoggingConfig |
type | the logging object — logger / format / skip / enrich |
LogFormat |
type | 'pretty' or 'json' — what the built-in formatter writes |
LogOutcome |
type | how a request finished, as enrich sees it |
FetchHandler |
type | what createHandler returns, bound to BunServer here |
FetchComposition |
type | the Bun-bound wrapFetch seam |
Auth
| Export | Kind | Summary |
|---|---|---|
createAuthHook |
function | one scope gate for HTTP authorize and tool beforeHandle — guide |
composeAuthHooks |
function | route multiple canonical auth domains by owned scope and atomically commit their typed contributions |
createErrorHook |
function | an async-capable, endpoint-aware onError hook from a defineErrors vocabulary or a code map, plus an envelope renderer — guide |
ErrorHookBase / ErrorHookMapping |
type | common hook fields and the vocabulary-or-map branch accepted by createErrorHook |
ErrorHookConfig |
type | async observer/renderer config with partial codeMap and optional typed unmappedCode fallback |
ResolvedError |
type | the normalised error handed to createErrorHook’s render |
createBearerResolver |
function | a bearer-token identity resolver |
signJwt |
function | sign an HS256 JWT |
VerifyJwtOptions |
type | options for verifyJwt |
verifyJwt |
function | verify an HS256 JWT |
extractToken |
function | read a bearer token from header or cookie |
deriveCodeChallenge |
function | PKCE — derive the code_challenge from a verifier |
verifyPkce |
function | PKCE — verify a verifier against a stored challenge |
AuthHook |
type | the hook createAuthHook returns |
AuthHookConfig |
type | config for createAuthHook |
AuthRule |
type | 'public' | 'authenticated' | predicate |
AuthRuleContribution |
type | plain context fields a sync/async rule may contribute after authorizing |
ScopedAuthRule |
type | a rule plus its typed context contribution — { rule, inject? } |
AuthRules |
type | the rules map: bare rules or scoped rules |
RuleScopes |
type | scope→context map derived from a rules object; 'public' fields become optional |
ScopedAuthHook |
type | an auth hook carrying its derived scope map at the type level |
AuthScopes |
type | recover the derived map — createScopedImplement<AuthScopes<typeof hook>>() |
ComposeAuthHooksConfig |
type | ordered canonical hooks plus the optional explicit composite default scope |
ComposedAuthScopes |
type | scope→context map derived from every owner in a composed auth hook |
BearerResolverConfig |
type | config for createBearerResolver |
JwtPayload |
type | a decoded JWT payload |
SignJwtOptions |
type | options for signJwt (expiry, claims) |
PkceMethod |
type | the PKCE challenge method — 'S256' | 'plain' |
Cookies & CORS
| Export | Kind | Summary |
|---|---|---|
defineCookie |
function | a typed cookie get / getAll / set / clear handle; duplicates names what get answers when two cookies share the name — guide |
parseCookies |
function | parse a Cookie header to a record (the last of two same-named cookies wins) |
parseCookieHeader |
function | parse a Cookie header to [name, value] pairs in header order, duplicates kept |
serializeCookie |
function | build a Set-Cookie value |
corsHeaders |
function | compute CORS response headers |
corsPreflightResponse |
function | build a preflight Response |
DEFAULT_CORS_ALLOW_HEADERS |
const | the default Access-Control-Allow-Headers (incl. traceparent) — extend it when overriding cors.headers |
DEFAULT_CORS_EXPOSE_HEADERS |
const | the default Access-Control-Expose-Headers (incl. Content-Disposition, ETag, Content-Range, X-Build-Id) — extend it when overriding cors.exposeHeaders, or a cross-origin page loses the build id |
CookieDef |
type | the defineCookie handle |
CookieOptions |
type | cookie attributes, plus the duplicates read policy |
CookieDuplicatesPolicy |
type | 'last' (default) / 'first' / 'reject' — reject yields undefined for two different values and the value when they agree |
CorsConfig |
type | CORS policy |
Realtime (server)
| bindSocketRegistry | function | room membership and consistent replay over an already-authenticated realtime server |
| AuthorizedSocketRoom / SocketRegistry / SocketRegistryConnection / SocketRegistryOptions / SocketRegistryServer / SocketRegistrySnapshot / SocketReplayFrame | type | authorized room token, structural server boundary, replay frames and immutable registry state |
| Export | Kind | Summary |
|---|---|---|
createSocketIOServer |
function | the typed Socket.IO server — guide |
bindRealtimeServer |
function | inferred, runtime-validated connection and broadcast boundary |
RealtimeServer |
type | validated broadcast and connection API inferred from a realtime contract |
RealtimeServerConnection |
type | one validated connection with raw socket access for auth and rooms |
RealtimeServerHandle |
type | minimal Socket.IO server handle accepted by bindRealtimeServer; carries the handshake identity type through to connection.raw.data |
SocketIORequestPolicy |
type | runtime-neutral async-capable Web Request handshake admission policy |
SocketIOServerConfig |
type | config for createSocketIOServer; handshake is the typed identity gate — guide |
SocketIOPeerLoaders |
type | peers: { server, bunEngine } — literal dynamic imports written in YOUR source, so a bundler puts the optional peers inside a self-contained artifact. Omit for the lazy default |
SocketIOHandshakeConfig |
type | the handshake gate — Zod schema over handshake.auth plus optional async verify; the result lands typed in socket.data |
SocketIOServerHandle |
type | typed Socket.IO server plus Bun mount fields and idempotent lifecycle |
SocketIOServerLifecycle |
type | non-generic Bun mount/shutdown portion accepted by createServer |
composeWebSocketHandlers |
function | compose one Bun websocket from N lanes — a raw binary lane beside Socket.IO (guide) |
webSocketLane |
function | a typed, cast-free lane for composeWebSocketHandlers |
socketIoLane |
function | the Socket.IO catch-all lane for composeWebSocketHandlers |
ComposedLane |
type | a lane bridged to the loose data type |
WebSocketLane |
type | a typed lane ({ match, handlers }) |
WebSocketComposeConfig |
type | server-wide tuning for the composed handler |
Primitives
| createFileStateStore | function | cross-process locked atomic JSON state updates over one Zod schema |
| FileStateStoreCorruption / FileStateStoreOptions | type | explicit corrupt-state report/policy, lock timing and the state read cap maxBytes; a transition whose resulting state encodes to the bytes it started from writes nothing |
| Export | Kind | Summary |
|---|---|---|
streamSSE |
function | an async generator → SSE Response — guide |
streamingRoute |
function | a long-lived subscription route: idle timeout, heartbeat, opening flush, cancellation — guide |
ndjsonRoute |
function | streamingRoute framed as NDJSON |
sseRoute |
function | streamingRoute framed as SSE |
DEFAULT_STREAM_HEARTBEAT_MS |
const | 5000 — deliberately well under Bun’s ten-second idle threshold |
MultipartLifecycle |
type | request-scoped rollback ownership for accepted streamed handles |
MultipartResult |
type | what parseMultipart returns |
parseMultipart |
function | parse a typed buffered/streaming multipart descriptor — guide |
defineMultipartStream |
function | bind typed streaming file receivers and a final endpoint handler |
createMultipartStream |
function | fix one handler context type for streaming multipart endpoints |
MultipartStreamConfig |
type | receivers plus the context-typed handler accepted by the streaming builders |
MultipartFileMetadata |
type | field, filename, declared media type and optional declared size |
MultipartReceiver |
type | consumer-owned Web-stream storage receiver |
MultipartReceiverResult |
type | receiver value plus rollback cleanup |
StreamingMultipartImplementation |
type | receiver registry and handler shape inferred by defineMultipartStream |
bindReleaseRefreshSignal / ReleaseRefreshSignalOptions / ReleaseRefreshSignal |
function / type | a deploy signal (SIGUSR2, the one user-defined signal the process vocabulary has) refreshes a stitchkit/release marker, whose subscribers tell every socket; never throws at the signal — guide |
bindProcessSignals |
function | bind SIGINT / SIGTERM to one managed shutdown() — one chain, force on a later signal, default disposition on the one after — guide |
ProcessSignalsOptions |
type | config for bindProcessSignals |
ProcessSignalsBinding |
type | the { promise, close } handle bindProcessSignals returns |
ProcessSignalsErrorPhase |
type | 'prepare' | 'shutdown' | 'complete' — which phase an onError report came from |
SignalSource |
type | injectable signal source — process by default |
ProcessSignalName |
type | signal names the binding accepts (owned, so the published types need no @types/node) |
ShutdownTarget |
type | the shutdown-only slice a binding needs — an interface, so a composite target can drain several domains under one signal machine |
createRateLimiter |
function | token-bucket rate limiting — guide |
createCache |
function | an in-memory TTL cache |
CacheOptions |
type | bounded-cache options, including the maximum retained entry count |
cacheHeaders |
function | build a Cache-Control header |
EventBusOptions |
type | options for createEventBus |
EventHandler |
type | one event-bus subscriber |
DefaultEventMap |
type | the default event map — Record<string, unknown> |
createEventBus |
function | typed in-process pub/sub — guide |
generateTraceId |
function | a fresh trace id |
resolveTraceId |
function | the default per-request trace-id resolver |
extractIp |
function | the caller IP from a request |
isPublicIp |
function | whether an address belongs to the public internet; anything unparseable is not |
resolveSocketIp |
function | the caller IP for a Socket.IO handshake (proxy-aware) |
getClientInfo |
function | caller IP + user-agent |
EventBus |
type | the createEventBus handle |
RateLimitConfig |
type | config for createRateLimiter |
ClientIpOptions |
type | trusted-proxy config for extractIp / resolveSocketIp |
StreamingRouteOptions |
type | options for streamingRoute / ndjsonRoute / sseRoute |
StreamingSourceContext |
type | what a streaming source is given, including the cancellation signal |
StreamingFormat |
type | 'ndjson' | 'sse' |
createUnixClientTransport |
function | owned Fetch-compatible Unix-socket transport on Bun and Node; every redirect stays on the socket — guide |
UnixClientTransportConfig |
type | absolute socket path plus request/header/connection/redirect bounds and an explicit bounded-or-streaming response policy |
UnixClientTransport |
type | { fetch, closed, close() }; close() settles owned active work |
UnixResponseBodyMode |
type | bounded | streaming; bounded is the 16 MiB cumulative default, streaming keeps pull-driven buffering without a lifetime total |
UnixClientTransportError |
class | stable transport failure with code and dispatch certainty in delivery |
UnixClientTransportErrorCode |
type | finite Unix transport failure-code union |
UnixClientDeliveryState |
type | not-dispatched | possibly-dispatched | response-received; input to application retry policy, never an implicit retry |
OpenAPI
| Export | Kind | Summary |
|---|---|---|
generateOpenApiDocument |
function | an OpenAPI 3.1 document from contract services — ADR 0018 |
openApiRoute |
function | a RawRoute that serves the document as JSON |
OpenApiConfig |
type | config for generateOpenApiDocument (incl. includeMethod — curate a public subset) — guide |
OpenApiDocument |
type | the generated document |
OpenApiInfo |
type | the spec info block |
OpenApiServer |
type | a spec servers entry |
Trust fence
Refuses a request whose Host is not a declared authority, at both admission points — the socket
lane never reaches the hooks on either runtime.
→ ADR 0151.
| Export | Kind | Summary |
|---|---|---|
createTrustFence |
function | hooks for the HTTP lane and allowRequest for the Socket.IO lane; a bare 403 that never says which rule refused |
isLoopbackAddress |
function | whether an address is this machine — for the auth rule a privileged operation belongs in, not for the fence |
TrustFence / TrustFenceConfig / TrustRefusal / TrustRefusalReason / TrustLane |
types | the two admission points, the declared authorities, and why and where a request was refused |
RouteGroupHooks |
type | a route group’s hooks — LifecycleHooks without onRequest, which runs before the group is known |
stitchkit/application
StartFact also carries previousDrainUpperBoundMs: the time from a predecessor’s recorded admission stop to this start when its exit is interrupted, otherwise null. This is an upper bound, and does not identify a kill signal or supervisor deadline.
Server-only process-local application composition. See the application kernel guide and architecture. Complete consumer cutovers are covered by the executable migration recipes.
Kernel and resources
| Export | Kind | Summary |
|---|---|---|
createApplication |
function | compose a validated resource DAG into one startup, readiness, admission and shutdown state machine |
StateStore / StateStoreUpdate |
type | async atomic read/update boundary shared by durable application state machines |
createProcessLifecycleLedger / ProcessLifecycleLedger / ProcessLifecycleLedgerConfig |
function / type | durable bounded run history and typed fact subscription |
LifecycleRunSchema / LifecycleRun / LifecycleStateSchema / LifecycleState / LifecycleTerminationSchema / LifecycleTermination |
schema / type | versioned process-run state — open (active, draining with unavailableAt) and ended (clean, forced, startup-failed, hot-reload, abnormal) |
PreviousExitSchema / PreviousExit / StartFact / ReadyFact / DrainingFact / ShutdownFact / ProcessLifecycleFact |
schema / type | first-boot, hot-reload, clean, forced, startup-failed, handoff and abnormal lifecycle facts; processGapMs on start, downtimeMs (unavailable → ready) on ready |
transitionProcessStart / transitionProcessReady / transitionProcessDraining / transitionProcessShutdown |
function | pure idempotent runId+pid-owned transitions |
LifecycleTransition / TransitionStartInput / TransitionRunInput / TransitionShutdownInput / SameVersionOverlap / VersionChangeOverlap |
type | pure transition inputs (TransitionRunInput for ready and draining, extended with forced for shutdown), the same-build overlap policy (abnormal default / handoff), the version-change overlap policy (handoff default / abnormal) and state+fact result |
lifecycleLedgerResource / LifecycleLedgerResource / LifecycleLedgerResourceConfig |
function / type | managed-resource adapter that records start, readiness, admission stop (draining) and shutdown |
createNotificationOutbox / NotificationOutbox / NotificationOutboxConfig |
function / type | bounded at-least-once queue with durable claims, leases, retries and supersede |
NotificationOutboxItem / NotificationOutboxReceipt / NotificationOutboxState / NotificationSend / NotificationFailureClassification / DroppedNotification / EnqueueNotification |
type | versioned queue records, stable send identity and delivery decisions |
notificationOutboxStateSchema |
function | strict persisted-state schema over an application payload schema |
notificationOutboxResource / NotificationOutboxResource / NotificationOutboxResourceConfig |
function / type | thin managed-resource scheduler over an outbox handle |
createDirectoryInbox (from stitchkit/application/directory-inbox) / DirectoryInbox / DirectoryInboxConfig / DirectoryInboxDelivery / DirectoryInboxResource |
function / type | one managed directory inbox for files or durable accept({ source, key, entry }) (entry is the schema’s input, stored as given); a hard-linked file is set aside as invalid; first payload wins, bounded capacity/bytes/receipts and renewable fenced leases; delivery begins after readiness and effects remain at least once |
DirectoryInboxIdentitySchema / DirectoryInboxIdentity / DirectoryInboxAccept / DirectoryInboxAcceptResultSchema / DirectoryInboxAcceptResult |
schema / type | validated source/key, typed entry and durable accepted/duplicate result with filename; duplicates do not replace the first payload |
StateStoreUpdateContext |
type | real active protected transaction: assertHeld() refuses after ownership loss or completion; custom adapters supply this context to their transition |
DirectoryInboxStateSchema / DirectoryInboxState / DirectoryInboxRejection / DirectoryInboxRejectionReasonSchema / DirectoryInboxRejectionReason |
schema / type | the inbox’s claims, receipts and rejections (invalid, too-large, attempt-limit) |
ApplicationHandle.restart |
method | replace one resource and everything that depends on it, leaving the rest of the graph running and the process epoch unchanged |
ApplicationRestartInputSchema / ApplicationRestartInput |
schema / type | the resource to replace, by id, and optionally gracePeriodMs / forceTimeoutMs for this restart — the application’s own shutdown budget otherwise |
ApplicationRestartResultSchema / ApplicationRestartResult |
schema / type | the subtree that was actually taken down and brought back, in start order, with the outcome, the reason on anything but success, and how long it took |
ApplicationRestartOutcomeSchema / ApplicationRestartOutcome |
schema / type | restarted, failed or refused — a refusal (unknown id, shutting down, not yet ready) is not a failure and touches nothing |
ApplicationResourceFailure |
type | one resource failure with the cause its phase label cannot carry — delivered to onResourceFailure |
ApplicationResourcePhase |
type | the phase a managed resource failed in — the vocabulary of ApplicationResourceShutdown.failures |
ApplicationShutdownOptionsSchema / ApplicationShutdownOptions |
schema / type | the two shutdown budgets and an abort signal — without the HTTP-only retryAfterSeconds |
ApplicationShutdownBudgetSchema / ApplicationShutdownBudget |
schema / type | the same two budgets without a signal — ApplicationConfig.shutdown, the default for shutdown() and the only budget a failed startup’s rollback can read |
ActivityTokenBrand |
const | the brand symbol ActivityToken carries, exported so ActivityProjection is implementable |
defineManagedResource |
function | retain the exact typed resource declaration; every invoked start is rollback-eligible |
managedServerResource |
function | own a managed server’s lifecycle without copying its HTTP/WebSocket shutdown machine — a thunk is called during start, and the handle is published to dependants |
managedResourceDependencyId |
function | the id of a dependency declared either as a string or as the resource itself |
createApplicationHealthHandler |
function | build a Fetch-clean liveness or readiness response from the sanitized application snapshot |
createApplicationOperationalHandlers |
function | compose always-readable status plus the canonical readiness/liveness handlers |
ApplicationAdmissionError |
class | stable APPLICATION_NOT_ACCEPTING rejection from admission.run(...) |
ApplicationConfig / ApplicationHandle |
type | application declaration and its start/snapshot/subscription/admission/shutdown handle |
ApplicationAdmission / ApplicationOperationLease |
type | atomic process-local admission and idempotent release primitive |
ManagedResource / ManagedResourceContext / ManagedResourceStartResult |
type | resource lifecycle callbacks, shared deadlines, health reporting, separate readiness/completion promises and the value a resource publishes to its dependants |
ManagedResourceAdmission |
type | context.admission: acquire() now or null, and acquireWhenAccepting(signal) for a resource that fetches work — a poller waits instead of fetching while the application is starting or degraded; rejects on abort and once the application can no longer admit |
ManagedResourceDependency |
type | a dependency named by id or given as the resource itself — the second form is what context.use(...) can type |
ManagedResourcePublished |
type | the value type context.use(resource) returns, recovered from that resource’s own start |
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 |
ManagedServerResourceConfig |
type | the server or a sync/async factory receiving ManagedResourceContext, plus stable ID, dependencies and server shutdown policy (retryAfterSeconds, realtimeCloseTimeoutMs) |
ManagedServerResource |
type | the resource managedServerResource returns, whose start publishes the ManagedServerHandle |
ApplicationHealthHandlerOptions / ApplicationHealthHandlerOptionsSchema |
type / schema | liveness/readiness selection and sanitized Retry-After policy |
ApplicationOperationalHandlers / ApplicationOperationalHandlersOptions / ApplicationOperationalHandlersOptionsSchema |
type / schema | conventional status/readiness/liveness route surface and shared retry policy |
Bounded admission
| Export | Kind | Summary |
|---|---|---|
createBoundedAdmission |
function | process-local no-queue global/per-key concurrency and rate leases, optionally composed with application admission |
BoundedAdmissionPolicySchema / BoundedAdmissionPolicy |
schema / type | finite global budget and optional finite per-key budget with maxKeys, declared either as one flat ceiling or as a resolver — never both |
BoundedAdmissionPerKeyLimitsSchema / BoundedAdmissionPerKeyLimits |
schema / type | one key’s resolved ceiling: maxConcurrent and optional rate |
BoundedAdmissionPerKeyLimitResolver |
type | (key) => limits, resolved on a key’s first admission and cached until the key is evicted |
BoundedRateBudgetSchema / BoundedRateBudget |
schema / type | { limit, intervalMs } monotonic sliding-window budget |
BoundedAdmissionStateSchema / BoundedAdmissionState |
schema / type | accepting | draining | closed |
BoundedAdmissionRefusalReasonSchema / BoundedAdmissionRefusalReason |
schema / type | exact local/upstream refusal vocabulary |
BoundedAdmissionSnapshotSchema / BoundedAdmissionSnapshot |
schema / type | absolute active/lifetime/refusal/rate-accounting counters |
BoundedAdmission / BoundedAdmissionConfig / BoundedAdmissionClock |
type | handle, policy/upstream/clock configuration and monotonic clock seam |
BoundedAdmissionResult / BoundedAdmissionLeaseResult / BoundedAdmissionRefusedResult |
type | explicit leased-or-refused acquisition result; retry time exists only for rate bounds |
BoundedOperationLease |
type | idempotent release lease, optionally carrying its key |
BoundedOperationRunContext / BoundedOperationRunOptions |
type | underlying work signal and caller abort/timeout wait budget |
BoundedAdmissionDrainOptions / BoundedAdmissionDrainResult / BoundedAdmissionForceResult |
type | bounded drain inputs and honest remaining-work results |
BoundedAdmissionRefusalError |
class | run() refusal with reason and optional retryAfterMs |
BoundedOperationWaitError |
class | caller wait ended as cancelled or timed-out; underlying capacity remains leased until work settles |
Revision wake-up
| Export | Kind | Summary |
|---|---|---|
createRevisionSignal |
function | finite broadcast wait for the next monotonic process-local revision |
RevisionSignal / RevisionSignalConfig / RevisionSignalClock / RevisionSignalTimer |
type | signal handle, waiter bound and replaceable timer boundary |
RevisionSignalWaitOptions |
type | optional caller signal and positive timeoutMs; absent options wait until advance or close |
RevisionSignalWaitOutcomeSchema / RevisionSignalWaitOutcome |
schema / type | changed | timed-out | aborted | closed | capacity |
RevisionSignalWaitResultSchema / RevisionSignalWaitResult |
schema / type | terminal wait outcome with the revision observed at settlement |
RevisionSignalAdvanceResultSchema / RevisionSignalAdvanceResult |
schema / type | successful advanced or post-close closed, with the resulting revision |
RevisionSignalStateSchema / RevisionSignalState |
schema / type | open | closed lifecycle |
RevisionSignalSnapshotSchema / RevisionSignalSnapshot |
schema / type | current revision, finite pending count and lifetime outcome counters |
Bounded delivery
| Export | Kind | Summary |
|---|---|---|
createBoundedChannel |
function | finite single-reader async channel with explicit ordered or latest-value policy |
BoundedChannelPolicySchema / BoundedChannelPolicy |
schema / type | ordered | latest retention policy |
BoundedChannelStateSchema / BoundedChannelState |
schema / type | open | draining | closed | failed |
BoundedChannelSnapshotSchema / BoundedChannelSnapshot |
schema / type | exact retained count/bytes, waiter and outcome counters |
BoundedChannel / BoundedChannelConfig / BoundedChannelCloseOptions |
type | iterator/offer handle, explicit count/byte/size policy and drain/discard close mode |
BoundedChannelOfferResult |
type | delivered, queued, coalesced, or reasoned refused outcome |
BoundedChannelReaderError |
class | refusal of a second concurrent pending next() |
createCreditWindow |
function | finite byte-credit lease window with exact once-only replenishment |
CreditWindow / CreditWindowSnapshot / CreditWindowSnapshotSchema |
type / schema | byte-credit handle and absolute accounting record |
CreditAcquireResult / CreditLease |
type | reasoned refusal or idempotently releasable byte-credit lease |
CreditAcquireWaitOptions |
type | signal / timeoutMs for the waiting acquire overload; absent budget waits until credit, close or abort |
CreditWaitResult / CreditWaitRefusalReason |
type | waiting-acquire outcome; insufficient-credit is absent by construction, timed-out and aborted replace it |
Bounded diagnostic journal
| Export | Kind | Summary |
|---|---|---|
createDiagnosticJournal |
function | create one schema-owned FIFO JSONL writer with bounded retained memory, exclusive local path ownership and finite rotation |
DiagnosticJournalConfig / DiagnosticJournal |
type | owner schema/path/limits/failure observer, startupScan (tails by default, or full), onStartupRefusal (quarantine by default, or fail) and the synchronous submit, bounded-wait flush/close, status handle |
DiagnosticJournalLimitsSchema / DiagnosticJournalLimits |
schema / type | positive event, pending-item, pending-byte, file-byte and retained-file limits |
DiagnosticJournalLockPolicySchema / DiagnosticJournalLockPolicy |
schema / type | refuse (default) or reclaim-stale, which reclaims only a lock whose recorded owner is provably gone |
DiagnosticJournalStartupScanSchema / DiagnosticJournalStartupScan |
schema / type | how much of the retained generations opening a journal reads: tails (default) checks only the end of each file for a torn line, full parses every line |
readDiagnosticJournalLockDiagnosis / DiagnosticJournalLockDiagnosis |
function / type | why a reclaim-stale acquisition refused — attribution, PID liveness and optional process identity evidence (matched, different-boot, reused-pid, pid-gone, legacy, unavailable) — read off the thrown EEXIST |
DiagnosticJournalSubmitResultSchema / DiagnosticJournalSubmitResult |
schema / type | accepted epoch/sequence or explicit invalid, oversized, capacity, closed or failed refusal |
DiagnosticJournalStatusSchema / DiagnosticJournalStatus |
schema / type | state, limits, exact admission/write/failure counters, pending ownership, rotations, partial tails and last safe sequences |
DiagnosticJournalFrameSchema / DiagnosticJournalFrame |
schema / type | version-1 JSONL frame carrying process epoch, contiguous accepted sequence and schema-validated JSON event |
DiagnosticJournalWaitResultSchema / DiagnosticJournalWaitResult |
schema / type | flush settlement boundary with truthful settled, timed-out or cancelled result |
DiagnosticJournalCloseResultSchema / DiagnosticJournalCloseResult |
schema / type | physical close or caller timeout/cancellation without pretending an active write stopped |
DiagnosticJournalStateSchema / DiagnosticJournalState |
schema / type | open | draining | closed | failed |
DiagnosticJournalRefusalReasonSchema / DiagnosticJournalRefusalReason |
schema / type | closed | failed | invalid | oversized | item-capacity | byte-capacity |
DiagnosticJournalFailurePhaseSchema / DiagnosticJournalFailurePhase |
schema / type | internal write | rotation | close failure phase exposed only to status and the isolated observer |
DiagnosticJournalWaitOptions / DiagnosticJournalFailure |
type | caller wait signal/timeout and isolated internal failure callback record |
DiagnosticJournalAnomalySchema / DiagnosticJournalAnomaly |
schema / type | corrupt-row reason, file, zero-based byte offset, one-based line, tail/interior position and skipped bytes |
createDiagnosticJournalReadResultSchema / DiagnosticJournalReadResult |
function / type | owner-schema frame output or explicit anomaly; retains transformed event output types |
DiagnosticJournalRecoveryStatusSchema / DiagnosticJournalRecoveryStatus |
schema / type | bounded startup inspection counts, first/last anomaly locations and every quarantined file beside the journal (quarantined, this open’s moves first with their reason, at most 32; quarantinedUnlisted counts the rest); evolving and .strict(), so every shape change is a breaking changelog item |
DiagnosticJournalStartupRefusalPolicySchema / DiagnosticJournalStartupRefusalPolicy |
schema / type | quarantine (default) renames a file opening cannot keep in place to <file>.quarantined-<epoch> and starts; fail throws and moves nothing |
DiagnosticJournalStartupRefusalReasonSchema / DiagnosticJournalStartupRefusalReason |
schema / type | torn-without-retention-slot | not-a-regular-file | unreadable |
DiagnosticJournalRecoveryError / DiagnosticJournalRecoveryErrorOptions |
class / type | typed startup refusal (reason, file, optional recovery, quarantineFailed) thrown under fail or when moving a file aside failed; preserves evidence and releases its lock |
accepted is bounded in-memory admission and written is completed append, not fsync or durable
delivery. Its filesystem reader is in the diagnostic-journal leaf; there is no managed replay/upload API. See the
guide,
architecture and ADR
0134.
Managed schedules
| Export | Kind | Summary |
|---|---|---|
createManagedSchedule |
function | fixed-rate process-local timer that activates after top-level readiness and participates in drain |
ManagedScheduleOverlapSchema / ManagedScheduleOverlap |
schema / type | skip, queue-one or bounded parallel overlap policy |
ManagedScheduleErrorPolicySchema / ManagedScheduleErrorPolicy |
schema / type | continue or stop-schedule after an observed callback failure |
ManagedScheduleDescriptorSchema / ManagedScheduleDescriptor |
schema / type | immutable public schedule identity and cadence policy |
ManagedScheduleStatusSchema / ManagedScheduleStatus |
schema / type | absolute schedule state, revision, counters and timestamps |
Schedule authoring additionally exports ManagedSchedule, ManagedScheduleConfig,
ManagedScheduleRunContext, ManagedScheduleClock, ManagedScheduleTimer and ManagedScheduleTrigger.
The clock exposes monotonic cadence/deadline arithmetic and a wall-clock projection for portable
status timestamps; it is a deterministic test boundary, not a durable scheduler.
A ManagedSchedule also has wake(): the owner of the event that creates work asks for one run now,
and the run follows the timer path (overlap, errorPolicy, onError, counters). Run context
carries trigger ('timer' or 'wake'); status adds runsWoken, wakesCoalesced and lastTrigger.
Application and activity projection
| Export | Kind | Summary |
|---|---|---|
createActivityProjection |
function | aggregate anonymous process-local activity into declared bounded stages and absolute snapshots |
createApplicationSnapshotSink |
function | latest-value delivery with one write in flight and one replaceable pending revision |
applicationLifecycleEvent |
function | project a sanitized lifecycle fact from a canonical application snapshot |
createApplicationEventSink |
function | bounded failure-isolated lifecycle-event delivery; events are not canonical state |
ActivitySnapshotSchema / ActivitySnapshot |
schema / type | epoch, monotonic revision, timestamps, declared stages and aggregate counts |
ApplicationSnapshotSinkStatusSchema / ApplicationSnapshotSinkStatus |
schema / type | immutable latest-value sink delivery and coalescing counters |
ApplicationLifecycleEventSchema / ApplicationLifecycleEvent |
schema / type | sanitized operator-facing application lifecycle fact |
Activity authoring additionally exports ActivityId, ActivityIdSchema,
ActivityStageId, ActivityStageIdSchema, ActivityStageSnapshot,
ActivityStageSnapshotSchema, ActivityLiveState, ActivityLiveStateSchema,
ActivityProjection, ActivityProjectionConfig,
ActivityProjectionSubscriberError, ActivityToken and ActivityTransition.
Latest-value delivery exports ApplicationSnapshotSink,
ApplicationSnapshotSinkConfig, ApplicationSnapshotSinkError and
RevisionedApplicationSnapshot; event delivery exports ApplicationEventSink
and ApplicationEventSinkConfig.
Canonical application records
These are also published on their own as
stitchkit/application/schemas, which carries
no server runtime and can therefore be imported from a browser bundle.
The entrypoint exports each Zod schema beside its inferred type:
ApplicationIdSchema / ApplicationId, ApplicationLifecycleSchema /
ApplicationLifecycle, ApplicationHealthSchema / ApplicationHealth,
ManagedResourceStateSchema / ManagedResourceState,
ApplicationAdmissionSnapshotSchema / ApplicationAdmissionSnapshot,
ManagedResourceSnapshotSchema / ManagedResourceSnapshot,
ApplicationSnapshotSchema / ApplicationSnapshot,
ApplicationStatusProjectionSchema / ApplicationStatusProjection with
projectApplicationStatus — what a status or probe endpoint may publish, and
the function that derives it from a snapshot,
ApplicationResourceShutdownSchema / ApplicationResourceShutdown, and
ApplicationShutdownResultSchema / ApplicationShutdownResult.
Decisions
A pipeline of policies that each vote allow, deny or defer, sharing its
vocabulary with an event topic declared mode: 'decision'.
| Export | Kind | Summary |
|---|---|---|
createDecisionPipeline |
function | run policies in declaration order; the first terminal verdict wins and the rest do not run |
DecisionPipelineConfig |
type | policyTimeoutMs — how long one policy has to answer. Required, no default: a policy that never settles hangs every caller of the operation it guards |
PolicyDecisionSchema / PolicyDecision |
schema / type | allow, deny with a reason, or defer — a deny cannot be silent |
DecisionPolicy / DecisionPipeline |
types | one named voter over the caller’s subject, and the pipeline it composes into |
DecisionResult / DecisionTraceEntry |
types | the verdict, and the trace of what actually ran — not what was declared |
DecisionUndecidedError |
class | every policy deferred and no undecided outcome was declared: an unanswered question, raised rather than guessed |
DecisionPolicyError |
class | a policy returned a non-decision, threw, or ran past policyTimeoutMs — one error for all three, carrying the policy id and the trace so far |
Keyspace and watched reads
| Export | Kind | Summary |
|---|---|---|
defineKeyspace / keyspaceResource |
function | a named record set read synchronously from memory and written through one serialised chain; backend first, then memory, then the change event |
openKeyspace / OpenedKeyspace |
function / type | the same keyspace opened directly, for an application that owns its own lifecycle rather than declaring resources to a kernel |
KeyspaceBackend / KeyspaceDeclaration / KeyspaceChange / KeyspaceResourceConfig / OpenKeyspace |
types | the four-method durability port, the declaration, the announced change, the resource’s options and the published handle. backend takes a value or a factory — a factory is called once per generation, so a restarted keyspace gets a backend that was never closed |
memoryKeyspaceBackend / sqliteKeyspaceBackend / SqliteKeyspaceBackendConfig |
function / type | a disposable in-process backend, and one table with a key and a JSON payload over a caller-owned database |
SqliteDatabase / SqliteStatement / SqliteValue |
types | the minimal synchronous SQLite boundary the framework types against |
createWatchHub / watchKey |
function | one read per question however many are asking: single-flight per key, re-read on a declared topic, publish only what changed |
WatchHub / WatchHubConfig / WatchOperation / WatchSubscriber / AttachedWatcher |
types | the hub, its read/watchable/invalidation policy, the operation identity, and one connection’s attachment |
Managed change subscriptions and scoped watches
changeSubscriptionResource (stitchkit/application) accepts
ChangeSubscriptionConfig: id, unique keys (1–128, at most 256 characters each),
connect(signal), reconcile(key, context), required reconcileIntervalMs (10 ms–1 h),
optional timeoutMs (30000; 1 ms–1 h), backoff, and onError.
ChangeConnection supplies subscribe({ signal, hint, disconnected }), which completes subscription
before the first read; close() releases it. ChangeReconciliation exposes signal
and a synchronous commit(callback) guard against late publication. Drivers must
honor cancellation. Uncooperative work retains its slot until settled instead of
allowing overlapping connections/reads. Errors reach onError; no raw payload or
connection string is logged by this resource. Recovery runs after reconnect and
periodically even when no notification arrives.
WatchHubConfig adds maxSources (1024), maxSubscribers (1024), and optional
reconcileIntervalMs (10 ms–1 h). hub.attach(subscriber, scope?) accepts a
WatchAdmissionScope containing a server-verified key (1–512 characters) and
revocation signal. The key separates sharing and is the optional third argument
of read(operation, args, scope); a key’s instance routes frames and never
separates sources. Attached over maxSubscribers, a subscriber gets a watcher whose
open refuses with Watch subscriber capacity exceeded; attach does not throw
for capacity. It must represent account, session and permissions;
never trust a client-supplied owner ID as that scope.
Notification action and projection receipts
NotificationOutboxConfig.delivery accepts NotificationDeliveryConfig:
immutable executor version, pure actions(payload) plan selector (1–128 unique
names, each at most 128 characters), and idempotent project(notification, receipts).
send receives optional action and stable idempotencyKey, and returns a JSON
remote receipt (void becomes null). A result that is not JSON or does not fit the
byte budget is kept as receipt: null with unrecorded: 'not-json' | 'too-large';
the action stays confirmed and is not sent again. retiredVersions maps earlier
plan versions to their NotificationProjection so queued items drain after an
executor upgrade; an unknown version is reported to onError as
NotificationPlanVersionError and waits, spending no attempt and not consulting
classify, for an executor that knows it. NotificationDeliveryStateSchema validates the
optional NotificationDeliveryState on queued items and completed receipts:
version, actions, receipts and optional projectedAt. Checkpoints share the
existing atomic StateStore and lease fence. Receipt retention and serialized byte
budgets still apply. Single-send configuration remains valid without delivery.
A remote result lost before its checkpoint may be sent again; provider idempotency
or reconciliation is required. A projection may repeat after a crash before its
checkpoint. Business-transaction enqueue and durable quarantine are not implied.
stitchkit/application/grammy
Isolated optional-peer lifecycle adapters. Importing stitchkit/application
does not resolve grammY.
| Export | Kind | Summary |
|---|---|---|
grammyPollingResource |
function | adapt an injected bot’s long polling with distinct onStart readiness, observed completion and one stop chain |
grammyBotResources |
function | a long-polling bot as telegram-configuration (optional configure, e.g. setMyCommands) then telegram-polling, both after the bot’s dependsOn; updates admitted by batch and the end of polling reported to onEnded |
GrammyBotResourcesConfig / GrammyBotResources |
type | injected bot, dependsOn, configure, polling options, onStart / onError / onEnded; { configuration?, polling, resources } in start order |
TELEGRAM_CONFIGURATION_RESOURCE_ID / TELEGRAM_POLLING_RESOURCE_ID |
constant | the two stable ids a monitor, a test or a restart addresses |
GrammyPollingEnd |
type | { error? } — how a poller that was ready ended on its own; never reported for a requested stop |
createGrammyWebhookResource |
function | return a managed resource plus admission-guarded handleUpdate; HTTP hosting and webhook registration stay application-owned |
GrammyWebhookUnavailableError |
class | stable GRAMMY_WEBHOOK_NOT_ACCEPTING rejection after webhook admission closes |
GrammyPollingResourceConfig |
type | injected bot, polling options, resource graph policy and isolated error observer |
GrammyWebhookResourceConfig / GrammyWebhookResource |
type | injected webhook bot declaration and { resource, handleUpdate } handle |
GrammyUpdate |
type | exact update input inferred from the injected grammY bot context |
stitchkit/application/opentelemetry
Type-only optional-peer adapter for applications that already own an OpenTelemetry SDK and exporter. Its observable gauges pull absolute canonical snapshots; the adapter owns no SDK lifecycle, polling or delta state.
| Export | Kind | Summary |
|---|---|---|
createApplicationOpenTelemetry |
function | register fixed observable application, resource, admission, schedule and activity gauges on an injected Meter |
ApplicationOpenTelemetryConfig |
type | injected meter and canonical application/activity/schedule pull sources plus isolated diagnostic hook |
ApplicationOpenTelemetryBinding |
type | idempotent exact callback removal and closed state |
ApplicationTelemetryMeter |
type | minimal structural Meter.createObservableGauge boundary compatible with @opentelemetry/api |
ApplicationOpenTelemetryCollectionError |
type | isolated instrument-name/error diagnostic without product/provider attributes |
stitchkit/application/diagnostic-journal
| Export | Kind | Summary |
|---|---|---|
createDiagnosticJournal |
function | the bounded local journal: a file lock, a spawn to diagnose a stale one, and framed writes |
readDiagnosticJournal |
function | bounded async stream of validated frames and explicit anomalies from finite snapshots of caller-selected files; I/O failures throw |
DiagnosticJournalReaderConfig |
type | normalized absolute paths, owner eventSchema, positive safe-integer maxLineBytes and optional cancellation signal |
Its own entrypoint because of what it reaches — node:child_process,
node:fs, node:os, node:util — with promisify(execFile) evaluated while
the module initialises. Exported from stitchkit/application, that one line made
the entire barrel unusable in a browser bundle: not by failing at the call, but
by throwing during module initialisation, on every route.
Its contract stays in stitchkit/application — every
DiagnosticJournal*Schema, the states and the refusal reasons touch nothing but
Zod, and a client reading a journal’s status has as much right to them as the
server writing it.
stitchkit/application/schemas
The canonical application records — and nothing else. Every export here is also
reachable from stitchkit/application; the difference is what comes with it.
stitchkit/application is the server runtime: it reaches node:child_process,
node:fs and node:crypto. A browser bundler does not omit those, it
substitutes stubs — so a module that merely names an application schema fails
while it is initialising, and the page never mounts, on every route rather than
the one that wanted the schema. A contract whose output is an application
snapshot could be declared and never consumed, which is the one thing a contract
is for.
So the same schemas ship a second way, from a module with nothing behind them:
// browser and server alike
import { ApplicationSnapshotSchema } from 'stitchkit/application/schemas';
The exports are exactly those listed under
canonical application records above.
packages/core/scripts/check-browser-clean.mjs holds the promise against the
built artifact: it walks the browser lane’s real dist output and refuses a
node: import reachable from any of it, and refuses an entry built for the
browser that no exports path leads to — which is how this one was missing.
stitchkit/agent-runtime
Server-only optional application runtime. See the agent runtime guide.
| Export | Kind | Summary |
|---|---|---|
createAgentRuntime |
function | compose durable acceptance, stream loop, checkpoints, coordination, managed tools and winner-only terminal publication; reconciles same-owner terminal/interrupt/head CAS races before releasing the lane |
createDeferredAgentToolSurface |
function | bounded canonical catalog search plus durable same-run activation of direct mountAgent tools; supports one immutable surface or a finite identity-specific registry |
DeferredAgentToolSearchInputSchema / DeferredAgentToolMatchSchema / DeferredAgentToolReceiptSchema |
schema | bounded search input, public match and versioned durable selection receipt |
DeferredAgentToolSurfaceConfig / DeferredAgentToolCommonConfig / DeferredAgentToolSurfaceDefinition / DeferredAgentToolController |
type | finite catalogs, selector, pin, budget and mount/prepareStep composition contracts |
DeferredAgentRuntimeToolDefinition / DeferredAgentToolMountConfig |
type | peer-free Agent-only runtime definition and canonical mount configuration accepted by the controller |
DeferredAgentToolManifestEntry / DeferredAgentToolSearchContext / DeferredAgentToolReceipt |
type | canonical selector input and inferred durable receipt records |
DeferredAgentToolEvent |
type | PII-free search/step evidence with surface, provenance, counts, canonical schema bytes and ceilings |
defineAgentProtocol |
function | declare context, input metadata, canonical parts and optional pre-CAS terminal acceptance (allow-empty, require-output or callback) |
hasAgentTerminalOutput |
function | generic require-output predicate for non-blank text, generated files, structured provider parts and explicit tool-only policy stops |
AgentMessageSchema / AgentRunSchema / AgentSnapshotSchema |
schema | versioned canonical engine records |
AgentRunQueuePrioritySchema |
schema | durable opt-in priority for queued interrupt-next runs |
AgentRuntimeStore |
type | aggregate CAS transaction boundary for message, run and compaction mutations |
BranchAgentConversationInputSchema / BranchAgentConversationInput |
schema / type | strict branch request: stable request key, empty destination, settled conversation boundary or archive bytes, fresh artifact authorization |
AgentConversationBranchReceiptSchema / AgentConversationBranchReceipt |
schema / type | durable lineage: request fingerprint, source/destination identities, source sequence/version/digest and creation time |
AgentConversationBranchResultSchema / AgentConversationBranchResult |
schema / type | created or duplicate with the same durable receipt; AgentRuntimeStore.branchConversation is optional for hand-written stores |
createAgentRuntimeStore |
function | build the aggregate store from one coherent transaction driver; framework owns every state transition |
AgentRuntimeStoreDriver |
type | ORM-neutral transaction over a bounded head, normalized runs/admissions, product history, a required events: { append, list } ledger table, an optional archive: { export, import } for driver-owned durable payloads, and indexed run recovery; optional { access: 'read' } selects a coherent read transaction while absent options remain write-safe |
recordAgentRetryDecision / AgentRetryPolicy |
function / type | loop.retry policy and the ledger record of a retry decision: explicit retryability and backoff at a durable provider-step boundary |
AgentRuntimeHeadSchema |
schema | constant-size conversation identity plus monotonic runtime version |
AgentStoredRunSchema |
schema | canonical normalized run with an optional retained terminal assistant |
AgentAdmissionReceiptSchema |
schema | durable idempotency receipt with canonical input and assigned run/assistant identities |
AgentHistoryMutationSchema |
schema | typed canonical message mutation applied inside the winning state transaction |
RecoverAgentRunSchema |
schema | explicit abandon/requeue recovery decision; acquired runs require replay-safe evidence |
createMemoryAgentRuntimeStore |
function | process-local reference adapter, not production durability |
purgeAgentConversation |
function | dispatch optional atomic deletion; returns unsupported, active, conflict, purged or already_purged |
AgentConversationPurgeInputSchema / AgentConversationPurgeInput |
schema / type | conversation ID and optional expected snapshot version |
AgentConversationPurgeResultSchema / AgentConversationPurgeResult |
schema / type | typed deletion/refusal outcomes; active refusal includes run IDs |
AgentConversationPurgedError |
class | runtime mutation rejected because its conversation ID is permanently purged |
AgentConversationPurgeDriver |
type | optional driver.conversations capability: serialized tombstone read and atomic removal of all owned records |
projectAgentHistory |
function | asynchronously project canonical records and resolved multimodal files into provider-valid AI SDK messages |
defineModelRegistry |
function | typed language-model descriptors, capabilities and provider construction |
AgentModelCatalogSchema / AgentModelCatalog |
schema / type | provider-neutral complete/partial model catalog with separately sourced popularity, metrics, prices and observation time |
AgentModelCatalogEntrySchema / AgentModelCatalogEntry |
schema / type | one canonical provider model descriptor with optional price, popularity and metric evidence |
AgentModelPriceSchema / AgentModelPrice |
schema / type | normalized per-token input/output pricing and source currency |
AgentModelPopularitySchema / AgentModelPopularity |
schema / type | independently sourced ranked popularity observation with window and timestamp |
AgentModelMetricSchema / AgentModelMetric |
schema / type | independently sourced benchmark measurement with provenance and observation time |
AgentModelCatalogProvider |
type | abortable live catalog loader supplied by a provider adapter or application |
AgentModelSearchInputSchema / AgentModelSearchInput |
schema / type | bounded catalog text query and result ceiling |
AgentModelSearchResultSchema / AgentModelSearchResult |
schema / type | exact bounded catalog projection with total match count |
searchAgentModelCatalog |
function | deterministic bounded search over a loaded canonical catalog |
AgentModelSelectionSchema / AgentModelSelection / AgentModelSelectionStore |
schema / type | durable per-conversation model choice; runtime resolvers receive run and snapshot to recover the model pinned to input metadata |
createMemoryAgentModelSelectionStore |
function | process-local selection reference adapter |
AgentConversationReader |
type | optional bounded conversation-summary and message-history reader; messages takes includeCompacted and every page names its compacted ids; not part of the required runtime store contract |
AgentConversationSummarySchema / AgentConversationSummary |
schema / type | bounded durable conversation list item with version, activity and preview |
AgentConversationPageSchema / AgentConversationPage |
schema / type | cursor-paged conversation summaries |
AgentConversationMessagePageSchema / AgentConversationMessagePage |
schema / type | cursor-paged durable message history |
composeAgentPrompt |
function | ordered prompt contributions and provenance-aware signed context budget; irreducible reservation deficits are oversized, not compactable history |
SeedConversationInputSchema / SeedConversationInput |
schema / type | atomic once-seeding input; partial imported identity sets are refused |
AgentSeedReceiptSchema / AgentSeedReceipt |
schema / type | durable seed receipt retained beyond compaction and implemented by custom store drivers |
StepRunOptions |
type | per-step options of the durability engine (stitchkit/tools) as the runtime drives it |
DURABILITY_STEP_EVENT_KIND |
const | the ledger event kind a recorded step is written under |
StepResultDecodeError / StepResultNotSerializableError / StepAbortedError / ParkRecordDecodeError / ParkAbortedError |
class | fail-closed decode of a recorded step or park, a body whose result cannot be serialized, an aborted step, and a park collapsed around an aborted waiter |
structuredCompaction |
function | summarize a provider-valid snapshot range and replace it through CAS |
selectCompactableHistory |
function | which oldest whole complete turns may be summarised away — the half of compaction that needs no store (→ ADR 0142) |
SelectCompactableHistoryOptions / CompactableHistory |
type | message list, retained-turn count and evidence policy in; leadingSummary, compactable and retained out |
createAgentSessionCoordinator |
function | strict process-local queue/interrupt/supersede lifecycle |
AgentRuntimeStopPolicy |
type | named custom AI SDK stop condition persisted and published on policy stop |
AgentRuntimePrepareStep |
type | per-run controlled step callback with typed domain context and managed run signal/fence |
AgentContextOverflowError |
class | deliberate application budget refusal thrown from loop.prepareStep; terminalizes as context_overflow without classifying arbitrary error text |
AgentRuntimeRecordIds |
type | optional caller-provided input, run and assistant IDs for stable application records |
AgentRuntimeAdmission |
type | canonical committed input, assigned run, pending assistant projection, compatibility IDs and snapshot version |
AgentAdmissionEventSchema |
schema | post-commit admission projection; removes store rereads but does not imply exactly-once delivery |
AgentRunMetricsSchema |
schema | optional provenance-aware usage and timings; partial says the provider never reported the run finished, so the figure beside it is not a confirmed total |
AgentRuntimeRecoverOptions |
type | bounded paged startup recovery with causal per-conversation scheduling, context resolver and explicit evidence policy |
AgentRuntimeAbandonInput |
type | one known orphan identity, expected revision and mandatory stale-owner evidence for runtime.abandon() |
AgentRuntimeConflictError |
class | thrown when a store mutation loses to a concurrent writer — catchable by type from stitchkit/agent-runtime |
AgentSessionCloseOptions |
type | gracePeriodMs for natural settlement, then abort, then forceTimeoutMs for bounded settlement after it |
AgentSessionCloseResult |
type | what close() achieved: settled, or timedOut with remaining runs still in flight. Only omitting forceTimeoutMs guarantees nothing is in flight on return |
AgentHistoryProjectionOptions |
type | storage-neutral file resolver, explicit unresolved-file behavior, and how an interrupted turn reaches the model (interruptedAssistant) |
createAgentToolFenceLifecycle |
function | pre-effect and post-effect run ownership fence for mountAgent; compose beside application idempotency for durable operations |
AgentRuntimeEventSchema |
schema | transient stream lifecycle plus post-commit admission/checkpoint/run-state/run-operation/terminal projections |
AgentRunOperationKindSchema / AgentRunOperationPhaseSchema / AgentRunOperationSchema / AgentRunOperation |
schemas / type | latest durable model-request or compaction phase with operation/step identity and original timestamps; request admission is awaited before provider invocation |
RecordRunOperationSchema / RecordRunOperation |
schema / type | owner/fencing/revision-checked mutation of AgentRun.lastOperation |
createAgentObservability |
function | separate agent-run sink over the shared bounded observability lifecycle |
AgentProviderResponseSchema / AgentProviderResponse |
schema / type | provider-assigned response ID and the optional upstream provider the model’s own adapter resolves, shared by step-finished.response and durable provider/response facts |
AgentStepFinishedEventSchema / AgentStepFinishedEvent |
schema / type | one completed provider step with required usage and provider response identity |
Durable capability layer
| Export | Kind | Summary |
|---|---|---|
AgentConversationArchiveSchema / AgentConversationArchive / encodeAgentConversationArchive / decodeAgentConversationArchive / canonicalAgentJson |
schema / type / functions | canonical validated conversation archive (canonicalAgentJson is canonicalJson with the node and byte limits at their maximum, reading -0 as 0 like z.json()) with exact ledger events, recovery projection and durable spill payloads |
AgentStoreEventEnvelopeSchema / AgentStoreEventEnvelope / AgentStoreEventKindSchema / AgentStoreEventKind / AgentStoreEventPageSchema / AgentStoreEventPage |
schema / type | append-only event envelope, closed current vocabulary (including provider/request and provider/response) and bounded page |
AppendAgentStoreEventSchema / AppendAgentStoreEvent / ReadAgentStoreEventsSchema / ReadAgentStoreEvents |
schema / type | required append and bounded-read store contracts |
AgentStoreTransitionSchema / AgentStoreTransition / AgentStoreEventDraft / AgentStoreEventDecodeAccepted / AgentStoreEventDecodeIgnored / AgentStoreEventDecodeResult / decodeAgentStoreEvent |
schema / types / function | normalized runtime mutations, append drafts and strict current/ignorable future-event decoding outcomes |
AgentStoreTransitionRecordSchema / AgentStoreTransitionRecord |
schema / type | persisted journal payloads: full runtime mutations or hash-only streaming checkpoint observations with numeric part/byte counts; inspection does not authorize replay |
defineAgentProjection / AgentProjectionDefinition / AgentProjectionValue / createAgentProjectionRegistry / createSqliteAgentProjectionStore |
functions / type | deterministic folds with persisted version and honest uptoSeq checkpoints |
agentSummaryProjection / agentUsageProjection / agentOutlineProjection |
constants | built-in list summary, provenance-carrying usage and request outline projections |
agentConversationCardProjection / agentStateSlotsProjection / agentScheduleSummaryProjection |
constants | focused card, durable-state and schedule lifecycle projections |
defineStateSlot / AgentStateSlotDefinition / AgentStateSlotStore / AgentStateSlotValue / AnyAgentStateSlot / createAgentStateSlotStore / renderAgentStateSlots |
functions / types | typed durable state written as ledger events and injected on every provider request |
agentGoalStateSlot / agentTodoStateSlot / createAgentStateTools |
constants / function | built-in goal/todo state and bound goal_* / todo_write Agent tools |
AgentSandboxGradeSchema / AgentSandboxGrade / AgentSandboxRestrictionSchema / AgentSandboxRestriction / AgentProcessSandbox |
schema / type | host-provided process sandbox capability and explicit restriction vocabulary |
probeAgentProcessSandbox / missingSandboxRestrictions / recordAgentSandboxProbe |
functions | probe cached per sandbox object (keep the sandbox long-lived), fail-closed required-gap calculation and durable probe record; a probe that throws or returns no valid grade resolves to unavailable with a fixed reason, its cause emitted as a process warning (the coding tools instead carry it as the refusal’s cause to the mount’s onToolError hook) |
AgentSandboxProcess / AgentSandboxOutputStream |
types | structural child/output interface for optional lifecycle-owned AgentProcessSandbox.spawn, without Node ambient type dependencies |
AgentEventSearchResultSchema / AgentEventSearchResult / createSqliteAgentEventSearch / createAgentEventSearchTools |
schema / type / functions | authorized FTS5 search with exact event addresses and session_* tools |
createSqliteAgentSpillStore |
function | durable content-address-checked artifact storage, bounded read/search, retention facts and archive participation |
AgentScheduleSchema / AgentSchedule / AgentScheduleService / AgentScheduleDeliveryOutcomeSchema / AgentScheduleDeliveryOutcome / createAgentScheduleService / createAgentScheduleTools |
schemas / types / functions | durable at/after/timezone-explicit every, indexed retry eligibility, typed retry/terminal failure (any other returned value delivers), maxAttempts (default 1000) per occurrence — a one-off ends failed, a recurring schedule skips to its next slot — bounded dispatch and fenced stable occurrence identity (ADR 0202) |
AgentChildBudgetSchema / AgentChildBudget / AgentChildStateSchema / AgentChildState / AgentChildRecordSchema / AgentChildRecord |
schema / type | durable child graph, bounded seed and measured budget state |
AgentChildBlockingKindSchema / AgentChildBlockingKind / AgentChildBlockingSourceSchema / AgentChildBlockingSource / AgentChildBlockingEventSchema / AgentChildBlockingEvent / AgentChildBlockingDecision |
schemas / types | parent-owned request identities; responses discriminate approval decisions from JSON input values |
AgentChildHandle / AgentChildManager / SqliteAgentChildManagerConfig / createSqliteAgentChildManager / createAgentChildTools / agentChildBudgetStopPolicy |
type / functions | host execution port, child lifecycle, cascade (given to createAgentRuntime as children), messaging, Agent tools, and the child runtime’s own budget stop policy — recordStepUsage at every step boundary, policy_stop as child-budget when spent |
AgentToolDefinition |
type | peer-neutral shape returned by the bound agent-only state, search, schedule and child tool factories |
AgentProviderStreamCutError |
class | explicit retryable provider stream truncation evidence |
Complete runtime inventory
The entrypoint deliberately exports the schemas beside their inferred types so persistence and
transport adapters validate the same records. Runtime composition types are AgentRuntime,
AgentRuntimeConfig, AgentRuntimeInput, AgentRuntimeProtocolInput, AgentRuntimeRunContext,
AgentRuntimeResult, AgentRuntimeInterruptInput, AgentRuntimeAbandonInput, AgentRuntimeRecoveryInput,
AgentRuntimeRecoveryDecision, AgentRuntimeRecoveryOutcome, AgentRuntimePublisher,
AgentInputPolicy, AgentStopReason, AgentCoordinatedRun, AgentRunTicket,
AgentSessionCoordinator, AgentCompactionContext, AgentCompactionResult and
StructuredCompactionConfig.
A provider refusal is classified rather than phrased. classifyProviderFailure returns an
AgentProviderFailure — an AgentProviderFailureReason (insufficient-credits, rate-limited,
model-unavailable, context-overflow, timeout, cancelled, unknown), the provider’s status
when it supplied one, whether the same request is retryable unchanged, and the evidence the
answer rests on: status is the provider stating its own answer, message is us reading its prose,
and none is an honest refusal to guess. The sentence a user reads stays with the application —
its tone and its decision about what to admit are not the core’s to make. isToolResultFailure
recognises a failure carried inside a successful tool result, in both the bare and the
{ value: … } envelope. Both are plain functions and need no runtime. → ADR 0141
normalizeOpenRouterUsage is the same normalisation openRouterProvider
applies, exported so an application calling the SDK directly gets provenance-correct numbers
without adopting the runtime. Pass each completed SDK step’s usage, including raw.
Token provenance comes from the original OpenRouter fields: missing fields remain
unavailable, even when the SDK substitutes zero. Aggregate usage without raw cannot
establish reported token counts. Explicit zero remains provider-reported; cost is never
estimated from token prices.
AgentContextUsage reaches every step through AgentRuntimeRunContext.contextUsage: how full the
model’s context is, as usedTokens (an AgentUsageValue, so it carries the provenance that says
where the number came from) beside the model’s declared contextWindow. It is the last completed
step’s prompt size, not the run’s cumulative input tokens — cumulative counts every step’s prompt
again and is a multiple of the real fill. Before the first step lands there is no provider-reported
number and the provenance is unavailable, which is a different fact from zero. No fraction is
exposed: dividing is one line where it is rendered, and the output reserve belongs to the
consumer’s prompt budget rather than to this layer.
Canonical protocol exports are AgentProtocol, AgentProtocolConfig, AgentTerminalAcceptance,
AgentTerminalAcceptanceInput, hasAgentTerminalOutput, AgentRecordIdSchema, AgentRecordVersionSchema,
AgentTimestampSchema, AgentJsonObjectSchema, AgentProviderEnvelopeSchema,
AgentProviderEnvelope, AgentMessagePartSchema, AgentMessagePart, AgentTextPartSchema,
AgentReasoningPartSchema, AgentFilePartSchema, AgentSourcePartSchema,
AgentToolCallPartSchema, AgentToolResultPartSchema, AgentOpaquePartSchema,
AgentControlPartSchema, AgentMessageRoleSchema, AgentMessageStatusSchema, AgentMessage,
AgentAssistantPlaceholderSchema, AgentAssistantPlaceholder, AgentRunStateSchema,
AgentTerminalReasonSchema, AgentTerminalReason, AgentRunQueuePrioritySchema,
AgentRunQueuePriority, AgentRun, AgentSnapshot,
AgentUsageValueSchema, AgentCostValueSchema, AgentUsageSchema, AgentUsage and
AgentRunMetrics.
AgentProvenanceSchema / AgentProvenance is the entrypoint’s single vocabulary for how a
number came to be known: provider-reported (the provider stated it about a request it served),
measured (this process counted it exactly, before any request was made), computed (arithmetic
over other values — a sum of exact numbers is still computed), estimated (a heuristic) and
unavailable (not known, so value is absent, which is a different fact from a reported zero).
Each surface declares the subset it can produce: AgentUsageValueSchema and AgentCostValueSchema
describe a request that has already happened and never say measured; AgentTokenCountSchema
describes a prompt being composed and never says provider-reported. Every token count is an
integer — AgentUsageValueSchema and AgentTokenCountSchema refuse a fractional value, and a
provider figure that is not a whole number is normalised to unavailable rather than thrown.
AgentCostValueSchema.value stays fractional, because money is.
runs.inputPolicy takes queue (default), inject, interrupt, interrupt-next or supersede, or a function of
the raw input returning one. inject lets a run in flight take a newly arrived input into its prompt
at a step boundary and answer it too; the absorption is committed in the same transaction as that
run’s terminal record, via CommitRunTerminal.absorb, so a run that ends any other way leaves an
ordinary queued successor. The absorbed run ends with terminalReason: 'absorbed', run state
'superseded', absorbedIntoRunId naming the run that answered it, and no assistant message of
its own; a submission on its idempotency key resolves through that pointer to the answer
(→ ADR 0113).
interrupt-next interrupts the active run, waits for its real settlement and then executes the new
input before ordinary pending work. Ordinary work is not dropped or re-admitted, and urgent work is
FIFO within its own class. AgentRun.queuePriority persists the pending class;
AgentRun.executionSequence persists the actual first-acquisition order, so recovery and canonical
history preserve the same A → C → B order across equal timestamps and scan pages (→ ADR 0127).
With queue, a durable successor admission is not prompt eligibility: the current executor sees
only records through its own run boundary. Snapshot history is normalized to causal turn order
(assigned input(s), assistant, then successor input(s)) even when the storage codec physically
appended the successor before the predecessor checkpoint.
AgentRuntimeStore has two bounded reads beside loadSnapshot:
loadRun({ conversationId, runId }) returns an AgentRunView — the run, the conversation version it
was read at, and the retained answer once the run is terminal — or undefined; listActiveRuns(conversationId)
returns the runs that have not ended in durable execution/priority order. Neither reads history, so
neither grows with the length of the conversation, and neither needs anything new from
AgentRuntimeStoreDriver. loadSnapshot and every mutation result still carry the whole
conversation — that is what the store’s reducer validates against, and what the runtime builds a
prompt from (→ ADR 0112).
AgentRuntimeStore.purgeConversation is optional; purgeAgentConversation(store, input) explicitly
handles unsupported stores. Official memory and initialized SQLite stores refuse active runs,
remove every owned payload and reserve the conversation ID permanently. Empty snapshots are not
deletion receipts. Consumer metadata, files, event logs and UI cache invalidation remain outside
the transaction. See purging a conversation.
Store command/result exports are AcceptInputAndAssignRun, AcceptInputAndAssignRunSchema,
AcquireAgentRun, AcquireAgentRunSchema, CheckpointRunAssistant,
CheckpointRunAssistantSchema, CommitRunTerminal, CommitRunTerminalSchema,
RequestRunInterrupt, RequestRunInterruptSchema, AgentRunView, AgentRunViewSchema,
runStateForTerminalReason,
ACTIVE_AGENT_RUN_STATES, RecoverAgentRun, ReplaceCompactedRange,
ReplaceCompactedRangeSchema, AgentStoreMutationResult, AgentStoreMutationResultSchema,
AgentStoreAppliedSchema, AgentStoreConflictSchema, AgentStoreDuplicateSchema,
AgentStoreNotFoundSchema, AgentAdmissionReceipt, AgentAdmissionReceiptSchema,
AgentRuntimeHead, AgentStoredRun, AgentStoreCompareAndSwapResult, AgentHistoryMutation,
AgentRecoverableDescriptor, AgentRecoverableDescriptorSchema, AgentRecoverablePage and
AgentRecoverablePageSchema.
History and context-budget exports are projectAgentHistoryDetailed,
AgentHistoryProjectionDecision, AgentHistoryProjectionResult, selectAgentHistory,
SelectAgentHistoryOptions, AgentHistoryBudgetDecision, AgentHistoryBudgetResult,
AgentPromptBudget, AgentPromptSection, AgentPromptSectionContext, AgentTokenCount,
AgentTokenCountSchema, ComposeAgentPromptOptions and ComposedAgentPrompt. Whole-turn history
selection never splits a tool chronology and reports why every canonical record was retained or
removed. AgentHistoryEvidencePolicy is the shared opt-in for marked failed-assistant evidence in
projection, budgeting and structured compaction; isAssistantHistoryEvidence applies it. The
compatibility default omits it. Approval message schemas are
AgentToolApprovalRequestPartSchema and AgentToolApprovalResponsePartSchema.
Model exports are AgentLanguageModelProvider, AgentModelCapability,
AgentModelCapabilitySchema, AgentModelDescriptor,
AgentModelDescriptorSchema, AgentModelRegistry, AgentModelRegistryConfig,
AgentModelRegistrySnapshot, AgentModelRegistrySnapshotSchema, AgentModelSnapshotPolicy,
AgentResolvedModel and validateAgentModelSnapshot. Registry preflight validates availability,
provider and required capabilities without constructing the model; runtime models.preflight
runs before durable admission.
Delivery exports are AgentAdmissionEventSchema, AgentAttemptResetEventSchema, AgentCheckpointEventSchema,
AgentRunStateEventSchema, AgentRunOperationEventSchema, AgentTerminalEventSchema,
AgentTransientDeltaEventSchema,
AgentReasoningStartEventSchema, AgentReasoningDeltaEventSchema,
AgentReasoningEndEventSchema, AgentToolStatusEventSchema, AgentRuntimeEvent,
AgentRuntimeEventCursor, AgentRuntimeEventCursorSchema, AgentRuntimeCursorAdvance,
advanceAgentRuntimeEventCursor, agentDurableEventId, AgentRuntimeEventSink,
AgentRuntimeEventSinkConfig and createAgentRuntimeEventSink. Cursor gaps require a canonical
snapshot reload; the bounded sink isolates transport failure and supports a typed projection step.
Managed effects and operator telemetry additionally export AgentToolFenceConfig,
AgentToolFenceContext, AgentObservability, AgentRunEvent, AgentRunEventSchema,
AgentRunStartedEvent, AgentRunStartedEventSchema, AgentStepFinishedEvent,
AgentStepFinishedEventSchema, AgentRunTerminalEvent, AgentRunTerminalEventSchema,
AgentRunSinkConfig, AgentRunSinkDrop and AgentRunSinkError. A monotonic run fencingToken
may accompany checkpoint/terminal writes and tool context; internal causes are redacted unless an
operator-only observability sink explicitly opts in.
Completion and agent invocation receipts
createModelInvocationLedger constructs a ModelInvocationLedger from
ModelInvocationConfig: the existing store and model registry, a 32-byte payload
key, required host authorization, optional bounded payload size and onAttempt.
complete(input, context, signal?) executes only the supplied prompt, with no tools
or framework instructions; repeated keys return the existing invocation ID. It
resolves { invocationId, outcome, text?, receiptError? }: receiptError says a
receipt could not be written and never changes outcome or drops text.
read(input, context) returns a bounded event page shared by agent and completion;
readPayload(input, context) requires a separate authorization action to decrypt
one protected artifact. See the guide and migration example.
| Export | Kind | Purpose |
|---|---|---|
CompletionInvocationInputSchema / CompletionInvocationInput |
schema/type | strict prompt, model-attempt list, deadline, idempotency key and trace input |
ModelInvocationTraceSchema / ModelInvocationTrace |
schema/type | operation, purpose, project, parent trace and optional experiment/case/profile |
ModelInvocationRecordSchema / ModelInvocationRecord |
schema/type | discriminated invocation start/finish and per-attempt requested/sent/effective evidence |
ModelInvocationAttemptContext |
type | conversation, operation, invocation, attempt, step and optional agent run identity |
currentModelInvocationAttempt |
function | returns causal IDs inside the provider transport; undefined outside an invocation |
The runtime invocations option takes this ledger and a trace callback; it requires
the same store and preserves the existing tool loop. AgentRuntimeStore.appendEventOnce
is an optional atomic capability required by receipt admission, and
AgentRuntimeStore.findEventOnce reads the event it wrote by kind and key. Built-in
stores supply both; custom adapters must honor the once-only transaction contract.
A driver’s optional events.find(transaction, { conversationId, eventId }) makes
both one lookup instead of a scan of the conversation log.
stitchkit/agent-runtime/testing
Credential-free provider and concurrency fixtures for Bun and Node tests.
| Export | Kind | Summary |
|---|---|---|
createFaultProviderServer |
function | start an OpenAI-compatible local SSE endpoint with deterministic pass, connection-refused, timeout, stream-cut, HTTP, malformed JSON, slow-stream and missing-usage steps |
AgentFaultStepSchema / AgentFaultStep |
schema / type | strict fault-plan step vocabulary |
defineAgentFaultPlan |
function | validate a non-empty deterministic fault sequence |
createReplayAgentProvider |
function | serve a declared sequence of credential-free language-model fixtures per model ID |
createAgentRaceBarrier / AgentRaceBarrier |
function / type | named bounded deterministic concurrency barrier |
createAgentRaceTrace / AgentRaceTrace / AgentRaceTraceEntry |
function / type | record and assert exact event order without wall-clock guesses |
createAgentRaceDriver / AgentRaceDriver |
function / type | collect named barriers and release their teardown together |
runAgentStoreConformance |
function | reusable black-box duplicate/coalescing/stale/recovery contract for durable agent-store adapters |
AgentStoreConformanceConfig |
type | { createStore(context), cleanup?(context) } — the factory the contract runs against, plus a teardown that runs once whether the scenario passed or failed |
AgentStoreConformanceContext |
type | { conversationIds } — every conversation the scenario will mutate, handed over before the first mutation so an adapter can provision application-owned parent rows; a zero-argument factory stays valid |
inspectAgentRun takes (snapshot, runId) and returns completed(), calledTool(name),
notCalledTool(name) and toolSucceeded(name) assertions over durable evidence for
that exact run. Completion requires terminal reason success, not policy_stop or
provider_stop, and no pending approval. Successful tools require matching call/result IDs.
stitchkit/agent-runtime/harness
Server-only evolving facade over the canonical Agent runtime. It requires the optional ai peer
and introduces no store, queue or model-provider implementation of its own.
| Export | Kind | Summary |
|---|---|---|
createHeadlessAgentHarness |
function | compose one createAgentRuntime with caller-supplied model resolution, bounded resources, tools and prompt policy; adds canonical snapshot |
HeadlessAgentHarness / HeadlessAgentHarnessConfig |
type | runtime facade and injected ownership boundary |
HeadlessAgentModelResolver |
type | per-run preflight/resolve port returning the actual AgentResolvedModel |
AgentHarnessResourceSchema / AgentHarnessResource |
schema / type | strict instruction, skill or resource with name, text and provenance |
AgentHarnessResourceKindSchema / AgentHarnessResourceKind |
schema / type | closed instruction, skill or resource vocabulary |
AgentHarnessResourceResult |
type | one loader result containing resources and diagnostics |
AgentHarnessResourceDiagnosticSchema / AgentHarnessResourceDiagnostic |
schema / type | bounded caller evidence; observer failure is isolated |
AgentHarnessLimitsSchema / AgentHarnessLimits |
schema / type | resource count, total UTF-8 bytes and diagnostic ceilings |
AgentHarnessProfileEventSchema / AgentHarnessProfileEvent |
schema / type | actual model descriptor, non-content resource provenance and sorted direct tool identities applied to one run |
createAgentHarnessFileResources |
function | discover explicit instruction/skill/resource roots with symlink containment, bounded summaries and direct exact reads |
AgentHarnessFileRootSchema / AgentHarnessFileRoot |
schema / type | caller-owned absolute path, public root ID and resource kind |
AgentHarnessFileLimitsSchema / AgentHarnessFileLimits |
schema / type | file count, depth, per-file and aggregate byte ceilings |
AgentHarnessFileResources |
type | loader plus direct read_resource definition for lazy exact content |
createAgentHarnessControlServer |
function | transport-neutral correlated requests, observer attachments and exclusive controller leases |
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 |
AgentHarnessControlServerConfig |
type | explicit per-connection pending-event and server-wide concurrent attachment-snapshot bounds for failure-isolated control delivery |
AgentHarnessPendingApproval / AgentHarnessApprovalDecision |
type | exact durable pending request and allow/deny successor input |
AgentHarnessApprovalRequest |
type | the pending request as a response-time policy sees it: approval id, call id, tool name and input |
AgentHarnessApprovalAuthorization / AgentHarnessApprovalAuthorizationResult |
type | response-time policy input (responder, conversation, request, proposed decision) and its allowed / rejected result |
AgentHarnessApprovalRejectedError |
class | thrown when the response policy refuses a responder; the pending request is left answerable |
Resources default to at most 64 entries, 1 MiB of total UTF-8 text and 128 diagnostics. Duplicate names and exceeded bounds fail before the provider step. Recovery remains the underlying runtime’s explicit policy; use the Bun or Node SQLite leaf for durable reopen.
stitchkit/agent-runtime/coding-tools
Server-only evolving, peer-free direct runtime tools. createAgentCodingTools(config) returns
read_file, write_file, edit_file, list_directory, glob, search_files, optional
run_command and, when an
artifact store is supplied, read_output.
| Export | Kind | Summary |
|---|---|---|
createAgentCodingTools |
function | construct direct host-authorized bounded file, listing, glob, search, exact-snippet edit, shell and artifact runtime-tool definitions; edit_file inserts newText literally in both single and replaceAll modes; every ordinary refusal is a typed code with an instructive hint, and filesystem operations use Linux /proc/self/fd or the packaged macOS Node-API backend and otherwise fail closed |
AGENT_CODING_TOOL_NAMES |
const | the mounted tool names — read_file, write_file, edit_file, list_directory, glob, search_files, run_command, read_output |
AgentCodingToolDefinition |
type | peer-free structural direct-tool shape accepted by the canonical runtime-tool surface |
AgentCodingToolConfig |
type | absolute root, required operation authorization, optional async/sync authorizePath({ path }) shared by direct file effects and discovery, finite executable alias map, exact child environment and optional limits |
AgentCodingToolAuthorizationSchema / AgentCodingToolAuthorization |
schema / type | discriminated read/write/search/patch/shell/artifact decision presented to host policy before effect |
AgentCodingToolPathAuthorizationSchema / AgentCodingToolPathAuthorization |
schema / type | strict workspace-relative path presented to the shared path policy before disclosure, opening or mutation |
AgentCodingToolLimitsSchema / AgentCodingToolLimits |
schema / type | explicit path/read/write/argument-count/argument-byte/output/artifact/timeout/termination-grace ceilings |
AgentCodingArtifactStore |
type | host-owned opaque artifact write and bounded read boundary |
FileReadInputSchema / FileReadOutputSchema |
schema | bounded strict-UTF-8 byte slice; offsets must align with UTF-8 code-point boundaries |
FileWriteInputSchema / FileWriteOutputSchema |
schema | create-only by default or explicit atomic replacement; symlink targets fail closed |
createShellInputSchema / ShellOutputSchema |
schema | enumerated executable alias plus arguments and concrete relative cwd; explicit exited/timeout/output-limit/cancelled outcome |
File/search operations pin directory descriptors across authorization and the actual effect; resource discovery uses the same ancestor-safe traversal. This closes parent rename/symlink races without claiming an executable sandbox. The default ceilings are 4,096 path bytes, 256 KiB read/write/output, 128 shell arguments, 64 KiB of aggregate argument text, 4 MiB per artifact and 30 seconds. The root is a path-resolution boundary, not an OS sandbox; executable behavior, process isolation, credentials and external-effect idempotency remain host responsibilities.
When authorizePath denies a path, direct read/write/edit returns FORBIDDEN, while
list_directory, glob and search_files omit it. Denial is recursive: direct access and
discovery base paths are checked against . and every ancestor, outermost first and segment-wise,
so denying credentials denies credentials/token.txt but not credentials-backup. Directory
admission happens before descent and file admission before opening; search_files.include is also
applied before content is read. Requested paths must use / — a backslash is refused, because the
containment walk reads it as a separator while a callback would read it as one name.
Absolute paths remain refused; an absolute path inside the canonical root carries an exact
workspace-relative recoveryPath, while one outside the root carries no replacement. The
search_files.include schema states that its pattern is anchored to the whole workspace-relative
path, * does not cross /, and **/ is required for nested matches. scannedFiles is the
post-include/post-authorization comparison count. A hint is added only when the filter itself
produced the zero — it rejected every file the scan reached — never when there was nothing to
reject or the host refused it.
run_command is intentionally outside this guarantee because an executable needs process isolation,
not path filtering, to constrain its filesystem access. → ADR 0172.
stitchkit/agent-runtime/browser
Browser-safe canonical agent data. It re-exports the run, message, part, usage,
terminal and provider-envelope schemas/types listed under
stitchkit/agent-runtime, together with all runtime delivery event schemas (durable and transient,
including AgentAttemptResetEventSchema for attempt-reset),
AgentRuntimeEventCursorSchema, advanceAgentRuntimeEventCursor,
AgentControlRequestSchema / AgentControlRequest, AgentControlResponseSchema /
AgentControlResponse, AgentControlDeliverySchema / AgentControlDelivery,
AgentControlErrorCodeSchema / AgentControlErrorCode (the one vocabulary of every control
error code: FORBIDDEN, CONNECTION_CLOSED, REQUEST_CAPACITY, ATTACHMENT_CAPACITY,
LEASE_CONFLICT, EVENT_OVERFLOW and the rest), AgentMultiSessionCursorSchema /
AgentMultiSessionCursor, AgentConversationView, AgentControlView,
advanceAgentMultiSessionCursor, createAgentControlView, reduceAgentControlSnapshot,
reduceAgentControlEvent and
agentDurableEventId. It imports no model provider, executor, store, event sink
or Node context module.
Use this entrypoint from client components and shared DTO packages. The full
stitchkit/agent-runtime entrypoint remains server-only.
Browser control composition
AgentBrowserRequestSchema / AgentBrowserRequest derive from the trusted control
protocol but exclude runtime context. Submit permits only strict text/file parts;
file ownership and metadata policy are checked by server authorization. The shared
agentControlRealtimeContract owns agent:control acknowledgements and agent:delivery.
createAgentController / AgentControllerConfig take an existing Stitchkit
realtime transport, conversationId, access (observe or control), optional
timeoutMs (10000), maxBufferedEvents (256), maxBufferedBytes (1048576) and
maxPendingRequests (32). All bounds are positive safe integers. One controller owns one
attachment per conversation on that transport; share the controller between views.
AgentController exposes stable subscribe, getSnapshot, request(command) and async
close. AgentBrowserCommand uses the canonical operations, without request/conversation identity;
submit requires a caller-owned idempotency key. Unknown-outcome mutations are never
replayed automatically. AgentControllerState distinguishes connecting, ready,
disconnected, error and closed and retains the canonical full view plus safe error
code/message. Errors in automatic attach/refresh appear there, and so does an
access-denied delivery: the server detached the conversation, the state becomes
error with code FORBIDDEN, and nothing arrives until the controller attaches again.
Reconnect attaches again and reads a snapshot; requests of the previous connection are
rejected at once and release their capacity, snapshot gaps coalesce, stale generations
cannot overwrite state, and buffers/queues are bounded. Overflow or failed refresh is visible and requires
explicit recovery. Closing detaches without closing the shared transport or remote run.
See agent composition for a complete wiring example.
stitchkit/agent-runtime/openrouter
| Export | Kind | Summary |
|---|---|---|
openRouterProvider |
function | isolated @openrouter/ai-sdk-provider language-model factory |
openRouterModelCatalog |
function | complete tool-capable text catalog plus independent weekly popularity and available benchmark observations |
OpenRouterProviderSettings |
type | official provider settings accepted by the factory |
OpenRouterModelCatalogOptions / OpenRouterCatalogFetch |
type | credential, timeout, clock and injected fetch boundary for catalog loading |
stitchkit/agent-runtime/sqlite/bun
Bun built-in SQLite persistence. The entrypoint imports bun:sqlite and is not
loaded by the neutral, browser or Node runtime surfaces.
| Export | Kind | Summary |
|---|---|---|
createBunSqliteAgentRuntimeStore |
function | open an owned Bun SQLite connection, initialize/validate schema v2, migrate v1 transactionally and return { store, conversations, database, transaction, close } |
BunSqliteAgentRuntimeStoreConfig |
type | database filename plus optional create and initialization policies |
createSqliteAgentRuntimeStore |
function | build the normalized store over an injected synchronous SQLite boundary |
initializeAgentRuntimeSqlite |
function | initialize or validate only Stitchkit’s namespaced SQLite schema |
SqliteDatabase / SqliteStatement / SqliteValue |
type | minimal runtime-neutral synchronous SQLite boundary |
SqliteAgentRuntimeStore / SqliteAgentRuntimeStoreConfig / SqliteStoreTransaction |
type | durable store handle — store, conversations, database, transaction, close — owned connection lifecycle, initialization policy, and the one write transaction the SQLite companions share |
stitchkit-tui
Separate optional evolving Bun/OpenTUI package over a caller-composed headless harness.
| Export | Kind | Summary |
|---|---|---|
defineAgentTui |
function | typed config for title/theme/status rows, model catalog, context, commands, runtime bundle and optional host-evidenced recovery policy; the default never requeues acquired effects |
runAgentTui |
function | start one fresh durable conversation and terminal controller, recover durable work and publish its authenticated local session; initialConversationId is an explicit resume override |
defineTuiCommand / resolveTuiCommand |
function | typed composable slash-command registry; unknown slash input remains an ordinary model prompt |
createAgentTuiController |
function | single admission, selection, approval, interruption and conversation-switch owner over the harness |
startAgentTuiSessionHost / createAgentTuiClient |
function | authenticated mode-0600 Unix-socket host/client for status, submit and interrupt through that controller |
listAgentTuiSessions |
function | discover live local terminal session IDs and their current conversation |
createAgentTuiComposer / navigateAgentTuiHistory |
function | multiline draft and reversible prompt-history state |
defaultAgentTuiStatusLine / AgentTuiStatusLineFormatter |
function / type | terminal-native default rows and a host formatter over model capacity, durable snapshot, activity, workspace and local identities; statusLine: false hides the rows |
createAgentTuiDiagnosticRecorder / AgentTuiDiagnosticEventSchema |
function / schema | bounded per-session metadata journal that rejects prompt, reasoning, tool-input and provider-cause payloads before disk admission |
The stitchkit-agent binary loads stitchkit.agent.ts by default and also exposes sessions,
status, send and interrupt. --workspace addresses a host outside the caller’s cwd,
send --idempotency-key accepts caller-owned retry identity, and interrupt defaults to the
active run returned by status. Session descriptors and sockets are local control credentials,
not a remote API.
Interactive /resume and /sessions open the durable conversation picker. /clear creates a new
conversation and keeps the previous one available there; it is not a viewport-only operation.
The slash palette owns its highlighted selection: Up/Down move it, Tab completes it, Enter runs
the exact command and Escape dismisses it. Partial input is never submitted while the palette is
active; unknown slash text with no match remains an ordinary model prompt.
stitchkit-tui/core
Renderer-neutral state only. This entrypoint imports neither React/OpenTUI nor the agent runtime.
| Export | Kind | Summary |
|---|---|---|
createTerminalCollection / reduceTerminalCollection |
function | identity-stable live collection selection, reconciliation, windowing and resize |
createTerminalFeedViewport / reduceTerminalFeedViewport |
function | generic follow-tail, history anchoring, unseen and bounded visible-range state |
createTerminalPaneState / reduceTerminalPaneState |
function | bounded split-pane focus, resize and single-pane collapse |
createTerminalCommandPalette / terminalCommandMatches |
function | bounded command filtering and keyboard selection over a collision-validated registry |
resolveExactTerminalCommand / validateTerminalCommands |
function | exact dispatch and fail-closed name/alias validation |
createTerminalOperationState / reduceTerminalOperationState |
function | confirmation and single-pending-operation lifecycle |
stitchkit/agent-runtime/sqlite/node
Node 22.5+ built-in SQLite persistence. It shares the schema and semantics of
the Bun leaf but imports only node:sqlite.
| Export | Kind | Summary |
|---|---|---|
createNodeSqliteAgentRuntimeStore |
function | open an owned Node DatabaseSync, initialize/validate schema v2, migrate v1 transactionally and return { store, conversations, database, transaction, close } |
NodeSqliteAgentRuntimeStoreConfig |
type | database filename plus optional read-only and initialization policies; read-only requires an initialized schema |
createSqliteAgentRuntimeStore / initializeAgentRuntimeSqlite |
function | shared normalized adapter and namespaced schema lifecycle |
SqliteDatabase / SqliteStatement / SqliteValue |
type | minimal runtime-neutral synchronous SQLite boundary |
SqliteAgentRuntimeStore / SqliteAgentRuntimeStoreConfig / SqliteStoreTransaction |
type | durable store handle — store, conversations, database, transaction, close — owned connection lifecycle, initialization policy, and the one write transaction the SQLite companions share |
stitchkit/observability
Server-only. The audit layer one level above the raw hooks — W3C trace context,
an AsyncLocalStorage request context, payload sanitisation and a normalised
audit event. See the Observability guide.
Events
| Export | Kind | Summary |
|---|---|---|
createObservability |
function | configure framework-owned request completion and canonical tool event sinks — guide |
auditChanges |
function | the sink filter most projects write themselves — drops GET/HEAD/OPTIONS, keeps 401/403 whatever the verb, keeps an unrecognised verb |
createSpooledSink / SpooledSink / SpooledSinkConfig / SpoolRecovery |
function / types | spool the row to an append-only file before the store and replay what a previous process left undelivered — at least once, keyed on spanId |
createDimensionsProjector / DimensionsProjector / DimensionsProjectorConfig / ProjectedDimensions |
function / type | typed request/result/error attribution projected into the existing request context |
DimensionCollision / SetRequestDimensionsOptions |
type | explicit overwrite, preserve or error policy for dimension keys |
createBoundedLogger |
function | decorate a StitchLogger with request context, shared sanitisation, redaction and total bounds |
DEFAULT_REDACT_PATHS |
constant | baseline credential/token paths added to the sanitizer’s sensitive-key policy |
createJsonLogger |
function | the process journal: one JSON line per call in pino’s shape (numeric level, epoch time, msg) on standard output, through createBoundedLogger — an Error in any field keeps name, message, stack and cause; secrets masked; level threshold, static fields, injectable write |
JsonLoggerOptions / JsonLogLevel / JSON_LOG_LEVELS |
type / constant | the bounded-logger options plus level, fields, write, now; pino’s numbers debug 20 … error 50, which a line reader matches on; sensitiveValues masks exact secrets in every string |
secretValuesFromEnv / SecretValuesOptions |
function / type | every secret an environment holds, for sensitiveValues: variables named as a token, secret, key, password or credential, the password and secret query values in any URL variable, each URL-encoded too, longest first; values under minLength (8) skipped |
BoundedLoggerBounds / BoundedLoggerOptions |
type | per-value and total record ceilings (stringLengthByKey raises the string bound for named keys such as stack) plus sink/redaction configuration |
RequestEvent |
type | the normalised audit event handed to the sink; opt-in HTTP cancellation rows carry outcome: 'cancelled' |
runUnitOfWork / RunUnitOfWorkOptions |
function / type | run work that did not arrive over a transport — an agent loop, a scheduled broadcast — inside one context, with the same completion record a request gets |
RequestContextKind |
type | 'request' | 'job' — what the row describes, written on every event so a filter never has to read it off an absent method |
ObservabilityConfig |
type | independent request and tool sink configuration |
Observability |
type | { request?, toolCall, getStatus(), flush(bound?): Promise<boolean>, close(bound?) } with bounded sink lifecycle |
ObservabilityDrainBound |
type | timeoutMs and/or signal limiting how long flush/close wait; the wait ends, outstanding writes do not |
ObservabilitySinkStatus |
type | immutable counters for one bounded request/tool sink |
ObservabilityStatus |
type | per-surface plus aggregate operational snapshot |
ObservabilityDrainReport |
type | final closed/drained snapshot, durationMs (the shared drain’s age, not this call’s wait), and drained — read from the counters, false only when total.pending + total.preparing is nonzero |
ObservabilitySinkStatusSchema / ObservabilityStatusSchema / ObservabilityDrainReportSchema |
schema | runtime schemas for status/report integration boundaries |
RequestEventSinkConfig |
type | write, filter/sanitisation, maxPending, onSinkError and onDrop |
RequestObservabilityConfig |
type | request sink plus opt-in payload capture (payloadMaxBytes bounds the body read, payloadTruncated marks a cut one) and default-off includeCancelled rows |
SinkDropReason |
type | 'capacity' | 'closed' |
SinkError |
type | isolated sink/projection failure and optional event |
SinkDrop |
type | rejected event, reason and current pending count |
HttpRequestCompletion |
type | the single framework-owned HTTP outcome, including optional neutral cancellation, projected to logging and request events |
HttpRequestObserver |
type | server-facing projection consumed by HandlerConfig.observability |
Request context
| Export | Kind | Summary |
|---|---|---|
WrapRequestContextOptions |
type | options for wrapInRequestContext |
wrapInRequestContext |
function | run a fetch handler inside a request context — guide |
getRequestContext |
function | the active request context |
getTraceId |
function | the active trace id — pass as traceId to createServer |
getUserId |
function | the active user id, once auth has resolved it |
setRequestUser |
function | attach the resolved user to the active context |
setRequestEndpoint |
function | attach the resolved endpoint identity to the active context |
setRequestDimensions |
function | attach custom audit dimensions to the active context |
setRequestError |
function | record the error outcome on the active context |
runWithRequestContext |
function | run a function inside a given context |
RequestContext |
type | the per-request record |
Trace context
| Export | Kind | Summary |
|---|---|---|
resolveTraceContext |
function | the trace for a request — traceparent continued or fresh |
resolvePropagationContext |
function | continue bounded MCP/W3C propagation metadata with optional ambient fallback |
parseTraceparent |
function | parse a traceparent header |
formatTraceparent |
function | render a traceparent header value |
createTraceContext |
function | a fresh root trace |
childSpan |
function | a child span of a parent trace |
TraceContext |
type | { traceId, spanId, parentSpanId?, tracestate?, baggage? } |
Sanitisation
| Export | Kind | Summary |
|---|---|---|
sanitizePayload |
function | redact secrets and cap size — guide |
redact |
function | mask secret-named keys and secrets recognised by shape in every string — the secret half of a bot token, a password in an address, a query parameter named as a secret; drop binary blobs; an error keeps its own fields (error_code, parameters), a class instance on one is named, not written |
truncatePreview |
function | cap a value by serialised size |
measureSize |
function | item count + byte size of a result |
JsonValue |
type | a JSON-serialisable value |
SanitizeOptions |
type | tuning for redact / sanitizePayload — maxStringLengthByKey bounds a named key wherever it sits without changing the record-wide bound |
SizeMeasure |
type | the result of measureSize |
stitchkit/remote
Peer-free remote implementation boundary. Importing it does not load the MCP
SDK, ai, or other optional tool peers, so it is safe in a thin CLI bundle.
| Export | Kind | Summary |
|---|---|---|
implementRemote |
function | bind a contract to a remote HTTP API — guide |
ImplementRemoteOptions |
type | optional argument-rewrite hook for implementRemote |
stitchkit/tools
Server-only. Turns contracts into MCP and AI-agent tools. MCP server surfaces
need the @modelcontextprotocol/server v2 peer; MCP hosts/tests use the separate
@modelcontextprotocol/client package. Agent surfaces need the ai peer.
Framework-owned MCP tools advertise the exact declared output schema and return
the validated value unchanged as structuredContent, including arrays, scalars
and null. Tools without an output contract advertise and return no structured
payload.
| Export | Kind | Summary |
|---|---|---|
createMcpHandler |
function | a stateless dual-era Streamable-HTTP MCP handler — guide |
createMcpHttpRoute |
function | framework-owned RawRoute adapter for an MCP HTTP handler |
createStdioMcpServer |
function | a complete stdio MCP server — guide |
bindStdioProcessSignals |
function | explicitly bind OS signals to one close-only stdio handle — guide |
buildMcpServer |
function | build an McpServer from contract/runtime surfaces; no-auth configs omit the second argument |
mountMcp |
function | add contract tools to an existing McpServer — guide |
mountAgent |
function | a Vercel AI SDK ToolSet from a service; failed executions reject through the SDK tool-error channel with a safe typed envelope, while successful output is never classified by field name — guide |
defineRuntimeTool |
function | define one validated pathless operation for explicit MCP, Agent and/or CLI surfaces — guide |
createRuntimeToolFactory |
function | bind shared identity and Zod-validated per-call context for runtime tools — guide |
createToolInvoker |
function | compile an exposure-aware in-process dispatcher over the canonical tool runner; use peer-free stitchkit/tools/invoker, or the full stitchkit/tools adapter barrel — guide |
createToolkit |
function | context-typed tool mounts — guide |
mountViewFile |
function | a native multimodal “view file” MCP tool |
resolveMedia |
function | resolve a media reference for a tool result |
validateMcpSchemas |
function | object-shaped assertion over the exact advertised schema surface — compatibility, typed properties and portable formats (guide) |
listToolNames |
function | every contract/runtime tool name with origin, identity and transports — for stable snapshots — guide |
listContractToolNames |
function | the same listing straight from contracts — no handlers or stub services needed |
describeToolCatalog |
function | inspect the exact model-facing names, source identities, schema byte sizes and deferred state; an explicit total byte budget fails closed |
ToolCatalogConfig / ToolCatalogEntry |
type | catalog source, transport, optional explicit schema budget and one inspectable result row |
McpHandlerConfig |
type | server surface plus stateless HTTP transport config |
McpHttpConfig |
type | HTTP auth, protected-resource, legacy-era and security options |
McpHttpHandler |
type | framework-owned { fetch(request), close() } lifecycle |
McpHttpSecurityConfig |
type | Fetch-boundary Host and Origin allowlists |
McpLegacyPolicy |
type | 'serve' | 'reject' protocol-era compatibility policy |
McpStdioHandle |
type | closeable official stdio transport handle |
StdioMcpServerConfig |
type | config for createStdioMcpServer |
StdioCloseTarget |
type | minimal close-only target accepted by bindStdioProcessSignals |
StdioProcessSignalsOptions |
type | signal source, close callbacks and phased error reporting |
StdioProcessSignalsBinding |
type | close-only signal binding with observed promise and listener close() |
StdioProcessSignalsErrorPhase |
type | 'prepare' | 'close' | 'complete' reporting phase |
McpServerBuildConfig |
type | shared config for buildMcpServer |
McpServerSharedConfig |
type | transport-neutral options shared by direct and finite surface configs |
McpServer |
type | official split-SDK server instance accepted by raw extension points |
DirectMcpSurfaceConfig |
type | static or identity-dynamic services / runtimeTools source |
FiniteMcpSurfaceConfig |
type | bounded surfaces registry plus typed selector |
McpSurfaceDefinition |
type | one immutable { services, runtimeTools } MCP surface |
McpSurfaceRegistry |
type | finite keyed surface registry for eager preparation |
StdioAuthConfig |
type | startup identity composed into StdioMcpServerConfig |
McpMountConfig |
type | config for mountMcp |
McpSchemaValidationConfig |
type | shared { policy, requireTypedProperties, allowUntyped, requirePortableFormats, allowFormats } profile |
ValidateMcpSchemasConfig |
type | standalone validation profile plus services, extend, flattening and logger |
RuntimeToolDefinition |
type | heterogeneous registration of pathless operations in runtimeTools: [...]; an inline handler is contextually typed by the parsed object, a definition constructed with its own schema registers unchanged, and the runner validates input before the handler |
RuntimeToolDefinitionBase |
type | common name, identity, input, exposure and MCP metadata fields |
RuntimeToolDefinitionWithOutput |
type | the one neutral construction: identity, schemas and a handler typed from them; the fourth type argument names the adapter’s present extension (RuntimeToolPresenters<…> here, RuntimeMcpToolPresenters<…> on stitchkit/tools/mcp, none by default) |
RuntimeToolDefinitionWithoutOutput |
type | the same construction with a void handler and no presentation callbacks |
RuntimeToolFactory |
type | identity/context-bound runtime-tool definition factory |
RuntimeToolFactoryConfig |
type | factory service identity and context schema |
RuntimeToolFactoryDefinitionWithOutput |
type | factory-authored runtime tool with a validated output schema |
RuntimeToolFactoryDefinitionWithoutOutput |
type | factory-authored void runtime tool without presenters |
RuntimeToolFactoryHandlerContext |
type | parsed factory context plus parsed tool input |
RuntimeToolFactoryIdentityFields |
type | per-tool action, semantic method and optional identity metadata |
RuntimeToolIdentity |
type | { serviceName, action, scope?, method, meta? } for runtime lifecycle/audit |
RuntimeToolHandlerContext |
type | runtime context with the definition’s parsed input |
RuntimeToolOutput |
type | output inferred from a runtime tool’s optional Zod schema |
RuntimeToolPresenters |
type | optional MCP and AI SDK toModelOutput presentation callbacks |
RuntimeMcpPresentation |
type | MCP content/metadata result without framework-owned structuredContent or isError |
RuntimeMcpInput |
type | typed accepted multi-round input for an opted-in runtime tool |
OAuthClientRegistrationConfig |
type | deterministic pre-registered → CIMD → explicit-DCR client resolution |
CimdClientMetadata |
type | validated Client ID Metadata Document |
CimdClientMetadataFetcher |
type | injectable secure network boundary for metadata loading |
CimdFetchResponse |
type | bounded metadata fetch result passed across the injectable network boundary |
CimdFetchPolicy |
type | CIMD timeout, redirect and size limits |
CimdCachePolicy |
type | bounded HTTP-aware cache policy: separate positive/negative pools (maxEntries), per-client and server-wide resolution rate limits (maxResolutionsPerClient / maxResolutions per resolutionWindowMs) |
CimdCacheEvent |
type | observable CIMD cache hit, miss, revalidation and eviction event |
createSecureClientMetadataFetcher |
function | production HTTPS, DNS/IP-pinned CIMD fetcher |
RuntimeAgentModelOutput |
type | AI SDK model-facing text/JSON/content output returned by present.agent |
AgentMountConfig |
type | config for mountAgent |
AgentToolRegistry / AgentToolRegistryBuilder / AgentToolRegistryInput |
type | the composed runtime surface and its builder: declared defaults, replace/disable by name, and the exact { tools, names } a mount receives |
defineToolRegistry |
function | compose runtime tools over one declared default set; an unknown replace/disable name is refused instead of silently leaving the default in place |
AgentContext |
type | the context merged into agent tool handlers |
Toolkit |
type | the context-pinned tool surface from createToolkit |
ToolExtend |
type | extra-args extension for mountMcp / mountAgent |
ToolLifecycle |
type | beforeHandle / afterHandle gate for tool calls — guide |
ToolExecutionControlReason |
type | internal managed-execution stop reason: stale run or requested interruption |
ToolExecutionControlError |
class | control-flow error used to unwind a superseded managed tool call without presenting it as a model-facing tool failure |
isToolExecutionControlError |
function | narrow an unknown thrown value to the managed execution control error |
ToolOperation |
type | executable path-free operation shape shared by contract and framework-native runners |
ToolCallHooks |
type | object-shaped beforeToolCall / afterToolCall / onToolError observability hooks; the raw thrown value reaches the last two as error (guide) |
BeforeToolCallOptions |
type | { toolName, args, context, endpoint } passed before execution |
AfterToolCallOptions |
type | completed call options plus { result, durationMs, error? } |
ToolErrorOptions |
type | { toolName, error, context, endpoint } for a thrown handler-path value |
ErrorHintFn |
type | (toolName, errorCode) => string | null — a per-tool recovery hint, shared by every mount |
ToolResult |
type | the result of one tool call |
ToolInvoker |
type | immutable compiled dispatcher (names, envelope invoke, throwing invokeOrThrow) |
ToolInvokerConfig |
type | compile-time exposure, extension and presentation options |
ToolInvocationOptions |
type | per-call source, context, lifecycle, hooks and output-strip reporter |
ToolCallContext |
type | the context every tool hook receives — { source, mcp? } plus whatever the mount’s context added |
ViewFileOptions |
type | shared URL/managed-file-boundary policy for defineViewFileTool, mountViewFile and resolveMedia |
ViewFileOutput |
type | neutral managed batch result with multimodal content and per-item errors |
ViewFileInputSchema |
constant | one media path/URL or an array of at most 20; rejects a JSON array written as text, including in array items, before IO |
ViewFileOutputSchema |
constant | Zod schema for the neutral managed view-file batch result |
ViewFileErrorSchema |
constant | Zod schema for one structured per-item view failure |
McpAnnotations |
type | MCP annotations on a media result |
McpAnnotationsSchema |
constant | Zod schema for MCP media annotations |
McpMediaContentSchema |
constant | Zod schema for text/image/audio media content |
CollectToolsConfig |
type | options for collectTools |
findUntypedProperties |
function | every property in a JSON Schema with no type/enum/$ref — what a model is shown and cannot obey (guide) |
UntypedProperty |
type | one such property — { path, description? } |
findNonPortableFormats |
function | deep finder for formats outside the portable MCP/AJV baseline |
NonPortableFormat |
type | one { path, format } portability finding |
PORTABLE_JSON_SCHEMA_FORMATS |
constant | portable-format baseline used by MCP validation |
ToolNameEntry |
type | one listToolNames row — { kind, name, service, method, transports } |
IncompatibleSchemaPolicy |
type | 'throw' | 'skip' | 'warn' |
McpMediaContent |
type | a multimodal MCP content item |
Native tools
Generic host-supplied operations — managed definitions for the canonical runtime-tool runner, plus deliberate raw MCP adapters over the same mechanics.
| Export | Kind | Summary |
|---|---|---|
defineDownloadTool |
function | define a guarded, size-capped managed download for MCP/Agent runtimeTools |
defineUploadTool |
function | define a typed managed local-file upload for MCP/Agent runtimeTools |
defineWaitTool |
function | define a typed, cancellable managed polling operation for MCP/Agent runtimeTools |
defineViewFileTool |
function | define a guarded, batch-capped managed multimodal operation for MCP/Agent runtimeTools |
DefineDownloadToolConfig |
type | Zod input, stable identity, URL resolver, storage policy and presenters for defineDownloadTool |
DefineUploadToolConfig |
type | stable identity, typed output, upload callback and presenters for defineUploadTool |
DefineWaitToolConfig |
type | Zod input/state, identity, poll/done/timeout policy and presenters for defineWaitTool |
DefineViewFileToolConfig |
type | identity, media security policy and optional presenters for defineViewFileTool |
ManagedNativeToolConfig |
type | shared name, description, identity, exposure and annotations for managed native factories |
NativeToolIdentity |
type | pathless service/action/scope/meta identity; semantic method is factory-owned |
ManagedWaitRender |
type | optional managed wait terminal text and failure classification |
UploadToolInputSchema |
constant | fixed { path: string } input schema for defineUploadTool |
defineAsyncOperation |
function | runtime-only start/status/wait plus configured cancel/result/artifacts definitions; see the durable application-owned recipe |
defineAsyncOperationContract |
function | define one canonical Zod-first HTTP contract for start/status/wait plus optional capabilities; execution and recovery remain application-owned |
bindContractAsyncOperation |
function | bind literal methods from an existing contract without creating another HTTP surface |
createAsyncOperationSnapshotSchema |
function | canonical pending/running/succeeded/failed/cancelled Zod snapshot |
AsyncOperationSnapshotSchema |
type | the snapshot union createAsyncOperationSnapshotSchema returns when no progress schema is configured |
AsyncOperationSnapshotSchemaWithProgress |
type | the same union with the configured progress schema optional on every phase |
AsyncOperationCancelResultSchema |
constant | validated accepted/already_terminal/rejected cancellation result |
AsyncOperationCancelResult |
type | validated cancel capability result |
AsyncOperationCancelCapability |
type | optional typed domain cancellation callback |
AsyncOperationCapability |
type | generated capability-name union |
AsyncOperationStartDefinition / AsyncOperationFollowDefinition |
type | generated runtime definition types |
AsyncOperationIdentity |
type | shared service/action/scope/meta identity for an operation |
AsyncOperationOutputCapability |
type | optional result/artifact schema plus handler |
RuntimeAsyncOperationConfig |
type | runtime-only descriptor configuration |
RuntimeAsyncOperation |
type | inferred generated definitions and schemas |
AsyncOperationContractConfig |
type | canonical contract config where start returns the operation id; optional expose names the transports per capability, because this contract is built inside the framework and never passes through a consumer’s toolExposure: 'explicit' factory |
AsyncOperationContractWithStartOutputConfig |
type | canonical contract config with an application start envelope and typed id extractor |
DefinedAsyncOperationContract |
type | generated contract, capability keys, schemas and parsed adapters |
ContractAsyncOperationConfig |
type | literal contract method binding and handlers |
AdaptedContractAsyncOperationConfig |
type | existing-contract binding with explicit id and per-capability input adapters |
BoundAdaptedContractAsyncOperation |
type | inferred adapted binding with parsed id/input projectors |
AdaptedContractAsyncOperationStartKey |
type | existing-contract keys with a declared start output |
AdaptedContractAsyncOperationFollowKey |
type | existing-contract keys with both input and output schemas |
AdaptedContractAsyncOperationWaitKey |
type | adapted follow-up keys whose output matches the selected status snapshot |
ContractAsyncOperationInputAdapters |
type | guaranteed direct-binding status/wait input adapters plus configured optional capabilities |
ContractAsyncOperationKeys |
type | literal method-key union of a bound contract |
ContractAsyncOperationStartKey |
type | direct-binding start keys whose declared ID schema has stable input/output |
ContractAsyncOperationFollowKey |
type | contract keys whose input schema type matches the selected start output |
ContractAsyncOperationWaitKey |
type | follow-up keys whose output schema type also matches the selected status output |
composeToolLifecycle |
function | ordered composition of tool before/after phases |
mountDownload |
function | raw MCP “download a URL to disk” adapter (SSRF-guarded, size-capped) |
mountUpload |
function | raw MCP “upload a local file” adapter |
mountWait |
function | raw MCP generic --wait-style polling adapter |
DownloadToolConfig |
type | config for mountDownload |
UploadToolConfig |
type | config for mountUpload |
WaitToolConfig |
type | config for mountWait |
OAuth 2.1 provider
A native remote-connector auth surface for MCP — guide.
| Export | Kind | Summary |
|---|---|---|
mountOAuthProvider |
function | the OAuth 2.1 provider routes (DCR, PKCE, token) |
oauthProtectedResourceRoute |
function | the RFC 9728 protected-resource-metadata route |
protectedResourceMetadataUrl |
function | build the metadata URL for a resource |
wwwAuthenticateHeader |
function | build the WWW-Authenticate challenge header |
PROTECTED_RESOURCE_PATH |
const | the well-known metadata path |
OAuthProviderConfig |
type | config for mountOAuthProvider; maxRequestBodyBytes bounds the /token and /register bodies (64 KiB by default) |
ProtectedResourceConfig |
type | config for oauthProtectedResourceRoute |
ApplicationType |
type | DCR application_type — 'native' (loopback allowed) | 'web' (https only) |
AuthCodeData |
type | a stored authorization-code record |
AuthRequest |
type | a parsed authorization request |
ClientMetadata |
type | dynamic-client-registration metadata |
RefreshData |
type | a stored refresh-token record |
RegisteredClient |
type | a registered OAuth client |
Durable tool bodies
A mounted tool body can be made restartable without adopting agent-runtime: declare a
factory and step / sleep / waitFor appear in the handler context, backed by whatever
ledger the application already has.
mountAgent(services, { durability: (toolCallId) => myLedgerFor(toolCallId) });
| Export | Kind | Summary |
|---|---|---|
ToolDurability |
type | the port a tool body needs: step, sleep, waitFor |
ToolDurabilityFactory |
type | (toolCallId, signal) => ToolDurability, called once per call |
DurableJsonValue |
type | what a durable step result may hold — a record is read back in another process, so it must be JSON |
createLocalStepDurability |
function | the durability engine — replay, absolute deadlines, park/deliver — over a two-method ledger the application owns |
StepDurabilityLedger |
type | the two methods an engine needs: appendEvent, readEvents |
LocalStepDurability |
type | what the engine returns; satisfies ToolDurability and adds deliver, effect and record introspection for the ledger’s owner |
EffectHandlers / EffectOutcome / EffectRunOptions |
type | effect(name, { run, reconcile }, { signal, reconcileTimeoutMs }): the intent is recorded before run, an intent without an outcome is settled by reconcile and never run again; accepted with the proof or a recorded, final uncertain → ADR 0200 |
EffectUnresolvedError |
class | an effect whose outcome this call could not settle — run or reconcile threw, reconcile overran, the proof was not recordable; the intent stands and the next call reconciles |
LocalStepDurabilityOptions |
type | { store, conversationId, runId, signal?, subscribe?, clock? } |
AppendAgentStoreEvent / ReadAgentStoreEvents / AgentStoreEventEnvelope / AgentStoreEventPage |
type | the ledger’s row shapes, re-exported so a ledger is typed from the entrypoint that consumes it |
AgentToolError |
class | the model-safe envelope a failed agent tool throws |
isAgentToolError |
function | brand check for it — a consumer running its own loop no longer parses the message |
Catalog stamp
Every advertised tool and every tool result carries the fingerprint of the catalog it came
from, so a long-lived consumer can see that its own copy is stale without making a
request for it. createMcpHandler is stateless by construction and therefore has no
retained session to push notifications/tools/list_changed down; the stamp needs none.
Store the stamp beside the tools when you list them, compare it against the one on every result, and re-list when they differ — including on a refusal, which is exactly when a stale catalog is the likeliest explanation and the least visible one. The server side needs no wiring: every mount stamps what it advertises.
| Export | Kind | Summary |
|---|---|---|
readMcpCatalogStamp |
function | read a peer’s stamp out of _meta, or null when there is none |
mcpCatalogMeta |
function | the _meta fragment a stamped tool or result carries |
MCP_CATALOG_META_KEY |
const | the namespaced _meta key (stitchkit/catalog) |
McpCatalogStamp |
type | { digest, tools } — the catalog fingerprint and its tool count |
MCP Apps (widgets)
Interactive MCP resources — ADR 0019.
| Export | Kind | Summary |
|---|---|---|
mountMcpResource |
function | mount an MCP Apps widget resource |
inlineMcpAppBundle |
function | inline a built widget bundle into a resource |
EXT_APPS_BUNDLE_PLACEHOLDER |
const | the placeholder token inlineMcpAppBundle replaces |
RESOURCE_MIME_TYPE |
const | the MCP Apps resource MIME type |
McpResourceDef |
type | an MCP Apps resource definition |
McpAppResourceMeta |
type | resource _meta for an MCP App |
McpAppCsp |
type | the widget content-security policy |
Introspection & internals
Advanced building blocks — the shared machinery the mounts are built on.
| Export | Kind | Summary |
|---|---|---|
collectTools |
function | resolve a service’s methods to mountable tools (the shared resolver) |
createToolLogger |
function | a ready afterToolCall that logs every tool call — guide |
summarizeTransports |
function | mixed contract/runtime operation counts and per-source breakdown for a boot-time summary |
buildToolManifest |
function | transport-aware searchable { name, description, inputSchema } rows from a mixed surface |
ToolLoggerConfig |
type | config for createToolLogger |
ToolCallRecord |
type | the structured record createToolLogger passes to onRecord |
TransportSummary |
type | { contractServices, runtimeTools, totals, sources } from summarizeTransports |
TransportCounts |
type | per-transport counts ({ HTTP, MCP, AGENT, CLI }) |
ToolSurfaceProjection |
type | the one readonly { services?, runtimeTools? } container shared by full, MCP-only and introspection surfaces (buildToolManifest, listToolNames, summarizeTransports take ToolSurfaceProjection<RuntimeToolDefinition>) |
ToolManifestConfig |
type | mixed surface plus required model-facing transport and presentation options |
coerceJsonArgs |
function | coerce JSON-stringified array/object tool arguments, including object guards restored from JSON Schema; arbitrary transform pipes stay untouched; throws a ZodError naming the field when a union that keeps a string member receives a string that parses to an array its array member accepts |
flattenToolJsonSchema |
function | project structurally identifiable discriminated unions into conservative object joins; scalar collisions retain provable types, object/array collisions retain structural alternatives, and field descriptions retain discriminator labels plus availability/requiredness hints; the projection never executes validation |
ToolPresentationSchema |
type | immutable model-facing JSON Schema document shared by tool transports |
MountableTool |
type | one operation with separate executable CLI argument schema and model-facing presentation schema |
ToolManifestEntry |
type | one buildToolManifest row |
stitchkit/tools/mcp
A server-only leaf over the same MCP owner as stitchkit/tools. Its runtime and strict
NodeNext declarations require Zod and @modelcontextprotocol/server, with no AI SDK peer.
HTTP/stdio factories, mounts, schema policy, catalog and resource helpers keep their canonical
behavior and names. See MCP guide.
| Export | Kind | Purpose |
|---|---|---|
createMcpHandler / createMcpHttpRoute / buildMcpServer / mountMcp |
function | the shared authenticated HTTP handler, raw-route adapter, SDK server and contract mount |
createStdioMcpServer / bindStdioProcessSignals |
function | the shared stdio server and bounded process cleanup |
RuntimeToolDefinitionWithOutput / RuntimeToolDefinitionWithoutOutput |
type | the one neutral construction, shared with stitchkit/cli and stitchkit/tools; MCP-only presenters are its fourth type argument, RuntimeMcpToolPresenters<z.output<typeof output>> |
RuntimeToolDefinition |
type | heterogeneous registration; the canonical runner validates input/output before invocation |
RuntimeMcpToolPresenters / RuntimeMcpPresentation |
type | official SDK content without framework-owned structuredContent or isError; one presenter owner shared with the full SDK surface |
stitchkit/tools/connections
Server-only subexport that consumes external MCP servers and OpenAPI specifications
as typed tools, without adding a peer dependency to stitchkit/tools. Foreign
operations mount as the same RuntimeToolDefinitions our own produce, so
mountAgent({ runtimeTools }) runs them through the canonical lifecycle, hooks
and approval path.
| Export | Kind | Summary |
|---|---|---|
defineMcpClientConnection |
function | declare one external MCP server connection over Streamable HTTP with an optional SSE fallback |
ConnectionOperationLimits / McpConnectionLimits |
type | positive finite deadline/raw byte ceilings with independent discovery/call overrides; omitted fields inherit the shared bounds |
ConnectionPhase / ConnectionOperation / ConnectionFailureContext |
type | closed operation/phase vocabulary and measured read context for existing typed connection errors |
ConnectionTimeoutError / ConnectionResponseTooLargeError |
class | bounded operation refusal, with phase, operation and finite observed bytes; safe tool projection retains the raw cause locally |
defineOpenApiConnection |
function | declare one OpenAPI document (object, JSON text or JSON URL) as a tool surface |
mountConnections |
function | discover every connection and return readonly RuntimeToolDefinitions for mountAgent; a call’s arguments are parsed against the discovered schema before sending, except its unions, which the server judges (ADR 0266) |
ConnectionAuthorizationRequiredError |
class | typed reauthorization signal raised on 401 with credentials resolved again on the next call |
ConnectionBudgetExceededError |
class | the mount would expose more foreign tools than its declared budget |
ConnectionRequestError |
class | any non-2xx connection response other than the reauthorization signal |
ConnectionUrlError |
class | a non-http(s) URL or a request host the SSRF fence refused |
ConnectionTokenProvider |
type | () => string | undefined | Promise<string | undefined> — the lazily resolved credential |
ConnectionBudget |
type | { maxTools? } ceiling on one mountConnections call |
ConnectionDefinition |
type | either a defined MCP client or OpenAPI connection |
ConnectionMountOptions |
type | shared { lifecycle?, budget?, onSkippedTool? } mount policy |
ConnectionToolSkipReporter |
type | (skipped) => void — called per discovered tool the mount could not build; defaults to a stderr line, and the rest of the surface still mounts |
SkippedConnectionTool |
type | { connection, tool, reason } — which tool was not mounted, and why |
McpClientConnection |
type | a defined MCP client connection |
McpClientConnectionConfig |
type | name, transport, tool filter, token provider, instance key, allowed hosts and transports — naming ['CLI'] makes the whole server’s discovered tools commands, with no per-definition rewriting |
McpConnectionTransport |
type | { url, headers? } for one MCP endpoint |
McpToolFilter |
type | { allow?, block? } discovered-tool filter |
OpenApiConnection |
type | a defined OpenAPI connection |
OpenApiConnectionConfig |
type | name, spec, base URL, token provider, instance key, allowed hosts and transports |
stitchkit/testing
Fetch-only integration helpers that preserve the real generated-client and handler pipeline without opening a TCP port.
| Export | Kind | Summary |
|---|---|---|
createHandlerTestClient |
function | one contract client backed by an in-process FetchHandler |
createHandlerTestClients |
function | exact contract-registry batch form |
createManualClock / ManualClock |
function / type | manual time for schedules, retries and deadlines: now, wallNow, schedule, advance(ms) firing due timers in order with real event-loop yields between them, until, pending and hold; a ManagedScheduleClock, DurabilityClock, RevisionSignalClock and BoundedAdmissionClock — guide |
ManualClockOptions / ManualClockUntilOptions / ManualClockTimer / ManualClockHold |
types | start and wall instants, event-loop turns per firing and the real-time hold limit; until step and manual limit; a cancellable timer; a hold that is released or parked |
ManualClockError / ManualClockErrorCode |
class / type | MANUAL_CLOCK_HOLD_TIMEOUT naming the open holds, or MANUAL_CLOCK_LIMIT when until runs out |
runManagedResourceConformance |
function | run the canonical deterministic lifecycle matrix against a fresh consumer-owned ManagedResource fixture; resolves void or throws ManagedResourceConformanceError with a stable scenario ID and normalized trace |
ManagedResourceConformanceScenarioIdSchema / ManagedResourceConformanceScenarioId |
schema / type | stable clean, rollback, readiness/completion, activation, shutdown-race and forced-cleanup scenario vocabulary |
ManagedResourceConformanceScenarioSchema / ManagedResourceConformanceScenario |
schema / type | discriminated scenario record including whether the controlled resource is required |
ManagedResourceConformanceTraceEntrySchema / ManagedResourceConformanceTraceEntry |
schema / type | sequence-numbered phase/outcome diagnostic without timestamps or generated IDs |
ManagedResourceConformancePhaseSchema / ManagedResourceConformancePhase |
schema / type | lifecycle and disposal trace phases |
ManagedResourceConformanceTraceOutcomeSchema / ManagedResourceConformanceTraceOutcome |
schema / type | normalized enter, resolve or reject outcome |
ManagedResourceConformanceConfig |
type | fresh-fixture factory, optional scenario subset and emergency watchdog bound |
ManagedResourceConformanceFactoryInput / ManagedResourceConformanceControls |
type | current discriminated scenario and caller-controlled startup, readiness, completion, activation, close and force promises |
ManagedResourceConformanceFixture |
type | tested resource plus required bounded disposal callback |
ManagedResourceConformanceError |
class | MANAGED_RESOURCE_CONFORMANCE_FAILED diagnostic carrying scenario, expected phase subsequence and observed trace |
HandlerTestClientDefaults |
type | ordinary bare-client defaults with handler-owned baseUrl and fetch removed |
HandlerTestClientConfig |
type | handler, contract, path prefix, scoped config and client request defaults |
HandlerTestClientsConfig |
type | batch helper configuration |
HandlerTestTransportConfig |
type | shared in-process handler, origin, prefix, client defaults and optional server handle |
buildSurfaceManifest |
function | deterministic manifest v2 with HTTP topology, transport-specific tool projections, named MCP surfaces and realtime schema digests |
assertSurfaceManifestSnapshot |
function | bounded deterministic manifest drift assertion |
assertSurfaceDiscovery |
function | compare real OpenAPI/tool/realtime caller-observed discovery to the exact manifest projection |
runSurfaceProbes |
function | execute explicit transport drivers under one per-scenario setup/invoke/teardown deadline |
defineRealtimeProbe |
function | declare one canonical realtime scenario for a caller-supplied real transport driver |
createRealtimeProbeDriver |
function | bind each scenario to a caller-owned transport and normalize actual event/ack/rejection/disconnect outcomes without lifecycle ownership |
TransportObservationSchema |
constant | normalized HTTP/tool/realtime outcome including rejection fields and handler-call evidence |
RealtimeRejectionObservationSchema |
constant | direction/phase/reason/fault observation for a rejected realtime event |
RealtimeDisconnectObservationSchema |
constant | observed before-invoke versus in-flight disconnect phase |
ConformanceTransport |
type | explicit probe transport union |
RunSurfaceProbesConfig |
type | probes, drivers and diagnostic byte cap |
SurfaceDiscoveryObservation |
type | real OpenAPI/tool/CLI/extension discovery values |
SurfaceToolDiscoveryObservation |
type | transport, optional named surface and caller-observed tool names |
SurfaceRealtimeDiscoveryObservation |
type | caller-observed server→client and client→server event names |
SurfaceProbe / SurfaceProbeDriver |
type | one bounded scenario and its consumer-supplied runner |
DefineRealtimeProbeConfig |
type | name, canonical scenario, explicit fixture and expected realtime outcome |
CreateRealtimeProbeDriverConfig |
type | per-scenario foreign-transport binder and optional handler-call counter |
RealtimeProbeAdapter |
type | connected-state observation, scenario invocation and subscription-only cleanup |
RealtimeProbeFixture / RealtimeProbeScenario |
type | driver input and supported event/ack/local-invalid/peer-refusal/disconnect/timeout scenario vocabulary |
RealtimeRejectionObservation |
type | parsed structured realtime rejection observation |
RealtimeDisconnectObservation |
type | normalized physical timing of a realtime disconnect |
TransportObservation |
type | validated normalized driver result |
SurfaceManifest / SurfaceManifestConfig |
type | deterministic surface snapshot and its inputs |
SurfaceManifestOperation / SurfaceManifestOperationSchema |
type / schema | one contract or runtime operation row |
SurfaceManifestOperationMcp / SurfaceManifestOperationMcpSchema |
type / schema | the rounds an operation declares before it runs: a fixed list, 'resolved-per-call', or null for no MCP policy |
SurfaceManifestOperationToolView / SurfaceManifestOperationToolViewSchema |
type / schema | an operation’s declared tool view — digests of its defaults and output, and whether it projects; present only where a view is declared |
SURFACE_MANIFEST_VERSION |
const | the format version this build writes; a committed snapshot on an older one is refused by name |
SurfaceManifestTool / SurfaceManifestToolSchema |
type / schema | one mounted tool row with advertised input digest |
SurfaceManifestToolSurface / SurfaceManifestToolSurfaceSchema |
type / schema | one static transport projection, optionally keyed for a finite MCP surface |
SurfaceManifestRealtimeEvent / SurfaceManifestRealtimeEventSchema |
type / schema | one named directional realtime event with input/output args and ack digests |
SurfaceManifestExtension / SurfaceManifestExtensionSchema |
type / schema | declared transport extension row |
SurfaceManifestSchema |
schema | complete deterministic manifest schema |
SurfaceToolDefinition |
type | plain service/runtime selection used by CLI and finite named MCP surfaces |
SurfaceAgentProjection |
type | Agent selection plus its reachable extend/flatten presentation policy |
SurfaceMcpPreparation |
type | one global MCP extend/flatten/schema-validation/multi-round preparation policy |
SurfaceRuntimeToolDefinition |
type | peer-free non-executable runtime-operation descriptor for manifest projection |
SurfaceToolExtension |
type | canonical structural tool extension including schema, resolver and optional filter |
McpSchemaValidationConfig / IncompatibleSchemaPolicy |
type | canonical MCP schema-preparation policy used by real mounts and manifests |
SurfaceRealtimeSchemaPairSchema |
schema | input/output digest pair for args or acknowledgements |
SurfaceSchemaDigestsSchema |
schema | params/input/output/multipart digest object |
stitchkit/files
Peer-free Bun/Node filesystem capability. Browser/contract-safe refs are also
available from stitchkit/contract.
| Export | Kind | Summary |
|---|---|---|
createManagedFileBoundary |
function | bind an application-owned root, optionally creating one final directory under a trusted existing parent |
ManagedFileBoundary |
type | non-reopenable read/write capability over canonical relative paths |
ManagedFileBoundaryConfig |
type | bound root, optional createRoot, finite read/write/inspection limits, inspector and cleanup observer |
ManagedFileRefSchema / ManagedFileRef |
schema / type | transport-safe relative path, measured size and optional media metadata |
ManagedFilePathSchema / ManagedFilePath |
schema / type | canonical POSIX relative managed-file path |
ManagedFileSource |
type | bounded immutable bytes plus validated ref passed to upload callbacks |
ManagedFileReadOptions / ManagedFileWriteOptions |
type | per-operation byte cap, signal and atomic write policy |
ManagedFileError / ManagedFileErrorCode |
class / type | stable boundary failures; registered FILE_* mistakes are caller-safe while FILE_IO_ERROR remains internal |
ManagedFileInspector |
type | bounded-prefix read/write inspection callback with a finite cancellation signal that cannot own path or size |
ManagedFileInspectionInput / ManagedFileInspection |
type | inspector prefix/name/declared media/signal input and validated metadata-only result |
writeFileAtomic / writeFileAtomicSync / WriteFileAtomicOptions |
function / type | replace a file atomically: a random staging name created exclusively (never through a planted link), the mode set on the descriptor before the file is visible (default 0o600, not masked by the umask), fsync, rename; a failure leaves the target and no staging file. The asynchronous form keeps the event loop running. A process killed before publication leaves its staging file; sweeping it is the caller’s job |
isAtomicStagingName |
function | true for a staging file name of an atomic write of this library (.stitchkit-<24 lowercase hex>.tmp, also used by the managed writer and the chunk spool); the form is a stable contract, and changing it is a breaking change (ADR 0242) |
sweepAtomicStaging / SweepAtomicStagingOptions |
function / type | remove abandoned staging files from one directory: only regular files matching isAtomicStagingName and older than the required olderThanMs, never following a symlink or entering a subdirectory; stops on signal; returns the removed names, [] for a directory that does not exist |
withExclusiveLock / ExclusiveLockOptions / ExclusiveLock / ExclusiveLockOwner |
function / type | run work under an exclusive lock between processes — a file recording its owner (pid, host, machine identity, time and nullable kernel process identity); waits up to timeoutMs (default 10 s) and stops on signal; a dead owner on this machine is taken over, a live, slow or foreign one never is; a lock recorded by this very process is held only while one of its descriptors is open on it, so the lock an earlier image of the same PID left (bun --watch restarts in place) is taken over at once; the lock is published with its owner already recorded (temporary file plus hard link), so a stalled holder is never displaced; a legacy empty lock file is taken by age only when ownerlessGraceMs is a number (default null: never; an abandoned empty reclaim guard is taken after 5 000 ms unless a value is set); exact mode is independent of umask; shared readers need a common group and traversable directories |
ExclusiveLockError |
class | LOCK_TIMEOUT naming the resource and its holder, or LOCK_ABORTED with the signal’s reason |
createChunkSpool |
function | the server half of a chunked upload: parts on disk under owner + client-minted uploadId, each with a size+sha256 receipt; idempotent open and put, the first writer of a part wins across processes, assemble in order once every part is in, sweep of untouched uploads — guide |
ChunkSpool / ChunkSpoolConfig / ChunkSpoolKey / ChunkSpoolOpen / ChunkSpoolPart / ChunkSpoolAssembly |
type | the spool, its directory, part size, file limit, meta schema and age; an upload’s key; its declaration; one part; the assembled parts with a concatenating stream() |
ChunkSpoolErrorCode |
type | the AppError codes a spool refuses with, each with its 4xx status: UPLOAD_INVALID, UPLOAD_TOO_LARGE, UPLOAD_NOT_FOUND, UPLOAD_CONFLICT, UPLOAD_CHUNK_OUT_OF_RANGE, UPLOAD_CHUNK_SIZE, UPLOAD_INCOMPLETE |
CHUNK_SPOOL_ERROR_CODES / isChunkSpoolErrorCode |
const / function | every ChunkSpoolErrorCode as a frozen list, and the guard for one — map them onto the app’s own error codes, or a spool refusal reaches its client as an unknown 500 |
| Export | Kind | Purpose |
|---|---|---|
AtomicFilePublicationError |
class | published=true with cleanup/directory-sync/directory-close phase |
FileObservation |
type | observed descriptor dev/ino/size/nlink/mtimeMs/ctimeMs |
stitchkit/telegram
Peer-free server-only Telegram platform primitives — the Bot API’s own
protocols and the jobs every bot rewrote around them. Importing this resolves no
bot library; stitchkit/application/grammy remains the lifecycle adapter for an
injected grammY bot. → ADR 0143, ADR 0201 — guide
| Export | Kind | Summary |
|---|---|---|
verifyTelegramInitData |
function | verify a Mini App initData signature against the bot token in constant time, before reading anything out of it |
VerifyTelegramInitDataOptions |
type | raw initData, bot token, optional maxAgeSeconds bound and injected clock |
TelegramInitDataVerification |
type | { valid: true, data } or a refusal carrying its reason |
TelegramInitData |
type | verified user/receiver as TelegramUser, authDate, ageSeconds, queryId, startParam, chatType, chatInstance and every signed pair in raw |
parseTelegramUser / TelegramUser |
function / type | Telegram’s snake_case user — grammY’s ctx.from, a Bot API User, a Mini App user — as the one camelCase record initData returns too; undefined when it is not a user |
TelegramInitDataRefusal |
type | missing-hash / signature-mismatch / malformed / expired — an expired string is not a forged one |
classifyTelegramSendFailure |
function | name a refused Bot API send and separate “retry this send” from “stop addressing this recipient” |
TelegramSendFailure |
type | reason, status, Telegram-stated retryAfterSeconds, retryable, recipientUnreachable and which evidence produced the answer |
createTelegramBotTransport / TelegramBotTransportOptions |
function / type | a fetch for the Bot API senders that connects before it writes, so a failure before the first byte is TelegramNotDispatchedError; connection attempt and budget, answer timeout and size, injectable resolver and socket factory — guide |
TelegramFetch / TelegramBotTransportOpen / TelegramBotTransportResolve / TelegramBotTransportSocket |
types | the (url, init) => Promise<Response> the senders take; the transport’s socket factory, resolver and the structural socket it needs (a Node net.Socket or tls.TLSSocket fits) |
TelegramNotDispatchedError / TelegramNotDispatchedStage |
class / type | a request that provably never left (lookup, connect or request), so repeating it cannot duplicate a message |
TelegramSendFailureReason / TELEGRAM_SEND_FAILURE_REASONS |
type / constant | blocked-by-user / user-deactivated / chat-not-found / not-started / rate-limited / message-invalid / server-error / not-dispatched / unknown, and the same as a list; a Record<TelegramSendFailureReason, …> over them fails to compile when a reason is added |
runTelegramBroadcast |
function | a resumable broadcast by name under a state directory: audience and journal durably recorded, pacing at ratePerSecond (25), exact retry delays within the finite declared budget, injected classifier, uncertain send outcomes never replayed, dryRun, one fenced runner per name |
TelegramBroadcastConfig / TelegramBroadcastSend / TelegramBroadcastReport / TelegramBroadcastRunOutcome / TelegramBroadcastOutcome / TelegramBroadcastRecipient |
type | name, directory, recipients(), send({ recipient, attempt }), maxAttempts, signal, onProgress; counts delivered / unreachable / failed / uncertain / pending and finished / stopped / halted / dry-run |
TelegramBroadcastFailureSchema / TelegramBroadcastFailure |
schema / type | injected classify answers retry-after/transient/permanent/ambiguous; exact provider delay is bounded by maxRetryDelayMs without shortening, unknown outcome remains uncertain and is never replayed |
telegramBroadcastSender / TelegramBroadcastSenderConfig / TelegramBroadcastMessage |
function / type | the standard send: sendMessage with a text or copyMessage of a prepared message, through the Bot API |
createTelegramOperatorChannel |
function | the operator chat, apart from the journal: post(text, topic?) returns at once and never throws; paced sends into forum topics, 429 honoured, oldest dropped on overflow, drain(signal) and close() for the way down |
TelegramOperatorChannelConfig / TelegramOperatorChannel / TelegramOperatorMessage / TelegramOperatorDrop / TelegramChatId |
type | chatId, topics, send, maxQueued, minIntervalMs, maxAttempts, onDropped, sensitivePatterns and sensitiveValues (a bot token is always masked), dedupe; a drop is overflow / refused / attempts / closed / repeated / over-budget with its classification |
createTelegramOperatorDedupe / TelegramOperatorDedupeVerdict |
function / type | the channel’s dedupe window alone, for a sender with its own bot and retry: (text, topic?) → { send: true, text } with the held-back counts, or { send: false, reason: 'repeated' | 'over-budget' } |
TelegramOperatorDedupe |
type | windowMs (10 min): one message per fingerprint per window, the next one sent carries repeatedLine(count); maxPerWindow (20) across fingerprints, the overflow counted onto the next one sent with overBudgetLine(count); now |
telegramOperatorSender / TelegramOperatorSenderConfig |
function / type | the standard send: sendMessage into the chat and topic, plain text unless parseMode; with 'HTML' the markup is cleaned and cut by what it shows, so the channel’s cut never leaves a tag open |
createTelegramLocalFiles |
function | files the local Bot API server wrote under <root>/<token>/: resolve(file_path) and remove(file_path) only inside the bot’s directory, judged on real paths so a link is judged by where it leads; check() for readiness. Recommended root variable: BOT_API_FILES_ROOT |
TelegramLocalFilesConfig / TelegramLocalFiles / TelegramLocalFilesCheck / TelegramLocalFileError / TelegramLocalFileRefusal |
type / class | root, token; refusals root-not-absolute / bot-directory-unavailable / outside-bot-directory / missing / not-a-file, never carrying the path or the token |
callTelegramBotApi / TelegramBotApiCall / TelegramBotApiError |
function / type / class | one Bot API method over fetch; a refusal keeps error_code, description and parameters for the classifier, and no error names the URL |
TELEGRAM_BOT_TOKEN_PATTERN / redactTelegramBotToken |
constant / function | the secret half of a bot token — the bot’s id before the colon is not matched; redact and every logger on it mask it already, redactTelegramBotToken(text) masks every token in a string to 123456:[redacted] |
claimTelegramWebhook |
function | set the webhook only where it already points here, or by naming the host it is taken from; confirm Telegram holds it; pending updates kept unless dropPendingUpdates |
ClaimTelegramWebhookConfig / TelegramWebhookConfig / TelegramWebhookClaim |
type | token, url, secret, apiRoot, fetch, signal; takeoverFrom (a host, or 'none'), allowedUpdates, maxConnections, dropPendingUpdates; the claim’s tagged url, takenFrom, pendingUpdates |
TelegramWebhookClaimError / TelegramWebhookRefusal / TELEGRAM_WEBHOOK_NONE |
class / type / constant | owned-elsewhere / other-secret / not-confirmed with ownerHost — a host, never a path; 'none' names no webhook |
telegramWebhookUrl |
function | the address with an owner tag derived from the secret: equal for one secret, different for another, the path untouched |
checkTelegramWebhook / TelegramWebhookState |
function / type | whether the webhook still points here: owned, ownerHost, pendingUpdates, Telegram’s lastError |
receiveTelegramWebhook / ReceiveTelegramWebhookOptions / TelegramUpdateAcceptance |
function / type | one webhook Request: 403 without the secret (compared in constant time), 405 for another method, 400 for no update, 200 once accept recorded it |
createTelegramUpdateIntake |
function | webhook updates recorded before Telegram is answered and handled after: chat order kept, other chats alongside up to maxConcurrent, a renewed lease and immutable fence per attempt, a sweep that takes over what a restart or a dead process left, retries, maxAttempts, optional recoverable exhaustion delivery, finished updates remembered retainMs to refuse repeats; at least once |
TelegramUpdateIntakeConfig / TelegramUpdateAttemptIntakeConfig / TelegramUpdateIntakeOptions / TelegramUpdateIntake / TelegramUpdateEnvelope / TelegramUpdateFailure / TelegramUpdateStoreStep |
type | store, unchanged handle(update) or attempt-aware handleAttempt(update, context) (a grammY BotError is unwrapped), shared retry, maxAttempts (5), leaseMs (120 000), pendingGraceMs (60 000), sweepEveryMs (30 000), retainMs (24 h), maxConcurrent (32), onFailure, durable handleExhaustion, onExhaustionFailure, onStoreError, now; accept(body), start(), sweep(), idle(), close() |
TelegramUpdateAttemptContext / TelegramUpdateAttemptIdentity / TelegramUpdateOwnershipLostError |
type / class | immutable { updateId, attempt, claimId } fence plus ownerLost; the persisted opaque claim token prevents a stale capability from matching after prune/re-add, while a store check in the consumer’s DB transaction fences a domain write |
TelegramUpdateExhaustion / TelegramUpdateExhaustionFailure / StoredTelegramUpdateExhaustion / TelegramUpdateExhaustionQuery |
type | a terminal update/attempt/error retained in the update store until handleExhaustion resolves; ordered { limit, afterUpdateId? } pages prevent a failing first batch from starving later rows; delivery failures are observational and leave it due |
TelegramUpdateStore / StoredTelegramUpdate / TelegramUpdateState / TelegramUpdateSettlement / TelegramUpdateClaimOptions / TelegramUpdateDueQuery |
type | the base store an intake runs on: add, claim, renew, settle, due, prune, each atomic on one record — a claim takes pending, a due failed or a lapsed processing; renew and settle only by the attempt holding it |
TelegramUpdateFencedStore / TelegramUpdateDurableStore |
type | reference-store capabilities: claimOwned creates and returns the persisted identity, renewOwned, owns(identity, at) and settleOwned(identity, settlement) act only on that exact unexpired claim; exhaust, dueExhaustions, acknowledgeExhaustion keep a final consumer obligation in the same row until exact acknowledgement |
memoryTelegramUpdateStore |
function | the store in this process’s memory — tests, or a bot that accepts losing unhandled updates to a restart |
sqliteTelegramUpdateStore / SqliteTelegramUpdateStoreConfig / TelegramSqliteDatabase |
function / type | the store in SQLite over the handle the application opened — bun:sqlite Database or node:sqlite DatabaseSync; table (default telegram_updates) created when missing |
postgresTelegramUpdateStore / PostgresTelegramUpdateStoreConfig / TelegramPostgresQuery |
function / type | the store in Postgres over the client the application holds, as one query(text, parameters) returning rows — Bun sql.unsafe, Prisma $queryRawUnsafe, pg pool.query; each rule one conditional statement; table, createTable (default true) |
postgresTelegramUpdateStoreSchema |
function | the table, idempotent claim_id upgrade and index as a statement for a migration, safe to run twice; required before fenced methods when createTable: false, while legacy base methods remain compatible with the prior table |
checkTelegramUpdateStore |
function | put any store through every rule, each on a fresh store from make, concurrent claims included; resolves with the violations, empty when it keeps them |
stitchkit/telegram/html
Telegram’s HTML parse mode as a tree: any markup in, markup Telegram accepts out, cut to its limits by what the reader sees. No peer and no DOM — the same parse serves a server send and a browser preview. → ADR 0213 — guide
| Export | Kind | Summary |
|---|---|---|
parseTelegramHtml |
function | markup into nodes Telegram accepts: synonyms renamed (strong → b), block tags into line breaks, a link only with an http/https/tg/mailto href, an element where Telegram forbids it kept as text, a closing tag closing what is open inside it; never throws |
TelegramHtmlNode / TelegramHtmlElement / TelegramHtmlTextNode / TelegramHtmlTag / TelegramHtmlStyle |
type | text nodes hold decoded text; elements b i u s tg-spoiler code, a with href, pre with language, blockquote with expandable, tg-emoji with emojiId, tg-time with unix and format |
renderTelegramHtml |
function | nodes back to markup Telegram parses into exactly them |
sanitizeTelegramHtml |
function | any markup as markup Telegram accepts — renderTelegramHtml(parseTelegramHtml(markup)) |
splitTelegramHtml / TelegramHtmlLimitOptions |
function / type | parts within limit visible characters (default 4096), cut at a paragraph, a line, a space, else anywhere but inside a character or a custom emoji; an element across a cut is closed and reopened with its attributes; nothing visible is no parts |
truncateTelegramHtml / TelegramHtmlTruncateOptions |
function / type | one part: cut to limit with ellipsis (…) inside it, still valid |
telegramHtmlText |
function | the text a reader sees, entities decoded |
checkTelegramHtml / TelegramHtmlCheck / TelegramHtmlProblem |
function / type | the first thing Telegram would refuse, unrepaired — bare-character / unsupported-tag / unmatched-end-tag / unclosed-tag — and the visible text before it |
escapeTelegramHtml |
function | &, <, > and " escaped for Telegram’s HTML |
TELEGRAM_TEXT_LIMIT / TELEGRAM_CAPTION_LIMIT |
constant | 4096 and 1024, counted after the markup is parsed, in UTF-16 code units |
stitchkit/telegram/screens
A bot’s menus as declared screens over grammY: a screen says what the chat
should show, and the runtime decides what to send, edit and delete. Server-only,
Bun or Node; grammy and zod appear in the declarations, and nothing imports
grammY at run time — the bot’s own ctx.api and a grammY StorageAdapter are
the whole dependency. → ADR 0211 — guide
| Export | Kind | Summary |
|---|---|---|
telegramScreens |
function | telegramScreens<Ctx>() — the root the bot’s screens are declared from; the context type is named once |
TelegramScreensRoot / ScreenScope |
class | screen(path, options?), group(prefix, { params?, id? }), and on the root create(config) |
ScreenGroupBuilder / ScreenBuilder / ScreenBodyBuilder |
class | the chain: load (first or never) → action / on → view, which ends the declaration |
ScopeOptions / ScreenOptions / ParamsSchemaFor / ActionInputSchema |
type | a group’s params schema and id; a screen’s explicit id; the schema a path’s params accept; an action’s flat input schema |
TelegramScreen / AnyTelegramScreen |
class / type | a declared screen, typed by its context, params, data and actions |
ScreenLoadContext / ScreenActionContext / ScreenInputContext / ScreenViewContext |
type | ctx, params, data; an action’s input; an input’s message, text and pending(text); a view’s act buttons |
ScreenParams / ScreenParamValue / ScreenPathParams / ScreenLinkArgs |
type | params parsed from the path literal (or its schema); the argument a link or go takes — required exactly when the path has params |
ScreenActions / ScreenActionButtons / NoActionInput |
type | action name → input; act.<name>(label, input?) typed by the action’s schema |
ScreenInputKind / ScreenInputOptions |
type | text rich photo video animation document audio voice video_note sticker location contact; keepMessage leaves the user’s message (default: deleted before the handler) |
ScreenHandlerResult / ScreenOutcome / ScreenOutcomeBuilders / ScreenInputOutcomeBuilders |
type / class | what a load, action or input answers: stay(), go(screen, params?), back(), toast(text, { alert? }) (≤ 200 characters), notice(content, { expiresInMs? }); void is stay(); after input there is no press, so no toast |
ScreenNavigation / ScreenToast / ScreenNotice / NoticeOptions |
type | the parts of an outcome; a notice without expiresInMs is a receipt the screen moves below, with it a remark under the screen that removes itself |
ViewMessage / ScreenViewResult / TextViewMessage / RichViewMessage / PhotoViewMessage / VideoViewMessage / AnimationViewMessage / DocumentViewMessage / AudioViewMessage / ScreenMediaKind |
type | one message or several; exactly one content (text, rich, or a media file id or URL with caption), plus keyboard, key and linkPreview |
link / back / ScreenButton |
function / class | a button to a screen with its params; a button to the parent screen |
Keyboard / KeyboardRow / KeyboardButton / PlainKeyboardButton / ButtonLabel |
type | rows of screen buttons and plain Telegram buttons without callback_data; false, null and undefined are skipped; a label is text or { text, style?, icon_custom_emoji_id? } |
html / TelegramHtml / HtmlTag / HtmlValue / TelegramText |
function / class / type | Telegram HTML with every interpolation escaped; html.raw() for markup already safe, html.join(); a plain string is always escaped (escapeTelegramHtml is stitchkit/telegram/html’s) |
ActionValue |
type | what a button can carry: a string, a finite number, a boolean or null |
TelegramScreensConfig |
type | screens, storage, chatKey (default screens:<chat id>), callbackPrefix (default ~), chats ('private' by default, or 'all'), onStale, onError, onEvent, clock |
TelegramScreens / OpenArgs / OpenOptions |
type | bot.use(screens); open(ctx, screen, params?, { previous: 'keep' | 'delete' }); button(link(…)) for a message the screens do not own; close() cancels expiry timers |
ScreenStaleContext / ScreenStaleReason / ScreenErrorContext / ScreenTrigger |
type | a press nothing can answer — malformed / forged / inaccessible / unknown-token / unknown-screen / invalid-params / unknown-action / invalid-input; an error with its trigger open / press / input |
ScreenEvent / ExecutionReport |
type | transition (trigger, path templates, duration, messages sent / edited / kept / deleted), state-discarded, message-kept, sweep-failed; never message text |
ScreenChatState / ScreenChatStateSchema / TelegramScreenStorage |
type / schema | one record per chat — the shown view and expiring remarks, no message text; any grammY StorageAdapter<ScreenChatState> |
createScreenTestChat / ScreenTestChat / TestChatOptions / TestChatMessage / TestChatCall / TestMessageKind |
function / type | a chat with the application’s own Bot and no Telegram: send, sendPhoto, press(label), pressData, failNext, deleteByUser, restart(bot); messages, calls, answers |
stitchkit/tracking
Browser-safe visitor-tracking mechanics, with no event vocabulary of their own
and no React. The React wrapper (a provider and a hook, ~40 lines) is the
application’s — it owns the router and the session. The server half is
stitchkit/tracking/server. → ADR 0166 — guide
| Export | Kind | Summary |
|---|---|---|
createTrackingClient |
function | the client: visit lease and renewal, pending queue, synchronous identity from reserved sequences, outbox and flush lease, delivery, the string-body page-leave beacon plus a queued copy, visible time, scroll milestones, declarative clicks, heartbeats |
TrackingClient / TrackingClientConfig |
type | track / onNavigate / start / visitId / browserStreamId / attribution, and the host, buildId, builtin names, bootstrap, deliver, optional decorate (your eventExtras on every minted event), unload / unloadUrl, outbox, onUnauthorized, onVisit, onFailure, isAction, referrerMap, clickAttributes, scrollMilestones, batchSize, periods and limits |
TrackFn / EventsWithMetadata / EventsWithoutMetadata |
type | track(type) / track(type, metadata) typed by the application’s metadata map, and the two halves of that map |
BuiltinTrackingEventTypes / CONVENTIONAL_TRACKING_EVENT_TYPES |
type / const | the application’s names for the events the client emits itself; the conventional PAGE_VIEW … INTERACTION set |
browserTrackingHost / TrackingHost / TrackingPageContext |
function / type | everything the client takes from a browser tab behind one interface — page context, visibility, scroll depth, events, intervals, clocks, storage — so a test or a non-tab host can supply its own |
createTrackingContract / TrackingContractConfig / TrackingContractEndpoints |
function / type | bootstrap (POST /visit) and track (POST /events, safelistedBody) from the application’s event types, scope and optional extras |
createTrackingSchemas / TrackingSchemas / TrackingSchemasConfig |
function / type | every schema of one surface — event, request, response, disposition, entry, bootstrap — from eventTypes, optional eventExtras, buildIdPattern, maxEventsPerBatch |
TrackingEventEnvelope / TrackingEventShape |
type | eventId, visitId, browserStreamId, browserSequence, type, page, metadata, clientTimestamp |
TrackEventsRequest / TrackEventsResponse / TrackEventsResponseSchema |
type / schema | a batch (buildId, events, utm) and its answer (accepted, dispositions) |
TrackingDisposition / TrackingDispositionSchema / TrackingDispositionStatus / TrackingDispositionStatusSchema |
type / schema | accepted / duplicate / identity-invalid / excluded-bot — every one terminal |
VisitEntryContext / VisitEntryContextShape / VisitBootstrapResponse / VisitBootstrapResponseSchema |
type / schema | what a browser reports to open a visit (lineage, landing, referrer, UTM, display, screen, buildId, outbox health) and the lease it gets back |
TrackingOutboxState / TrackingOutboxStateSchema |
type / schema | available / unavailable |
UtmData / UtmDataSchema / AttributionData / AttributionDataSchema |
type / schema | campaign tags and a touch (UTM, referrer, landing page) |
DEFAULT_BUILD_ID_PATTERN |
const | dev or a git SHA |
createTrackingOutbox / TrackingOutbox / TrackingOutboxOptions / TrackingOutboxHealth |
function / type | the tab-shared outbox: streamId, reserveSequences, enqueue, acquireLease / releaseLease (short, released on leave), readBatch, acknowledge, health; bounded by count and age |
TrackingOutboxStorage / TrackingOutboxMeta / TrackingOutboxEvents / TrackingOutboxRecord / TrackingQueuedEvent |
type | one atomic, all-or-nothing transact over a key/value store and an event store (readonly for pure reads) — the contract an adapter implements |
indexedDbOutboxStorage / memoryOutboxStorage |
function | the IndexedDB adapter (one readwrite transaction per transact) and the in-memory one for tests and degraded mode |
createSequenceReserve / SequenceReserve / SequenceReserveOptions |
function / type | a block of reserved numbers spent synchronously — take / refill / shared — with a per-tab fallback when the source fails |
deliverTrackingBatch / TrackingDeliveryOptions / TrackingDeliveryOutcome |
function / type | one batch, one bounded retry on 0 / 5xx; delivered / failed / auth-invalidated (on 401 / 403) with an optional onUnauthorized recovery |
sendUnloadBeacon |
function | sendBeacon with a string body — the text/plain request a dying document can still complete; false without the API |
createVisibleTimeMeter / VisibleTimeMeter / VisibleInterval / VisibleHeartbeat / VisibleTimeMeterOptions |
function / type | additive visible time — checkpoint / cut / heartbeat, each interval with its own id; a hidden heartbeat carries no interval |
scrollDepthPercent / createScrollMilestones / ScrollMilestones |
function / type | depth as a percentage of the scrollable range; milestones fired once each per page |
createOncePerPage / OncePerPage |
function / type | one fact per key per page within a window — the guard a twice-mounted component cannot keep itself |
resolveAttribution / ResolveAttributionInput / ResolvedAttribution / AttributionStorage / ReferrerRule |
function / type | first-touch once, current-touch on every new UTM; the referrer → source/medium map is the application’s, there is no built-in list |
parseUtmFromSearch / parseReferrer |
function | the two parsers resolveAttribution is built from |
resolveTrackedClick / ResolveTrackedClickOptions / TrackedClick / TrackedClickAttributes / ClickTarget |
function / type | data-track → click, data-track-action → interaction, a link to another origin → outbound; attribute names configurable; leavesPage says which path to send on |
stitchkit/tracking/server
The decisions a tracking backend makes, without the storage it makes them
over. The application reads visits and stored hashes from its database, hands
them here and writes what comes back; issueVisitLease runs the visit
algorithm over a store the application implements. → ADR 0166
| Export | Kind | Summary |
|---|---|---|
dispositionTrackingBatch / DispositionInput / DispositionResult / DispositionEvent / KnownVisit |
function / type | decide a batch: bot → all excluded-bot; wrong lineage or owner → identity-invalid; stored id → duplicate (+ conflicts when the hash differs); rest accepted; anonymous visits an identified caller may adopt |
issueVisitLease / IssueVisitLeaseOptions / IssuedVisitLease |
function / type | under the lineage lock: continue the named or latest active visit (adopting an anonymous one when ownership: 'adopting'), else end what is open and start a new one; a bot gets a lease no store holds |
TrackingVisitStore / FindActiveVisitQuery / ActiveVisit / VisitActor / VisitOutboxHealth / VisitOwnership |
type | the six-method store the application implements over its database — withLineageLock, findActive, touch, optional adopt, endOpen, create — and the shapes it exchanges |
activeIntervalOf / ActiveTimeInterval / ActiveIntervalOptions |
function / type | the visible-time interval an event carries, dated by the server clock; null for an unshaped or implausible one |
hashTrackingEvent |
function | sha256(JSON.stringify(parsedEvent)) — the stored payload hash, unsorted on purpose so it matches what applications already hold |
isBotUserAgent / DEFAULT_BOT_USER_AGENT_PATTERN |
function / const | crawlers, monitors and headlesschrome are not visitors |
createPresenceRegistry / PresenceRegistry / PresenceEntry |
function / type | who is here now, in this process: touch / snapshot(filter) / presentVisitOf with a 45 s TTL |
stitchkit/release
A page follows the release it was built for. The server keeps a marker of the
current frontend build and names it on every response (X-Build-Id) and every
socket connection; the browser compares that to its own build id and
reloads under a declared policy. Reading the build id and sending the deploy
signal stay with the application. → ADR 0167 — guide
| Export | Kind | Summary |
|---|---|---|
createReleaseMarker / ReleaseMarker / ReleaseMarkerConfig / ReleaseRefresh |
function / type | current(), refresh() → { changed, buildId }, subscribe; built on an application read that returns null where there is no release; a bad value or a throwing subscriber goes to onError, never out |
RELEASE_HEADER |
const | X-Build-Id — set on every response of a handler configured with release, exposed through CORS by default |
createReleaseWatcher / ReleaseWatcher / ReleaseWatcherConfig / ReleaseReloadPolicy |
function / type | observe(buildId) against the bundle’s own id; immediate / when-hidden / on-navigation with maxDeferMs; one reload per id, remembered across it; navigated, stale, dispose, onStale |
browserReleaseHost / ReleaseWatcherHost |
function / type | visibility, timer and reload behind one interface — a test supplies its own |
bindReleaseToSocketServer / observeReleaseFromSocket |
function | the socket channel: each connection re-reads and hears the build, everyone hears a change; the client hands the event to the watcher |
ReleaseSocketServer / ReleaseSocketEmitter / ReleaseSocketListener / ReleaseSocketOptions |
type | the structural slices of a Socket.IO server and client the bindings use — no peer import |
stitchkit/voice
Isomorphic, dependency-free mechanics of a live voice conversation. Recognition, synthesis providers, the microphone and the player remain application-owned. See the voice guide.
| Export | Kind | Summary |
|---|---|---|
SentenceCutter |
class | next(text, final) returns the sentences finished since the previous call of the reply streamed so far — never inside a fenced code block, never at 3.5 or т. е.; reset() starts a new turn |
speakableText |
function | the visible text of Markdown without delimiters, link and image addresses, bare addresses, fenced code blocks or tables |
SpeechQueue / SpeechQueueOptions |
class / type | speak sentences in order with lookahead (default 1) synthesised while one plays; close() finishes the queue, cancel() aborts the playing sentence and every synthesis; a failed sentence is reported to onError and skipped |
LIVE_VOICE_PHASES / LiveVoicePhase |
constant / type | opening, idle, hearing, thinking, speaking |
stitchkit/geo
Server-only managed GeoIP generations. Applications own database acquisition, licensing and domain mapping; the optional MaxMind peer is loaded only when its adapter is used.
| Export | Kind | Summary |
|---|---|---|
createGeoIpResolver / GeoIpResolver / GeoIpResolverOptions / GeoIpSnapshot |
function / type | public-IP lookup over one stable reader generation; unavailable start, last-known-good degraded reload and cleanup are explicit states |
createMaxMindGeoIpLoader / MaxMindGeoIpLoaderOptions / MaxMindGeoIpPaths |
function / type | lazy optional-peer City+ASN loader with stable before/after file revision checks |
GeoIpReader / GeoIpReaderLoader |
type | peer-neutral reader/generation seam for adapters and tests |
GeoAttribution / mapGeoIpRecord |
type / function | generic optional place and autonomous-system projection; application-specific fields remain outside |
stitchkit/oauth
Browser-safe, provider-neutral Authorization Code + PKCE transaction mechanics. Navigation, token exchange, identity and sessions remain application-owned. See the OAuth guide.
| Export | Kind | Summary |
|---|---|---|
createAuthorizationCodeClient / AuthorizationCodeClient / AuthorizationCodeClientConfig |
function / type | begin one S256 authorization request and consume its versioned pending transaction exactly once |
BeginAuthorizationCodeInput / BeginAuthorizationCodeResult / ConsumeAuthorizationCodeInput / ConsumedAuthorizationCode |
type | inputs and safe protocol result around caller-validated context |
AuthorizationCodeStorage / AuthorizationCodeCrypto |
type | injected browser capabilities; neither is read at module initialisation |
AuthorizationCodeClientError / AuthorizationCodeClientErrorCode |
class / type | fixed safe failure codes for configuration, context, storage, transaction and state failures |
safeInternalReturnPath |
function | accept only a single-slash current-origin path without backslashes or ASCII controls |
stitchkit/google
Server-only Google code exchange and verified OIDC identity. This entry requires the optional
google-auth-library peer. See the OAuth guide.
| Export | Kind | Summary |
|---|---|---|
createGoogleOidcClient / GoogleOidcClient / GoogleOidcClientConfig |
function / type | exact-redirect, deadline-bounded code exchange and verified identity projection |
ExchangeGoogleAuthorizationCodeInput / GoogleOidcIdentity / GoogleOidcClaims |
type | callback input, provider-neutral result and verifier seam claims |
GoogleOidcExchangeInput / GoogleOidcTokenTransport / GoogleOidcIdTokenVerifier |
type | injectable transport and verifier boundaries used by production and deterministic tests |
GoogleOidcError / GoogleOidcErrorCode |
class / type | safe MISCONFIGURED, INVALID_CREDENTIAL or retryable UPSTREAM_UNAVAILABLE failure |
stitchkit/declaration
Zod-only, dependency-free. The project declaration: the single machine-readable statement a repository makes about itself, read by the project, by the scaffolder that writes the first copy, and by whatever builds a source and binds the artifact into a deployment. It ships from the framework so those readers cannot hold different copies of the same schema.
identity identifies the repository-local buildable source/artifact, not a product project, checkout
or harness workspace. Product↔repository membership is explicit and many-to-many, owned by an
external registry; dependency edges do not establish membership. Private companion context is never
required in this public schema. See identity boundaries.
Declaring yourself is optional. A project with no project.json is a
complete project: nothing else in the framework imports this entrypoint, no
build, test or start path looks for a declaration, and its absence is never an
error or a warning.
The rule the schema exists to hold: a declaration must be complete and meaningful when no machine exists. A field that cannot be filled in without knowing where the code will run is a binding supplied by the deployment, not a declaration made by the repository.
Structure is the guarantee: nothing here requires a value of the place. A
command is executable plus an args array, no part may be an absolute path or
carry an inline value (--port=8080 must be ['--port', '8080']), paths are
repository-relative, bindings are named by variable and never valued, and a
listener’s variables must exist in env.variables with matching shapes.
Hygiene is the filter: every remaining free string is checked against
namesAMachine — a scheme, a protocol-relative host, an absolute or
home-relative path, a Windows drive, a host:port pair, a bare IPv4 literal —
and a number after a port flag is refused. It catches known shapes; it is not a
secret scanner, and a secret or hostname written as a plain argument passes.
Unknown keys are refused, not stripped. A key one reader does not recognise is a disagreement between programs that never meet, and discarding it silently is how a partially understood declaration becomes a running, wrong deployment.
| Export | Kind | Summary |
|---|---|---|
ProjectDeclarationSchema / ProjectDeclaration |
schema / type | the declaration: schemaVersion, kind, identity, roles, build, requires, release, env |
parseProjectDeclaration |
function | parse a declaration, refusing an unrecognised schemaVersion before any field is read |
PROJECT_DECLARATION_SCHEMA_VERSION |
constant | the declaration format this build understands — the number a reader refuses on |
namesAMachine |
function | why a string names a particular machine, or undefined — the one predicate every free string is checked against |
findProjectRole |
function | the role with a given name, or undefined |
ProjectIdentitySchema / ProjectIdentity |
schema / type | slug, name, version and a per-locale description |
ProjectRoleSchema / ProjectRole |
schema / type | one runnable role: a workingDirectory inside the source, per-mode commands, an optional listener, and drainFloorMs |
ProjectCommandSchema / ProjectCommand |
schema / type | executable plus args — argv, never a shell string |
ProjectRoleCommandSchema / ProjectRoleCommand |
schema / type | a command run under a supervisor: additionally never a script runner, because a launcher duplicates the shutdown signal |
ProjectListenerSchema |
schema | portVariable, bindVariable and readinessPath — absent means the role has no listener at all |
ProjectRunModeSchema |
schema | the run modes a role declares commands for |
ProjectBuildSchema |
schema | build command, the set of artifacts it produces — more than one path is normal — and any declared data inputs |
ProjectBuildInputSchema / ProjectBuildInput |
schema / type | data the build may read: a name, a frozen export path inside the source, and the sha256: digest that pins its bytes. Absent inputs means the build reads no data — an answer, not a gap |
ProjectRequirementSchema / ProjectRequirementPhaseSchema |
schema | something the code needs but does not provide, and the phases — release, start — it is needed in |
ProjectReleaseSchema / ProjectMigrationsSchema |
schema | what must happen once before roles start; migrations are declared as engine, root and lockfile — bytes, not a command to run |
ProjectEnvVariableSchema / ProjectEnvVariable / ProjectEnvShapeSchema |
schema / type | a variable a deployment must supply: name, shape, required, and members for an enum |
ProjectSlugSchema |
schema | lowercase hyphen-separated identity everything else is named after |
ProjectDescriptionSchema |
schema | description per locale tag |
RepositoryPathSchema |
schema | a path inside the source — absolute, .., ~ and Windows paths are refused |
BindingVariableSchema |
schema | the NAME of an environment variable a deployment fills in |
Version handling is fail-closed: an unrecognised schemaVersion is refused,
never assumed compatible, and refused before any field is read so a newer
declaration reports as a version this build cannot serve rather than as a list of
unrecognised keys.
To compose a stricter declaration, build on the exported member schemas — for
example ProjectDeclarationSchema.safeExtend({ identity: … }), which keeps the
boundary refinements in force. ProjectDescriptionSchema is a record, so narrow
it by replacing the field rather than extending it.
stitchkit/node
Server-only, for Node ≥ 22 (Bun uses stitchkit/server). The runtime-agnostic
core plus a Node HTTP adapter — ADR 0013,
deployment guide. Re-exports the
runtime-agnostic pieces of stitchkit/server and the error helpers.
| Export | Kind | Summary |
|---|---|---|
serveNode |
function | build the router and start a Node HTTP server (via srvx) |
createHandler |
function | the router as a bare (req) => Response (same as /server) |
createSocketIOServer |
function | the typed Node Socket.IO server (io + attach; no Bun engine declarations) |
createUnixClientTransport |
function | the same fail-closed Bun/Node Unix client adapter exported by stitchkit/server |
implement / createImplement / createScopedImplement / createScopedImplementRegistry / createMultipartStream |
function | bind a contract to typed handlers, optionally typed per endpoint scope (same as /server) |
NodeServerConfig |
type | config for serveNode |
NodeServerHandle |
type | managed Node handle (url, port, runtime, status, shutdown) |
NodeRuntimeServer |
type | concrete srvx/node runtime escape hatch |
NodeSocketLifecycle |
type | Bun-free Socket.IO lifecycle accepted by serveNode |
HandlerConfig / ServiceDef / RawRoute / RawRouteContext |
type | runtime-neutral handler types; raw routes default their host server to unknown and may declare stable serviceName / action observability identity |
SocketIORequestPolicy / SocketIOServerConfig / SocketIOPeerLoaders / SocketIOServerHandle |
type | runtime-neutral handshake policy, config, optional-peer loaders and the Bun-free Node handle with io, attach and lifecycle |
UnixClientTransportConfig / UnixClientTransport |
type | Unix socket bounds, explicit response-body mode and owned Fetch-compatible handle |
UnixResponseBodyMode |
type | finite cumulative bounded mode or explicit pull-driven streaming mode |
UnixClientTransportError / UnixClientTransportErrorCode / UnixClientDeliveryState |
class / type | stable failure plus dispatch certainty; no cross-transport fallback |
AppError + appError / badRequest / unauthorized / forbidden / notFound / conflict / rateLimited |
— | error helpers (same as /contract) |
stitchkit/cli
Server-only. Composes contract/runtime managed operations and CLI-only native
commands into one command-line program. Light by design: needs neither the MCP
SDK nor the ai peer.
| Export | Kind | Summary |
|---|---|---|
createCli |
function | build and run a CLI from contracts — guide |
defineCliCommand |
function | define one Zod-typed CLI-only executable command with optional validated-result presentation/exit policy |
parseCliArgs |
function | argv → typed tool args against a schema; inline --field:=JSON assigns a whole JSON value, including null, while ordinary string flags remain lexical (advanced) |
routeCliArgv |
function | select the command out of argv without duplicating the global-option grammar (advanced) |
extractCliGlobalOptions |
function | lift the application’s own global options out of argv before routing (advanced) |
coerceJsonArgs |
function | the second half of parseCliArgs — parse array/object values a consumer sends itself, including discovered MCP object guards restored from JSON Schema, without the stitchkit/tools barrel |
CliArgumentError |
class | the refusal parseCliArgs and the view flags raise; a CLI reports it and exits 2 |
renderCliView |
function | compute an aggregate over a result (--count-by, --sum, --top, --table) — guide |
createCliProfileStore |
function | named 0600 credential profiles resolved by name, with the never-substitute rule built in — guide |
CliProfileError |
class | an AppError refusing a named profile that is missing, unreadable or shared between users |
renderCliInstaller |
function | generate the one-line installer from a build manifest, with the URL and digest substituted — guide |
checkCliUpdate |
function | bounded, interval-limited, never-throwing check for a newer published build |
applyCliUpdate |
function | download, verify the decompressed digest and replace the binary by rename |
assertCliPublishable |
function | refuse republishing one version from a different commit — takes one manifest or every manifest already published, because the promise a version makes does not stop at a channel boundary |
rollbackCliUpdate / CliRollbackConfig / RolledBackCliUpdate |
function / types | put the kept previous build back, digest-checked first and written by the same atomic rename the update uses |
signCliManifest / verifyCliManifest / cliManifestSigningPayload |
function | Ed25519 over {name, version, commit, builtAt, assets[]} — every asset’s digest included, so the chain closes on the file that executes |
cliSignatureAccepted / CliSignatureVerdict |
function / type | valid | unenforced | missing | unknown-key | invalid; unenforced keeps an unpinned build updating while making the absence of a check visible |
CliTrustRoot / CliSigningKey / CliBuildSignature / CliBuildSignatureSchema |
types / schema | the keys a build trusts, by id, and the detached signature a manifest carries |
selectCliBuildAsset |
function | the asset for one target, or undefined |
currentCliBuildTarget |
function | { platform, arch } of the running process |
formatCliBuildStamp |
function | one line saying what the running build is |
compareCliVersions |
function | compare two versions, or undefined when they are not comparable |
CliBuildManifestSchema / CliBuildManifest |
schema / type | name, version, commit, build time and assets |
CliBuildAssetSchema / CliBuildAsset |
schema / type | one download; size and sha256 describe the decompressed bytes |
CliBuildTargetSchema / CliBuildTarget |
schema / type | { platform, arch } |
CliBuildStampSchema / CliBuildStamp |
schema / type | the version/commit/build time carried inside a binary |
CliInstallerConfig |
type | manifest, binary name, default install directory, and an optional asset — omit it for one script that selects the target by uname |
CliUpdateCheckConfig / CliUpdateCheck |
type | check inputs, and its four answers — skipped, current, outdated, unknown |
CliUpdateApplyConfig / AppliedCliUpdate |
type | apply inputs — including verify, run on an executable candidate beside the target before the backup and the replacement, within verifyTimeoutMs — and the replaced path, byte count and digest |
CliProfileStore / CliProfileStoreConfig / ResolvedCliProfile |
type | the profile store, its directory/schema/hint config, and one resolution |
CliResultView |
type | the requested view — count, sum, or records (ordered and/or table-rendered) |
CliViewOutput |
type | a JSON value, or the one human-facing text shape |
CliGlobalOptionsParse |
type | { argv, globals } returned by extractCliGlobalOptions |
CliArgvRoute |
type | { command, commandArgv, topLevelHelp, version, error? } returned by routeCliArgv |
pollUntilDone |
function | the generic --wait poller (advanced) |
emitResult |
function | write a pretty or compact ToolResult record to stdout/stderr + exit code (advanced) |
cliExitCode |
function | the exit code a result earns, from the same table, without writing anything — so an in-process run and the printed path cannot disagree |
createCliInvoker / CliInvoker / CliInvokerConfig / CliInvocationResult / CliInvokerCommand / cliInvocationResult |
function / types | compile the managed surface once and run parsed calls against it in process — no argv round-trip, no child process, no writing |
defineCliStreamCommand / CliStreamCommandConfig / CliStreamAnswer / CliStreamHooks / runCliStream |
function / types | one operation per JSON line of stdin, answered with the same id; a bad line answers and the stream continues |
defineCliBatchCommand / CliBatchCommandConfig |
function / type | the same loop, resumable: a recorded line replays, a line whose content changed under the same id is refused |
readCliCheckpoint / writeCliCheckpoint / CliCheckpoint / CliCheckpointEntry |
function / types | the batch’s record — id plus a digest of the line, written by atomic rename after every line |
DEFAULT_EXIT_CODES |
const | the default ToolResult.code → exit-code map |
CliConfig |
type | config for createCli; defaultCommand, globalOptions, optionAliases and positionals define the shared command presentation policy |
CliPresentationPolicyConfig |
type | shared command presentation-policy subset of CliConfig |
CliSurfaceSource |
type | static service/runtime array or identity-dependent factory |
RuntimeToolDefinition |
type | neutral heterogeneous runtime-tool registration; an inline handler is contextually typed, and handlers execute through the schema-validating managed runner |
RuntimeToolDefinitionWithOutput |
type | strict neutral managed definition with schema-derived handler input/output, the same declaration stitchkit/tools constructs with presenters |
RuntimeToolDefinitionWithoutOutput |
type | strict neutral managed void definition without an output contract or transport presenters |
CliCommandDefinition |
type | native command definition union |
CliCommandDefinitionBase |
type | native command name, description and input schema |
CliCommandDefinitionWithOutput |
type | native command with validated declared output and typed optional present / successful exitCode callbacks |
CliCommandDefinitionWithoutOutput |
type | native void command without an output contract |
CliCommandContext |
type | parsed input, framework run options, the application’s globals and stdout/stderr writers |
CliRunOptions |
type | parsed global flags (--json compacts success/error records, --wait, …) |
ParsedCliArgs |
type | result of parseCliArgs |
CliWaitConfig |
type | per-command --wait polling config; optional failed(result) maps a terminal domain failure to WAIT_FAILED and a non-zero exit |
ExitCodeMap |
type | ToolResult.code → process exit code |
PollParams |
type | params for pollUntilDone |
CliWriters |
type | stdout/stderr sinks for emitResult |
EmitOptions |
type | options for emitResult |
stitchkit/cli/publish
Build and release tooling, evolving. Publishes a CLI distribution into a local
application-owned directory; the manifest, signatures, installer and updater it
writes for stay in stitchkit/cli — guide,
ADR 0245.
| Export | Kind | Summary |
|---|---|---|
publishCli |
function | optional bounded builder/admission over one immutable name/version/commit stamp; commit verified assets before the manifest pointer, recover exact completed versions, retain verified history |
CliPublicationOptions |
type | identity, storage root, base URL, targets, limits, retention, the admit and build callbacks, optional signing and trust |
CliPublicationPhase |
type | the step admit is asked about — prepare, build, commit or promote |
CliPublicationResult |
type | published or existing, with the manifest ready to serve |
stitchkit/react
Browser- and server-render-safe React data-layer helpers. Needs the
@tanstack/react-query and react-query-kit peers.
| Export | Kind | Summary |
|---|---|---|
createCursorQuery |
function | a cursor-paginated infinite query — guide |
apiErrorRetry |
function | build a bounded network/HTTP-status retry predicate using cross-bundle ApiError.is — guide |
createQueryClientFactory |
function | request-local SSR QueryClient through a supplied cache adapter plus a factory-local browser singleton — guide |
createCacheBridge |
function | sync socket events into the Query cache — guide |
createRealtimeCacheBridge |
function | the same bridge fed by a validated realtime contract; the payload comes from the contract’s args tuple instead of inferring never |
createEntityCacheHandlers |
function | created/updated/deleted cache handlers for one entity — guide |
EntityCacheConfig |
type | config for createEntityCacheHandlers |
EntityCacheMembership / EntityCacheMembershipPolicy |
type | per-exact-query `include |
EntityCacheTotalPolicy / EntityCacheTotalDeltaInput |
type | evidence-aware reconciliation of numeric totals on paginated cache shapes |
EntityCacheHandlers |
type | the { created, updated, deleted } handlers it returns |
EntityCacheEvent |
type | discriminated created/updated/deleted input for dynamic cache keys |
EntityCacheKey |
type | static QueryKey or event-aware key factory |
EntityCacheListConfig |
type | list shape, scoped key, insertion/missing-update policy and comparator |
EntityCacheListShape |
type | array | paginated | infinite-array | infinite-paginated |
DeletedPayload |
type | a deleted event payload — the entity or a bare { id } |
CursorQueryConfig |
type | config for createCursorQuery |
ApiErrorRetryConfig |
type | retry attempts, excluded application codes, inclusive status ranges and network policy |
QueryClientFactoryConfig / QueryClientServerCache |
type | TanStack config, mutation observer, retry policy and request-cache adapter |
QueryRetryValue |
type | TanStack’s accepted query retry value retained by the factory pass-through |
CacheBridge |
type | the createCacheBridge handle |
CacheBridgeConfig |
type | config for createCacheBridge |
RealtimeCacheBridgeConfig |
type | config for createRealtimeCacheBridge — same fields, a ValidatedRealtimeSocket in place of the raw socket |
CacheBridgeContext |
type | the ctx a bridge handler receives |
CacheBridgeHandler |
type | one event-to-cache handler |
CacheBridgeHandlers |
type | the handler map |
CacheBridgeSocket |
type | the minimal emitter a bridge accepts |
For the rationale behind these APIs — why Bun.serve and not a framework, why
two context types, why thin wrappers — see the
Architecture Decisions.
Watched handles in the query cache
CacheBridgeConfig.watched accepts WatchCacheBinding entries with handle,
queryKey and optional state(frame) observer. Include the session in query keys.
CacheBridgeConfig.session fences events and removes bound queries when that login
ends. Watch loss marks a query stale without triggering an independent refetch;
recovery belongs to the watched read.
stitchkit/react/keyboard
Browser-only, headless keyboard handling for React: which part of a screen gets a
key, and lists the arrows move through with real focus. Needs the react peer;
no component, no styles, no router — see the keyboard guide.
| Export | Kind | Summary |
|---|---|---|
useKeyLayer |
hook | put a layer on the window’s one key stack — asked overlay → local → route → zone → global, innermost first within a kind |
useEscapeLayer |
hook | an overlay, local or route layer for Escape: one press closes one level |
useNavZone |
hook | a list zone — roving tab stop, arrows move DOM focus, select or highlight mode, cross-axis enter/exit, boundaries |
nextZoneIndex |
function | where a move lands in a list of a given length: an index, 'before-start' or 'after-end' |
isKeyFieldTarget |
function | whether a key was pressed in a field or a data-local-keys area, the test layers use |
KeyLayerOptions |
type | kind, onKey, active, scope, fields |
KeyLayerKind |
type | 'overlay' | 'local' | 'route' | 'zone' | 'global' |
EscapeLayerOptions |
type | kind, onEscape, active, scope |
NavZoneOptions |
type | items, value, onChange, mode, orientation, role, loop, onEnter, onExit, onBoundary, active, label, onReveal |
NavZone |
type | what useNavZone returns — zoneProps, itemProps(id), element, current, focus(id?) |
NavZoneProps / NavZoneItemProps |
type | the props spread on the zone’s element and on each item |
NextZoneIndexInput |
type | length, index, move, loop |
ZoneItemId |
type | an item id — string | number |
ZoneChangeCause |
type | 'arrow' | 'confirm' |
ZoneMove |
type | 'next' | 'previous' | 'first' | 'last' |
ZoneOrientation |
type | 'vertical' | 'horizontal' |
stitchkit/agent-runtime/sandbox
Optional server-only namespace sandbox. Exports:
createSandboxCodingTools composes the existing coding profile over a handle’s
host-only SandboxCodingBinding, with shared authorization, command collection and lifecycle.
createBubblewrapSandboxBackend, createSandboxSession, SandboxError,
SandboxCommandSchema, SandboxNetworkPolicySchema, SandboxStateSchema.
Its types are BubblewrapSandboxConfig, SandboxBackend, SandboxCommand,
SandboxCreateInput, SandboxDriver, SandboxHandle, SandboxNetworkPolicy,
SandboxPrewarmInput, SandboxProcess, SandboxRunOptions, SandboxSession,
and SandboxState. The sandbox guide specifies lifecycle,
network enforcement, gateway credentials and platform/resource boundaries.
stitchkit/agent-runtime/realtime
Optional evolving Socket.IO server binding, experimental: no committed consumer yet.
bindAgentHarnessRealtime takes (harness, socket, config) and returns an
AgentHarnessRealtimeBinding: close() for its subscriptions and control connections, without closing
socket or harness, and revoke(conversationId, matches?). AgentHarnessRealtimeConfig requires
authorize({ identity, request, source, signal }): return { context } after verifying the session
principal, conversation, operation, files and metadata, or null. Identity is socket.data from the
application’s verified handshake. Every request is authorized on arrival. The events of an
attached conversation are delivered under the grant the latest successful request created, so a
token stream costs no authorization call per event. revoke drops the grant of every matching
socket; the next event is re-authorized (source: 'delivery', an operation: 'snapshot' request),
and a refusal or failure detaches the conversation and sends an access-denied delivery, which
turns the browser controller into an error state. Without a revoke call a grant lasts until the socket disconnects or the conversation
is detached; this fail-open default is deliberate, so call revoke whenever access to a conversation may
have been withdrawn. An authorization that began before a revoke never restores the grant. Observe access does
not grant mutation; controller leases and approval policy still belong to the harness.
maxPendingEvents and maxPendingAttachments forward to the canonical control server;
maxPendingRequests bounds in-flight authorization/control requests per socket (32);
authorizationTimeoutMs bounds each authorization (10000 ms). Honor its AbortSignal.
onError receives internal errors; peers receive generic denials. Revoking a conversation
releases only its attachment. Event overflow closes the socket; explicitly reconnect the
application transport. A transport’s Engine.IO payload limit remains application-owned.
stitchkit/agent-runtime/react
Optional evolving React peer leaf, experimental: no committed consumer yet. useAgent takes a controller and subscribes through
useSyncExternalStore, returning the same AgentControllerState as getSnapshot().
Create and close the controller at application/session scope. Multiple components can
observe it; StrictMode and unmount release only the component’s own subscription.
stitchkit/process
Native POSIX Bun/Node one-shot command execution. See native IO.
| Export | Kind | Purpose |
|---|---|---|
runNativeCommand |
function | caller-lifetime streaming or explicitly bounded binary capture |
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 |
NativeCommandStream |
type | what streamNativeCommand returns: stdout, stderr, result (its buffers are empty) and stop() |
NativeCommandStreamOptions |
type | NativeCommandOptions without capture, onOutput and stdio, which the streams own |
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 |
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 } |
NativeCommandResult |
type | observed nullable exit code/signal, descendantsStopped (members left in the group after the leader exited were stopped) and captured stdout/stderr bytes |
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 |
| 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 |
| observeProcessInstance / ProcessInstanceObservation | function / type | Linux/Darwin lifetime observation; observed identity or unavailable with its original cause, never guessed absence |
| ProcessInstanceSchema / ProcessInstance | schema / type | platform, boot ID, namespace and process start identity from the shared native reader |
| probeProcessOwner / ProcessOwnerEvidence | function / type | compare lifetimes on one caller-established machine; matched, boot change, reused PID, gone, legacy or unavailable with cause |
stitchkit/process/owner-loss
Narrow startup entry for single-file applications that lazy-import stitchkit/process.
| Export | Kind | Purpose |
|---|---|---|
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 |
stitchkit/files/packaging
stitchkit/files/packaging owns createNativePackaging and the types
NativePackagingOptions, NativePackagingAsset, NativePackagingPlugin, NativePackagingResult,
and for a standalone executable NativePackagingEmbeddedOptions, NativePackagingEmbeddedAsset,
NativePackagingEmbeddedResult. inspectNativeArtifact classifies a built artifact’s bytes by the
loader it carries as a NativeArtifactLoader: packaged, unpackaged or no-loader. The plugin
fails a build whose entry imports the default loader of another stitchkit installation, naming
both versions and roots.
It resolves the installed package’s target/version, reads each selected addon once and checks it
against the size and sha256 published in the package’s native-assets.json (formatVersion: 2,
written when Stitchkit is built). Call it once per build and reuse the result.
platform, architecture, delivery, entryPath and assetPath are the explicit inputs of
companion delivery; embedded delivery takes platform, one architecture and delivery only, and
refuses a path. assetPath accepts one template, [hash], replaced by the first 16 hex digits of
the addon’s published SHA256;
platform is the closed set 'darwin', and another name is a type error and a schema refusal.
The result is ready with verified assets and a structural Bun plugin, or unsupported /
missing / mismatch with the safe code NATIVE_TARGET_UNSUPPORTED, NATIVE_ASSET_MISSING or
NATIVE_ASSET_DIGEST_MISMATCH. A mismatch names the first differing architecture with
expected (published) and actual (installed) { size, sha256 }.
Malformed options, a manifest of another formatVersion and other filesystem errors throw rather
than masquerade as missing.
Companion accepts a single architecture string with an assetPath string, or an architecture
array with an exact per-architecture assetPath map. NativePackagingOptions<true> and
NativePackagingResult<true> describe the array form; default types preserve single-target signatures.
A ready array-form result carries the architecture array; NativePackagingAsset<true> identifies
each asset architecture. A single-target asset has four fields: outputPath, the verified bytes,
and the published size and sha256.
Targets must be unique; entry and all asset paths must be disjoint. One lazy loader chooses only
the actual runtime architecture, with no fallback.
Companion mode places external addons relative to the emitted entry; embedded mode gives
Bun compile the verified bytes of the matching addon, and its asset (bytes, size, sha256)
has no outputPath, because nothing is written beside the executable. Keep companion JS builds
without splitting, preserve every output, and write each asset’s bytes to its outputPath.
This evolving entrypoint is a build dependency; runtime imports do not reach it.
The detailed recipe is in native IO.
stitchkit/http
An HTTP-only entrypoint for browsers, React Native/Hermes and servers. It exports the same createClient, createClients, createHttpClient, URL builders, client configuration types and ApiError as the root, without loading its optional Socket.IO graph. Import shared contracts from stitchkit/contract.
import { createClients, createHttpClient } from 'stitchkit/http';
import { defineContract } from 'stitchkit/contract';
stitchkit/realtime
Hermes-safe realtime clients reuse the root transport and contract implementation. Both
createRealtimeClient and createSocketIOClient require peers.client here; no default
computed import enters this graph. Root clients retain their optional lazy runtime loader.
import { createRealtimeClient, defineRealtimeContract } from 'stitchkit/realtime';
const client = createRealtimeClient(contract, {
url,
peers: { client: () => import('socket.io-client') },
});
Native consumers import HTTP factories, ApiError, createUrlBuilder,
contractEndpointMatchers and uploadInChunks from stitchkit/http; schema factories,
ContractDef and paginatedSchema from stitchkit/contract; realtime factories,
RealtimeClient, defineRealtimeContract, InferRealtimeEventMap, createRetainedTopics
and RetainedTopics from stitchkit/realtime. createQueryClientFactory remains in
stitchkit/react. Shared modules must use the same public leaves throughout their graph.