stitchkit 0.68.7 → 0.68.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/llms-full.txt CHANGED
@@ -62,6 +62,8 @@ own, recorded as an ADR.
62
62
  | `stitchkit/agent-runtime` | server | evolving<br>_redefined in 9 of the 13 minors since 0.56.2, most recently 0.66.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
63
63
  | `stitchkit/agent-runtime/openrouter` | server | evolving | isolated OpenRouter language-model adapter |
64
64
  | `stitchkit/agent-runtime/browser` | browser + server | evolving | canonical agent records, events and reconnect cursor without execution or sinks |
65
+ | `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
66
+ | `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
65
67
  | `stitchkit/application` | server | evolving<br>_redefined in 3 of the 13 minors since 0.56.2, most recently 0.67.0_ | managed resource graph, readiness, admission, schedules and bounded shutdown |
66
68
  | `stitchkit/application/grammy` | server | evolving | isolated grammY polling and webhook lifecycle adapters |
67
69
  | `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
@@ -165,6 +167,7 @@ map — feature → packages:
165
167
  | MCP / agent adapters (`stitchkit/tools`) | `@modelcontextprotocol/server` `ai` |
166
168
  | Agent application runtime (`stitchkit/agent-runtime`) | `ai` |
167
169
  | OpenRouter runtime adapter (`stitchkit/agent-runtime/openrouter`) | `ai` `@openrouter/ai-sdk-provider` |
170
+ | SQLite agent store (`stitchkit/agent-runtime/sqlite/bun` or `/node`) | — (runtime built-in) |
168
171
  | MCP host/client tests | `@modelcontextprotocol/client` |
169
172
  | MCP Apps UI widgets | `@modelcontextprotocol/ext-apps` |
170
173
  | React data layer (`stitchkit/react`) | `@tanstack/react-query` `react-query-kit` |
@@ -3530,6 +3533,36 @@ const exportOperation = defineAsyncOperation({
3530
3533
  const runtimeTools = exportOperation.runtimeTools
3531
3534
  ```
3532
3535
 
3536
+ #### Durable application-owned execution
3537
+
3538
+ The executable reference
3539
+ [`durable-async-operation-harness.ts`](../../packages/core/examples/durable-async-operation-harness.ts)
3540
+ shows the complete boundary behind that surface. It composes
3541
+ `defineAsyncOperationContract`, `defineAsyncOperation`, `createApplication`,
3542
+ `createBoundedAdmission`, managed shutdown and `createAgentToolFenceLifecycle`
3543
+ around an injected store and provider.
3544
+
3545
+ The store transactionally owns the idempotency key **and normalized request
3546
+ hash**. Reusing both returns the existing operation; reusing the key with a
3547
+ different hash conflicts. Every mutation is an expected-revision CAS. Before an
3548
+ external call, the application persists a unique attempt/effect key and marks
3549
+ the dispatch `possibly-dispatched`; a lost response is therefore reconciled by
3550
+ that key after restart and is never treated as permission to submit the effect
3551
+ again. Provider acknowledgement, progress, cancellation intent, result and
3552
+ artifact references remain durable application state.
3553
+
3554
+ Agent tool fencing and operation idempotency are separate guarantees. The fence
3555
+ prevents a stale run owner from crossing an effect boundary; the transactional
3556
+ idempotency record makes a repeated current call converge on one operation.
3557
+ Neither replaces the other.
3558
+
3559
+ Stitchkit deliberately does **not** own the durable queue, operation database,
3560
+ lease renewal, provider retry/reconciliation protocol, asset catalog or domain
3561
+ states. The process-local application resource stops admission and drains
3562
+ accepted work; unresolved durable records survive shutdown for the next
3563
+ recovery pass. The packed consumer lane executes this composition from the
3564
+ published package on Bun and Node.
3565
+
3533
3566
  Every follow-up repeats `authorize`; an opaque id is never authority. Aborting
3534
3567
  `wait` only stops waiting and never calls optional domain `cancel`.
3535
3568
 
@@ -3730,7 +3763,7 @@ description: Configure Stitchkit's optional durable history, stream loop, run co
3730
3763
  type: architecture
3731
3764
  status: active
3732
3765
  created: 2026-08-22
3733
- updated: 2026-08-22
3766
+ updated: 2026-08-28
3734
3767
  ---
3735
3768
 
3736
3769
  # Agent application runtime
@@ -3885,6 +3918,47 @@ await ticket.accepted
3885
3918
  const terminal = await ticket.result
3886
3919
  ```
3887
3920
 
3921
+ ### Executable headless harness and capability map
3922
+
3923
+ [`packages/core/examples/headless-agent-harness.ts`](../../packages/core/examples/headless-agent-harness.ts)
3924
+ is the complete resource-aware recipe. It accepts injected protocol, model,
3925
+ tool and store ports, validates resources plus diagnostics, carries provenance
3926
+ into the prompt and delegates execution to `createAgentRuntime`. Importing the
3927
+ example starts no process, opens no database and discovers no filesystem path.
3928
+
3929
+ | Concern | Public Stitchkit composition | Boundary |
3930
+ | --- | --- | --- |
3931
+ | execution loop | `createAgentRuntime` | already available; do not copy a second loop |
3932
+ | model choice | `defineModelRegistry` and `models.resolve` | provider credentials/discovery stay application-owned |
3933
+ | resources | injected loader → `composeAgentPrompt` sections | paths, trust, precedence and watching stay application-owned |
3934
+ | tools | `mountAgent` + `createAgentToolFenceLifecycle` | auth and domain effects stay application-owned |
3935
+ | follow-up | `runs.inputPolicy: 'queue'` | durable FIFO after the current run |
3936
+ | interrupt | `interrupt` or `interrupt-next` | `interrupt-next` terminates the active run and gives the new durable admission next priority |
3937
+ | recovery | `runtime.recover` + `scanRecoverable` | replay safety and context reconstruction are explicit callbacks |
3938
+ | reconnect | canonical snapshot + `advanceAgentRuntimeEventCursor` | transient deltas are replaceable; durable event IDs deduplicate |
3939
+ | persistence | memory reference, public driver, or SQLite leaf | product rows/outbox remain outside the runtime store |
3940
+
3941
+ Pi's steering queue waits for the current tool calls and injects the steering
3942
+ message at its next loop boundary. It is therefore not an alias for
3943
+ `interrupt-next`: Stitchkit requests termination of the active durable run,
3944
+ waits for its terminal settlement, and executes the prioritized successor.
3945
+ Pi follow-up is closest to Stitchkit `queue`, while JSONL trees, branching,
3946
+ workspace discovery, permissions and terminal UI remain embedding-application
3947
+ features rather than runtime requirements.
3948
+
3949
+ Runtime events preserve reasoning/text/tool lifecycle order. Durable admission,
3950
+ checkpoint, run-state and terminal events carry stable identities; transient
3951
+ deltas carry one runtime epoch and monotonic sequence. On a transient gap,
3952
+ reload the canonical snapshot and resume from the durable record instead of
3953
+ persisting deltas as a second history.
3954
+
3955
+ Prompt `contextWindow` budgeting is a pre-request decision over the assembled
3956
+ context. `AgentRun.usage` is cumulative measured/provider-reported execution
3957
+ evidence across attempts and compaction. They answer different questions and
3958
+ must not be substituted for each other. TTFT and throughput require timestamps
3959
+ from the actual provider stream plus a provider-reported or tokenizer-measured
3960
+ token count; character counts cannot produce exact token or throughput figures.
3961
+
3888
3962
  `recordIds` is optional. Supply stable application record IDs when an accepted-response transport must
3889
3963
  return durable placeholders before the run finishes. `ticket.admission` resolves after the store
3890
3964
  acceptance CAS and reports the canonical committed `input`, assigned `run`, a typed `pending`
@@ -3945,6 +4019,47 @@ recovery queries active run states directly instead of maintaining a second proj
3945
4019
  An admission receipt retains its canonical input, and a terminal run retains its canonical
3946
4020
  assistant, so physical product-history compaction cannot break idempotent retries.
3947
4021
 
4022
+ ### Built-in SQLite persistence
4023
+
4024
+ Use the runtime-specific leaf; the neutral agent runtime never imports either
4025
+ SQLite built-in:
4026
+
4027
+ ```ts
4028
+ // Bun
4029
+ import { createBunSqliteAgentRuntimeStore } from 'stitchkit/agent-runtime/sqlite/bun'
4030
+
4031
+ const sqlite = createBunSqliteAgentRuntimeStore({ filename: './agent-runtime.sqlite' })
4032
+ const runtime = createAgentRuntime({ ...config, store: sqlite.store })
4033
+
4034
+ await runtime.close()
4035
+ await sqlite.close()
4036
+ ```
4037
+
4038
+ ```ts
4039
+ // Node 22.5+
4040
+ import { createNodeSqliteAgentRuntimeStore } from 'stitchkit/agent-runtime/sqlite/node'
4041
+
4042
+ const sqlite = createNodeSqliteAgentRuntimeStore({ filename: './agent-runtime.sqlite' })
4043
+ ```
4044
+
4045
+ Initialization creates only `stitchkit_agent_runtime_*` tables and records
4046
+ schema version 1 in `stitchkit_agent_runtime_meta`; it does not use
4047
+ `PRAGMA user_version` or mutate application tables. An unknown schema version or
4048
+ unversioned partial Stitchkit schema is refused. The connection is owned by the
4049
+ returned handle and closes only after accepted operations drain.
4050
+
4051
+ Each handle serializes its transactions. Separate connections use
4052
+ `busy_timeout = 0`: a competing synchronous writer fails promptly with
4053
+ SQLite's lock error, so an awaited transaction can resume and commit or roll
4054
+ back. Retry that explicit error with an application-owned bounded policy; do
4055
+ not configure a blocking busy timeout on the same JavaScript thread.
4056
+
4057
+ The adapter proves canonical durability across reopen and process restart. It
4058
+ does not make external tool effects exactly once, join application projections
4059
+ atomically or replace an application outbox. If a product row must commit with
4060
+ an agent transition, implement `AgentRuntimeStoreDriver` over the application's
4061
+ own transaction boundary instead.
4062
+
3948
4063
  ## Durable order
3949
4064
 
3950
4065
  `acceptInputAndAssignRun` is one atomic operation. It is followed by ownership
@@ -4263,6 +4378,43 @@ These are post-commit notifications, not a transactional outbox: a process can
4263
4378
  crash between the database commit and `publish`. Reconnect should load canonical
4264
4379
  state. Exactly-once external delivery remains an application-owned outbox.
4265
4380
 
4381
+ ### External channel ingress and delivery
4382
+
4383
+ The executable
4384
+ [`external-channel-harness.ts`](../../packages/core/examples/external-channel-harness.ts)
4385
+ is the reference composition for webhooks, polling transports and local-device
4386
+ adapters. Its generic boundary injects a runtime, durable store and delivery
4387
+ adapter; the optional
4388
+ [`external-channel-grammy.ts`](../../packages/core/examples/external-channel-grammy.ts)
4389
+ attaches the same ingress function to grammY polling or webhook lifecycle
4390
+ without putting provider types in the agent runtime.
4391
+
4392
+ Inbound update identity, principal resolution, conversation mapping and reply
4393
+ target are application policy. Persist and deduplicate the update before
4394
+ `runtime.submit`, use the stored idempotency key on crash recovery, then persist
4395
+ the admitted `runId`. A duplicate arriving after restart resolves to that same
4396
+ mapping instead of creating another model turn.
4397
+
4398
+ For output, choose `terminal-only` or `streaming` explicitly. Stable durable
4399
+ `eventId` values and transient `(runtimeEpoch, sequence)` identities become
4400
+ outbox keys; the application store assigns causal ordinals. A bounded channel
4401
+ is only a process-local wakeup and never the durable authority. Before sending,
4402
+ persist one of these states:
4403
+
4404
+ | State | Recovery action |
4405
+ | --- | --- |
4406
+ | `not-dispatched` | may dispatch once |
4407
+ | `possibly-dispatched` | reconcile with the adapter or remain unresolved |
4408
+ | `acknowledged` | deduplicate; delivery is complete |
4409
+
4410
+ The agent `terminal` event and the adapter's delivery receipt are intentionally
4411
+ different records. A successful run does not prove that a reply reached its
4412
+ channel, and a delivery failure never rewrites the canonical agent result.
4413
+ Shutdown stops ingress, drains accepted process-local work and leaves ambiguous
4414
+ outbox records visible for a later reconciliation pass. Stitchkit does not own
4415
+ a channel database, durable broker, provider payload schema or application
4416
+ identity policy.
4417
+
4266
4418
  Durable event IDs are derived from run, event type and snapshot version. Use
4267
4419
  `advanceAgentRuntimeEventCursor` to classify delivery.
4268
4420
 
@@ -11561,7 +11713,7 @@ Server-only optional application runtime. See the
11561
11713
  | `AgentSessionCloseOptions` | _type_ | `gracePeriodMs` for natural settlement, then abort, then `forceTimeoutMs` for bounded settlement after it |
11562
11714
  | `AgentSessionCloseResult` | _type_ | what `close()` achieved: `settled`, or `timedOut` with `remaining` runs still in flight. Only omitting `forceTimeoutMs` guarantees nothing is in flight on return |
11563
11715
  | `AgentHistoryProjectionOptions` | _type_ | storage-neutral file resolver, explicit unresolved-file behavior, and how an interrupted turn reaches the model (`interruptedAssistant`) |
11564
- | `createAgentToolFenceLifecycle` | function | pre-effect and post-effect run ownership fence for `mountAgent` |
11716
+ | `createAgentToolFenceLifecycle` | function | pre-effect and post-effect run ownership fence for `mountAgent`; compose beside application idempotency for [durable operations](../guide/mcp-and-agents.md#durable-application-owned-execution) |
11565
11717
  | `AgentRuntimeEventSchema` | schema | transient stream lifecycle plus post-commit admission/checkpoint/run-state/terminal projections |
11566
11718
  | `createAgentObservability` | function | separate agent-run sink over the shared bounded observability lifecycle |
11567
11719
 
@@ -11697,6 +11849,33 @@ Use this entrypoint from client components and shared DTO packages. The full
11697
11849
  | `openRouterProvider` | function | isolated `@openrouter/ai-sdk-provider` language-model factory |
11698
11850
  | `OpenRouterProviderSettings` | _type_ | official provider settings accepted by the factory |
11699
11851
 
11852
+ ## `stitchkit/agent-runtime/sqlite/bun`
11853
+
11854
+ Bun built-in SQLite persistence. The entrypoint imports `bun:sqlite` and is not
11855
+ loaded by the neutral, browser or Node runtime surfaces.
11856
+
11857
+ | Export | Kind | Summary |
11858
+ |--------|------|---------|
11859
+ | `createBunSqliteAgentRuntimeStore` | function | open an owned Bun SQLite connection, initialize/validate schema v1 and return `{ store, close }` |
11860
+ | `BunSqliteAgentRuntimeStoreConfig` | _type_ | database filename plus optional create and initialization policies |
11861
+ | `createSqliteAgentRuntimeStore` | function | build the normalized store over an injected synchronous SQLite boundary |
11862
+ | `initializeAgentRuntimeSqlite` | function | initialize or validate only Stitchkit's namespaced SQLite schema |
11863
+ | `AgentRuntimeSqliteDatabase` / `AgentRuntimeSqliteStatement` / `AgentRuntimeSqliteValue` | _type_ | minimal runtime-neutral synchronous SQLite boundary |
11864
+ | `SqliteAgentRuntimeStore` / `SqliteAgentRuntimeStoreConfig` | _type_ | durable store handle, owned connection lifecycle and initialization policy |
11865
+
11866
+ ## `stitchkit/agent-runtime/sqlite/node`
11867
+
11868
+ Node 22.5+ built-in SQLite persistence. It shares the schema and semantics of
11869
+ the Bun leaf but imports only `node:sqlite`.
11870
+
11871
+ | Export | Kind | Summary |
11872
+ |--------|------|---------|
11873
+ | `createNodeSqliteAgentRuntimeStore` | function | open an owned Node `DatabaseSync`, initialize/validate schema v1 and return `{ store, close }` |
11874
+ | `NodeSqliteAgentRuntimeStoreConfig` | _type_ | database filename plus optional read-only and initialization policies; read-only requires an initialized schema |
11875
+ | `createSqliteAgentRuntimeStore` / `initializeAgentRuntimeSqlite` | function | shared normalized adapter and namespaced schema lifecycle |
11876
+ | `AgentRuntimeSqliteDatabase` / `AgentRuntimeSqliteStatement` / `AgentRuntimeSqliteValue` | _type_ | minimal runtime-neutral synchronous SQLite boundary |
11877
+ | `SqliteAgentRuntimeStore` / `SqliteAgentRuntimeStoreConfig` | _type_ | durable store handle, owned connection lifecycle and initialization policy |
11878
+
11700
11879
  ## `stitchkit/observability`
11701
11880
 
11702
11881
  Server-only. The audit layer one level above the raw hooks — W3C trace context,
@@ -11923,8 +12102,8 @@ runtime-tool runner, plus deliberate raw MCP adapters over the same mechanics.
11923
12102
  | `NativeToolIdentity` | _type_ | pathless service/action/scope/meta identity; semantic method is factory-owned |
11924
12103
  | `ManagedWaitRender` | _type_ | optional managed wait terminal text and failure classification |
11925
12104
  | `UploadToolInputSchema` | constant | fixed `{ path: string }` input schema for `defineUploadTool` |
11926
- | `defineAsyncOperation` | function | runtime-only start/status/wait plus configured cancel/result/artifacts definitions |
11927
- | `defineAsyncOperationContract` | function | define one canonical Zod-first HTTP contract for start/status/wait plus optional capabilities |
12105
+ | `defineAsyncOperation` | function | runtime-only start/status/wait plus configured cancel/result/artifacts definitions; see the [durable application-owned recipe](../guide/mcp-and-agents.md#durable-application-owned-execution) |
12106
+ | `defineAsyncOperationContract` | function | define one canonical Zod-first HTTP contract for start/status/wait plus optional capabilities; execution and recovery remain application-owned |
11928
12107
  | `bindContractAsyncOperation` | function | bind literal methods from an existing contract without creating another HTTP surface |
11929
12108
  | `createAsyncOperationSnapshotSchema` | function | canonical pending/running/succeeded/failed/cancelled Zod snapshot |
11930
12109
  | `AsyncOperationCancelResultSchema` | constant | validated accepted/already_terminal/rejected cancellation result |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.68.7",
3
+ "version": "0.68.9",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",
@@ -92,6 +92,14 @@
92
92
  "types": "./dist/agent-runtime-openrouter.d.ts",
93
93
  "import": "./dist/agent-runtime-openrouter.js"
94
94
  },
95
+ "./agent-runtime/sqlite/bun": {
96
+ "types": "./dist/agent-runtime-sqlite-bun.d.ts",
97
+ "import": "./dist/agent-runtime-sqlite-bun.js"
98
+ },
99
+ "./agent-runtime/sqlite/node": {
100
+ "types": "./dist/agent-runtime-sqlite-node.d.ts",
101
+ "import": "./dist/agent-runtime-sqlite-node.js"
102
+ },
95
103
  "./application": {
96
104
  "types": "./dist/application.d.ts",
97
105
  "import": "./dist/application.js"
@@ -127,7 +135,7 @@
127
135
  "scripts": {
128
136
  "check": "bun x tsc --noEmit",
129
137
  "build:browser": "bun build src/index.ts src/react.ts src/contract/index.ts src/declaration.ts src/agent-runtime-browser.ts --outdir dist --target node --packages external --splitting --root src",
130
- "build:server": "bun build src/server/index.ts src/node.ts src/tools.ts src/tool-invoker.ts src/cli.ts src/remote.ts src/files.ts src/testing.ts src/observability/index.ts src/agent-runtime.ts src/agent-runtime-openrouter.ts src/application.ts src/application-grammy.ts src/application-opentelemetry.ts --outdir dist --target node --packages external --splitting --root src",
138
+ "build:server": "bun build src/server/index.ts src/node.ts src/tools.ts src/tool-invoker.ts src/cli.ts src/remote.ts src/files.ts src/testing.ts src/observability/index.ts src/agent-runtime.ts src/agent-runtime-openrouter.ts src/agent-runtime-sqlite-bun.ts src/agent-runtime-sqlite-node.ts src/application.ts src/application-grammy.ts src/application-opentelemetry.ts --outdir dist --target node --packages external --splitting --root src",
131
139
  "build:js": "bun run build:browser && bun run build:server && bun scripts/preserve-webpack-ignore.mjs",
132
140
  "build:types": "bun x tsc -p tsconfig.build.json --emitDeclarationOnly && bun scripts/rewrite-declaration-specifiers.mjs",
133
141
  "build": "rm -rf dist && bun run build:js && bun run build:types && bun scripts/check-browser-clean.mjs && bun scripts/check-env-live.mjs && bun scripts/check-public-types.mjs",