stitchkit 0.68.0 → 0.68.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/dist/agent-runtime/admission-lanes.d.ts +1 -1
  2. package/dist/agent-runtime/compaction.d.ts +2 -2
  3. package/dist/agent-runtime/events.d.ts +1 -1
  4. package/dist/agent-runtime/history.d.ts +1 -1
  5. package/dist/agent-runtime/history.d.ts.map +1 -1
  6. package/dist/agent-runtime/injection.d.ts +1 -1
  7. package/dist/agent-runtime/managed-tools.d.ts +3 -3
  8. package/dist/agent-runtime/models.d.ts +1 -1
  9. package/dist/agent-runtime/observability.d.ts +1 -1
  10. package/dist/agent-runtime/prompt.d.ts +1 -1
  11. package/dist/agent-runtime/prompt.d.ts.map +1 -1
  12. package/dist/agent-runtime/protocol.d.ts +19 -1
  13. package/dist/agent-runtime/protocol.d.ts.map +1 -1
  14. package/dist/agent-runtime/run-execution.d.ts +5 -5
  15. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  16. package/dist/agent-runtime/runtime-internals.d.ts +1 -1
  17. package/dist/agent-runtime/runtime-result.d.ts +1 -1
  18. package/dist/agent-runtime/runtime.d.ts +14 -12
  19. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  20. package/dist/agent-runtime/store-driver.d.ts +2 -2
  21. package/dist/agent-runtime/store.d.ts +2 -2
  22. package/dist/agent-runtime/terminal-commit.d.ts +2 -2
  23. package/dist/agent-runtime/terminal-status.d.ts +1 -1
  24. package/dist/agent-runtime-openrouter.d.ts +1 -1
  25. package/dist/agent-runtime.d.ts +15 -15
  26. package/dist/agent-runtime.d.ts.map +1 -1
  27. package/dist/agent-runtime.js +87 -26
  28. package/dist/application/admission.d.ts +1 -1
  29. package/dist/application/events.d.ts +2 -2
  30. package/dist/application/grammy.d.ts +2 -2
  31. package/dist/application/graph.d.ts +1 -1
  32. package/dist/application/health.d.ts +1 -1
  33. package/dist/application/kernel.d.ts +3 -3
  34. package/dist/application/opentelemetry.d.ts +3 -3
  35. package/dist/application/resource.d.ts +1 -1
  36. package/dist/application/schedule.d.ts +1 -1
  37. package/dist/application/server-resource.d.ts +7 -9
  38. package/dist/application/server-resource.d.ts.map +1 -1
  39. package/dist/application-grammy.d.ts +1 -1
  40. package/dist/application-opentelemetry.d.ts +1 -1
  41. package/dist/application.d.ts +11 -11
  42. package/dist/application.js +7 -7
  43. package/dist/browser/client-multipart.d.ts +1 -1
  44. package/dist/browser/client-url.d.ts +2 -2
  45. package/dist/browser/client.d.ts +4 -4
  46. package/dist/browser/client.d.ts.map +1 -1
  47. package/dist/browser/contract-stream.d.ts +1 -1
  48. package/dist/browser/http.d.ts +7 -7
  49. package/dist/browser/http.d.ts.map +1 -1
  50. package/dist/browser/socket-io.d.ts +12 -31
  51. package/dist/browser/socket-io.d.ts.map +1 -1
  52. package/dist/browser/stream.d.ts +2 -2
  53. package/dist/cli.d.ts +6 -6
  54. package/dist/cli.js +4 -3
  55. package/dist/contract/errors-factory.d.ts +1 -1
  56. package/dist/contract/factory.d.ts +1 -1
  57. package/dist/contract/index.d.ts +7 -7
  58. package/dist/files/boundary.d.ts +1 -1
  59. package/dist/files.d.ts +2 -2
  60. package/dist/{index-zd4v31v2.js → index-2ve29dzn.js} +3 -3
  61. package/dist/{index-nymn7wbg.js → index-3vq6we8m.js} +29 -17
  62. package/dist/index-7etq650s.js +75 -0
  63. package/dist/{index-7pn02bgv.js → index-cszjsxy5.js} +22 -83
  64. package/dist/index-g2j2m6vv.js +63 -0
  65. package/dist/index.d.ts +10 -10
  66. package/dist/index.js +4 -4
  67. package/dist/internal/errors.d.ts +1 -1
  68. package/dist/internal/observability-sink.d.ts +1 -1
  69. package/dist/node.d.ts +11 -11
  70. package/dist/node.d.ts.map +1 -1
  71. package/dist/node.js +2 -2
  72. package/dist/observability/audit.d.ts +5 -5
  73. package/dist/observability/context.d.ts +2 -2
  74. package/dist/observability/event.d.ts +2 -2
  75. package/dist/observability/index.d.ts +6 -6
  76. package/dist/react/entity-cache.d.ts +26 -1
  77. package/dist/react/entity-cache.d.ts.map +1 -1
  78. package/dist/react.d.ts +3 -3
  79. package/dist/react.d.ts.map +1 -1
  80. package/dist/react.js +136 -38
  81. package/dist/realtime/contract.d.ts +1 -1
  82. package/dist/realtime/index.d.ts +4 -4
  83. package/dist/realtime/rejection.d.ts +1 -1
  84. package/dist/realtime/request.d.ts +1 -1
  85. package/dist/realtime/socket.d.ts +2 -2
  86. package/dist/remote.d.ts +1 -1
  87. package/dist/remote.js +1 -1
  88. package/dist/server/bun.d.ts +3 -3
  89. package/dist/server/context-contribution.d.ts +1 -1
  90. package/dist/server/context.d.ts +4 -4
  91. package/dist/server/contract-stream.d.ts +2 -2
  92. package/dist/server/create.d.ts +1 -1
  93. package/dist/server/error-hook.d.ts +3 -3
  94. package/dist/server/file.d.ts +1 -1
  95. package/dist/server/implement.d.ts +2 -2
  96. package/dist/server/index.d.ts +31 -31
  97. package/dist/server/index.d.ts.map +1 -1
  98. package/dist/server/index.js +9 -9
  99. package/dist/server/lifecycle.d.ts +1 -1
  100. package/dist/server/logging.d.ts +1 -1
  101. package/dist/server/middleware/auth.d.ts +2 -2
  102. package/dist/server/multipart.d.ts +2 -2
  103. package/dist/server/node.d.ts +2 -2
  104. package/dist/server/openapi.d.ts +1 -1
  105. package/dist/server/process-signal-common.d.ts +1 -1
  106. package/dist/server/process-signals.d.ts +1 -1
  107. package/dist/server/realtime.d.ts +4 -4
  108. package/dist/server/response-metadata.d.ts +1 -1
  109. package/dist/server/router.d.ts +1 -1
  110. package/dist/server/shutdown.d.ts +1 -1
  111. package/dist/server/socket-io-node.d.ts +3 -3
  112. package/dist/server/socket-io.d.ts +6 -6
  113. package/dist/server/streaming-route.d.ts +2 -2
  114. package/dist/server/types.d.ts +6 -6
  115. package/dist/server/unix-client-body.d.ts +1 -1
  116. package/dist/server/unix-client-body.d.ts.map +1 -1
  117. package/dist/server/unix-client-bun.d.ts +1 -1
  118. package/dist/server/unix-client-bun.d.ts.map +1 -1
  119. package/dist/server/unix-client.d.ts +16 -5
  120. package/dist/server/unix-client.d.ts.map +1 -1
  121. package/dist/testing/agent-store-conformance.d.ts +1 -1
  122. package/dist/testing/managed-resource-conformance-contract.d.ts +1 -1
  123. package/dist/testing/managed-resource-conformance-driver.d.ts +2 -2
  124. package/dist/testing/managed-resource-conformance-scenarios.d.ts +2 -2
  125. package/dist/testing/managed-resource-conformance.d.ts +2 -2
  126. package/dist/testing/surface-conformance.d.ts +3 -3
  127. package/dist/testing/surface-manifest.d.ts +5 -5
  128. package/dist/testing.d.ts +8 -8
  129. package/dist/testing.js +1 -1
  130. package/dist/tool-invoker.d.ts +9 -0
  131. package/dist/tool-invoker.d.ts.map +1 -0
  132. package/dist/tool-invoker.js +16 -0
  133. package/dist/tools/agent.d.ts +4 -4
  134. package/dist/tools/async-operation.d.ts +3 -3
  135. package/dist/tools/cli-command.d.ts +3 -3
  136. package/dist/tools/cli-format.d.ts +1 -1
  137. package/dist/tools/cli-policy.d.ts +1 -1
  138. package/dist/tools/cli-wait.d.ts +1 -1
  139. package/dist/tools/cli.d.ts +7 -7
  140. package/dist/tools/define-download-tool.d.ts +4 -4
  141. package/dist/tools/define-upload-tool.d.ts +3 -3
  142. package/dist/tools/define-view-file-tool.d.ts +3 -3
  143. package/dist/tools/define-wait-tool.d.ts +2 -2
  144. package/dist/tools/download-core.d.ts +2 -2
  145. package/dist/tools/execute.d.ts +2 -2
  146. package/dist/tools/flatten-join.d.ts +1 -1
  147. package/dist/tools/internal/surface-projector.d.ts +3 -3
  148. package/dist/tools/invoker.d.ts +4 -4
  149. package/dist/tools/lifecycle.d.ts +1 -1
  150. package/dist/tools/list-names.d.ts +2 -2
  151. package/dist/tools/managed-file-error.d.ts +1 -1
  152. package/dist/tools/manifest.d.ts +3 -3
  153. package/dist/tools/mcp-handler.d.ts +4 -4
  154. package/dist/tools/mcp-prepare.d.ts +8 -8
  155. package/dist/tools/mcp-round-policy.d.ts +1 -1
  156. package/dist/tools/mcp-round.d.ts +3 -3
  157. package/dist/tools/mcp-stdio-signals.d.ts +2 -2
  158. package/dist/tools/mcp-stdio.d.ts +3 -3
  159. package/dist/tools/mcp.d.ts +7 -7
  160. package/dist/tools/mount-download.d.ts +1 -1
  161. package/dist/tools/mount-upload.d.ts +1 -1
  162. package/dist/tools/mount.d.ts +5 -5
  163. package/dist/tools/native-definition.d.ts +2 -2
  164. package/dist/tools/native-mcp.d.ts +3 -3
  165. package/dist/tools/oauth-metadata.d.ts +1 -1
  166. package/dist/tools/oauth-provider.d.ts +1 -1
  167. package/dist/tools/presentation.d.ts +1 -1
  168. package/dist/tools/remote.d.ts +3 -3
  169. package/dist/tools/runtime-tool.d.ts +2 -2
  170. package/dist/tools/surface.d.ts +5 -5
  171. package/dist/tools/tool-logger.d.ts +1 -1
  172. package/dist/tools/toolkit.d.ts +7 -7
  173. package/dist/tools/transports.d.ts +2 -2
  174. package/dist/tools/upload-core.d.ts +1 -1
  175. package/dist/tools/view-file.d.ts +1 -1
  176. package/dist/tools.d.ts +42 -42
  177. package/dist/tools.js +18 -61
  178. package/llms-full.txt +196 -20
  179. package/package.json +8 -4
  180. package/dist/{index-avjd67h6.js → index-cz32amcb.js} +3 -3
package/llms-full.txt CHANGED
@@ -51,6 +51,7 @@ own, recorded as an ADR.
51
51
  | `stitchkit/server` | server (Bun) | stable | `createServer`, `implement`, hooks, auth, Socket.IO server, server primitives |
52
52
  | `stitchkit/node` | server (Node ≥ 22) | stable | `serveNode` + the runtime-agnostic core — the Node mirror of `/server` |
53
53
  | `stitchkit/tools` | server | stable | `createMcpHandler`, `mountMcp`, `mountAgent`, the OAuth provider, native tools |
54
+ | `stitchkit/tools/invoker` | server | stable | peer-free `createToolInvoker` over the canonical contract tool runner |
54
55
  | `stitchkit/cli` | server | stable | `createCli` — the CLI transport, light (no MCP SDK / `ai`) |
55
56
  | `stitchkit/remote` | browser **and** server | stable | peer-free `implementRemote` for thin HTTP proxy processes |
56
57
  | `stitchkit/files` | server (Bun or Node) | stable | peer-free managed local-file boundary |
@@ -159,7 +160,8 @@ map — feature → packages:
159
160
  | anything (validation) | `zod` |
160
161
  | `createServer` (Bun) | — (uses `Bun.serve`) |
161
162
  | `serveNode` (Node ≥ 22) | `srvx` (+ `@types/bun` dev) |
162
- | MCP / agent tools (`stitchkit/tools`) | `@modelcontextprotocol/server` `ai` |
163
+ | In-process contract tools (`stitchkit/tools/invoker`) | |
164
+ | MCP / agent adapters (`stitchkit/tools`) | `@modelcontextprotocol/server` `ai` |
163
165
  | Agent application runtime (`stitchkit/agent-runtime`) | `ai` |
164
166
  | OpenRouter runtime adapter (`stitchkit/agent-runtime/openrouter`) | `ai` `@openrouter/ai-sdk-provider` |
165
167
  | MCP host/client tests | `@modelcontextprotocol/client` |
@@ -167,7 +169,7 @@ map — feature → packages:
167
169
  | React data layer (`stitchkit/react`) | `@tanstack/react-query` `react-query-kit` |
168
170
  | **Socket.IO server on Bun** | `socket.io` `@socket.io/bun-engine` |
169
171
  | **Socket.IO server on Node** | `socket.io` |
170
- | Socket.IO client | `socket.io-client` (brings `@socket.io/component-emitter`, which the browser declarations reference for types only) |
172
+ | Socket.IO client | `socket.io-client` (runtime peer; unrelated root declarations remain peer-free) |
171
173
  | grammY lifecycle adapters (`stitchkit/application/grammy`) | `grammy` |
172
174
  | OpenTelemetry gauges (`stitchkit/application/opentelemetry`) | `@opentelemetry/api` |
173
175
 
@@ -1914,12 +1916,43 @@ socket, and a missing socket cannot fall through to that host over TCP. Defaults
1914
1916
  are 16 MiB request/response bodies, 64 KiB headers, 30 s to response headers,
1915
1917
  eight connections and five redirects.
1916
1918
 
1919
+ `maxHeaderBytes` is enforced before exposing a response. Bun's owned parser
1920
+ counts the complete response head in wire bytes, including the status line and
1921
+ terminating blank line. Node passes the same configured integer unchanged to
1922
+ `http.request({ maxHeaderSize })`, so its native parser's documented header-size
1923
+ accounting is authoritative there. Exceeding either ceiling yields
1924
+ `UNIX_HEADERS_TOO_LARGE` with `delivery: 'response-received'`. A stalled body
1925
+ pauses its socket, and resuming preserves the exact chunked body.
1926
+
1917
1927
  `UnixClientTransportError` carries a stable `code` and `delivery`:
1918
1928
  `not-dispatched`, `possibly-dispatched` or `response-received`. Only the first
1919
1929
  proves that the remote operation did not begin; Stitchkit never silently retries
1920
1930
  an ambiguous write. Response consumption/cancellation belongs to the operation,
1921
1931
  and `close()` interrupts active work and destroys owned connections.
1922
1932
 
1933
+ The response total is a unary-body policy, not a stream-buffer measurement. A
1934
+ long-lived NDJSON/SSE client opts into streaming explicitly instead of choosing
1935
+ an arbitrarily large integer:
1936
+
1937
+ ```ts
1938
+ const streamTransport = createUnixClientTransport({
1939
+ socketPath: '/run/my-daemon.sock',
1940
+ responseBodyMode: 'streaming',
1941
+ })
1942
+ const streamClient = createClient(streamContract, {
1943
+ baseUrl: 'http://my-daemon',
1944
+ fetch: streamTransport.fetch,
1945
+ })
1946
+ ```
1947
+
1948
+ `streaming` removes only the cumulative lifetime response limit. It cannot be
1949
+ combined with `maxResponseBytes`; request/header/connection bounds, socket
1950
+ pause/resume, cancellation and strict HTTP framing remain active. The stream
1951
+ descriptor's `maxFrameBytes` bounds each protocol frame, and the application
1952
+ still owns any queue it builds after consuming those frames. Use a separate
1953
+ default transport for finite calls that must retain the 16 MiB unary ceiling.
1954
+ The adapter never infers this policy from `Content-Type`. → ADR 0125.
1955
+
1923
1956
  The legacy `createHttpClient({ unix: '/absolute/path' })` spelling remains a
1924
1957
  Bun-only convenience. On a non-Bun runtime it now refuses before dispatch
1925
1958
  instead of ignoring the selection and dialing TCP. `unix` and an injected
@@ -2028,12 +2061,58 @@ Abort and timeout do not emit `network_error` and are not retried. The same
2028
2061
  options work for query, JSON, multipart and raw-response calls. Stitchkit does
2029
2062
  not expose upload progress: Fetch has no portable upload-progress primitive.
2030
2063
 
2064
+ An injected transport failure is normalized to `UNKNOWN_ERROR` while its exact
2065
+ object remains available as `ApiError.cause`. This is how a bounded adapter can
2066
+ preserve facts the generic client cannot invent — for example a Unix transport's
2067
+ `not-dispatched`, `possibly-dispatched` or `response-received` state. Never replay
2068
+ an effect from `UNKNOWN_ERROR` alone; inspect the owned adapter's cause and retry
2069
+ only when it proves that dispatch did not happen.
2070
+
2031
2071
  For an endpoint without contract arguments, pass only the options object:
2032
2072
 
2033
2073
  ```ts
2034
2074
  await api.health.withOptions({ signal: controller.signal })
2035
2075
  ```
2036
2076
 
2077
+ ### Injected delivery adapters
2078
+
2079
+ `ClientFetch` is the narrow composition seam for application-owned delivery.
2080
+ The contract still owns operation identity, request serialization and response
2081
+ validation; the adapter owns I/O, bounds and dispatch certainty:
2082
+
2083
+ ```ts
2084
+ import { type ClientFetch, createClient } from 'stitchkit'
2085
+
2086
+ const delivery: ClientFetch = async (input, init) => {
2087
+ // Fixed deployment destination and policy are chosen here, not by caller data.
2088
+ return boundedFetch(input, { ...init, signal: init?.signal })
2089
+ }
2090
+
2091
+ const query = createClient(queryContract, {
2092
+ baseUrl: 'https://service.internal',
2093
+ fetch: delivery,
2094
+ })
2095
+ const work = createClient(requestWorkContract, {
2096
+ baseUrl: 'https://service.internal',
2097
+ fetch: delivery,
2098
+ })
2099
+ ```
2100
+
2101
+ The same adapter accepts unrelated contract shapes without learning their DTOs
2102
+ or operation inventory. `createClient` chooses method/path from the contract,
2103
+ serializes only the declared arguments, forwards `.withOptions(..., { signal })`
2104
+ and validates the response through the endpoint's output schema. A caller payload
2105
+ cannot replace the configured base URL or reserved operation path.
2106
+
2107
+ Contract metadata describes an effect; it does not authorize one. Authentication,
2108
+ scope and destination policy remain in the application/server boundary. A schema
2109
+ mismatch is an explicit validation failure and is not retried automatically. A
2110
+ timeout means the caller stopped waiting, not that the remote effect did not run.
2111
+
2112
+ Published declarations are checked from a clean tarball under both bundler and
2113
+ NodeNext resolution. The HTTP-only NodeNext proof uses `skipLibCheck: false` and
2114
+ installs no Socket.IO peer. → ADR 0120.
2115
+
2037
2116
  ### Many contracts at once
2038
2117
 
2039
2118
  ```ts
@@ -2170,6 +2249,7 @@ try {
2170
2249
  err.details // structured details, if any
2171
2250
  err.hint // optional hint
2172
2251
  err.traceId // x-request-id — correlate this failure with backend logs
2252
+ err.cause // concrete injected transport failure, when delivery failed
2173
2253
  }
2174
2254
  }
2175
2255
  ```
@@ -2468,7 +2548,7 @@ AI SDK `ToolSet` and call its transport adapter manually. Compile an in-process
2468
2548
  invoker once and call the shared framework runner directly:
2469
2549
 
2470
2550
  ```ts
2471
- import { createToolInvoker } from 'stitchkit/tools'
2551
+ import { createToolInvoker } from 'stitchkit/tools/invoker'
2472
2552
 
2473
2553
  const invoker = createToolInvoker(services, {
2474
2554
  transport: 'AGENT', // required exposure policy
@@ -2497,6 +2577,11 @@ recursive calls without retaining request state. Every invocation gets a fresh
2497
2577
  tool-call context and runs the same extension resolution, input/output
2498
2578
  validation, lifecycle, hooks and output-strip reporter as mounted tools.
2499
2579
 
2580
+ The dedicated entrypoint needs only the normal `stitchkit`/`zod` install. Use
2581
+ the broader `stitchkit/tools` barrel when the same program also mounts MCP or AI
2582
+ adapters and has installed their optional peers. Both imports reach the same
2583
+ runner; this is dependency isolation, not a second execution implementation.
2584
+
2500
2585
  `invoke` returns the canonical discriminated `ToolResult`, not an AI SDK or MCP
2501
2586
  presentation envelope. `invokeOrThrow` returns validated data and throws the
2502
2587
  runner's normalized `AppError` on failure, preserving an application error's
@@ -3772,6 +3857,14 @@ const store = createAgentRuntimeStore({
3772
3857
  })
3773
3858
  ```
3774
3859
 
3860
+ Prompt budgeting keeps reservation deficits signed. If instructions,
3861
+ `reservedOutput`, tool schemas, attachments and provider overhead already exceed
3862
+ `contextWindow`, `composeAgentPrompt` returns `contextDecision: 'oversized'`
3863
+ and a negative `availableHistoryTokens` even when history is empty. A `compact`
3864
+ policy is returned only when removing history could actually make the prompt
3865
+ fit. Exact equality (including a zero window with zero reservations/history)
3866
+ fits; any unavailable component keeps the decision `unavailable`.
3867
+
3775
3868
  The same opaque `tx` reaches head, run, admission and history callbacks. The adapter maps rows
3776
3869
  and supplies atomicity; Stitchkit owns transition validation and revision
3777
3870
  arithmetic. The executable reference is
@@ -4099,6 +4192,24 @@ is the reserved built-in policy name. `loop.prepareStep` is the controlled AI
4099
4192
  SDK step boundary for changing active tools, model, instructions or messages.
4100
4193
  It cannot replace the managed tool set or bypass its lifecycle fence.
4101
4194
 
4195
+ Completion validity belongs to the protocol and is checked before the terminal
4196
+ CAS. Protocols that require a visible answer opt in explicitly:
4197
+
4198
+ ```ts
4199
+ const protocol = defineAgentProtocol({
4200
+ context: ContextSchema,
4201
+ inputMetadata: InputMetadataSchema,
4202
+ terminalAcceptance: 'require-output',
4203
+ })
4204
+ ```
4205
+
4206
+ The built-in rule accepts non-blank text, generated files, structured provider
4207
+ parts, and a named tool-only `policy_stop`. The default is `allow-empty` for
4208
+ protocols where an empty acknowledgement is meaningful. Pass a callback when
4209
+ the product has a narrower definition; it receives the candidate message,
4210
+ terminal reason and optional policy name, and runs before persistence. A false
4211
+ result fails the candidate instead of rewriting an already committed success.
4212
+
4102
4213
  `loop.idleTimeoutMs` is inactivity, not total duration: the deadline resets on
4103
4214
  every model stream event. A stalled call aborts with durable reason `timeout`;
4104
4215
  user interruption and shutdown remain distinct.
@@ -4121,7 +4232,10 @@ effect must be replay-safe.
4121
4232
  ## History, provider metadata and files
4122
4233
 
4123
4234
  `projectAgentHistory` converts canonical engine records into provider-valid AI
4124
- SDK messages and pairs tool calls/results. Provider-required metadata is kept
4235
+ SDK messages and pairs tool calls/results in persisted causal order. Adjacent
4236
+ parallel calls stay in one assistant round and their adjacent results stay in
4237
+ one tool round; a dependent call after those results starts a new assistant
4238
+ round, and trailing final text remains after the last tool result. Provider-required metadata is kept
4125
4239
  in a versioned opaque envelope and omitted from product delivery by default.
4126
4240
  `projectAgentHistoryDetailed` additionally returns one inspectable decision per canonical record;
4127
4241
  leading assistant records, crash drafts and unmatched tool chronology are never silently passed to
@@ -4358,10 +4472,12 @@ const cleanup = createManagedSchedule({
4358
4472
  const http = managedServerResource({
4359
4473
  id: 'http',
4360
4474
  dependsOn: [database],
4361
- // Called during `start`, after `database` is ready which is how "bind the
4362
- // port once the database is up" is expressed. Pass an already-running server
4363
- // instead when the application created it itself.
4364
- server: () => createServer({ port: env.PORT, services }),
4475
+ // Called during `start`, after `database` is ready. The factory receives the
4476
+ // same declared-dependency and startup-signal context as any resource.
4477
+ server: (context) => {
4478
+ const db = context.use(database)
4479
+ return createServer({ port: env.PORT, services: createServices(db) })
4480
+ },
4365
4481
  })
4366
4482
 
4367
4483
  const app = createApplication({
@@ -4449,6 +4565,12 @@ Declare the dependency with the **resource**, not its id, whenever you intend to
4449
4565
  read from it: that is the form `use` can type, and it keeps the declaration and
4450
4566
  the read from drifting apart. A string still works when all you need is order.
4451
4567
 
4568
+ `managedServerResource` follows the same rule. Its factory receives this context
4569
+ during `start`, so constructing routes from a database/service/socket value does
4570
+ not need an outer mutable handoff or a custom `start` override. A zero-argument
4571
+ factory remains valid when it needs only ordering, and an already-running handle
4572
+ can still be passed directly. → ADR 0121.
4573
+
4452
4574
  The value is published when `start` resolves and stays readable for the rest of
4453
4575
  the application's life — from `activate` and from the shutdown phases too, where
4454
4576
  a dependant may still need the handle it was given.
@@ -5071,7 +5193,10 @@ already-listening server and it adopts that one instead.
5071
5193
  const http = managedServerResource({
5072
5194
  id: 'http',
5073
5195
  dependsOn: [database],
5074
- server: () => createServer({ port: env.PORT, services }),
5196
+ server: (context) => {
5197
+ const db = context.use(database)
5198
+ return createServer({ port: env.PORT, services: createServices(db) })
5199
+ },
5075
5200
  })
5076
5201
 
5077
5202
  const app = createApplication({ id: 'service', resources: [database, http] })
@@ -5082,6 +5207,11 @@ The server resource publishes its `ManagedServerHandle`, so anything that needs
5082
5207
  the running server — a Socket.IO attachment, a URL to log, a probe — reads it
5083
5208
  with `context.use(http)` rather than through a module-local.
5084
5209
 
5210
+ The factory itself receives `ManagedResourceContext` too. It can read only the
5211
+ dependencies declared on the server resource and shares the graph's startup
5212
+ signal. A dependency failure prevents the factory from binding; a factory
5213
+ rejection is rolled back without invoking the factory a second time.
5214
+
5085
5215
  Do not spread this resource over your own `start` to control creation order:
5086
5216
  that shape exists only as a workaround for the version whose `start` was empty,
5087
5217
  and `dependsOn` now expresses the order directly. The executable recipe binds a
@@ -5995,6 +6125,36 @@ page metadata and `pageParams`; an infinite create changes only the selected
5995
6125
  edge page (`createAt: 'start' | 'end'`). Creates are deduplicated across every
5996
6126
  cached page. `updateMissing` makes an absent update explicitly skip or insert.
5997
6127
 
6128
+ Filtered query families can additionally declare membership per exact key and
6129
+ evidence-aware total reconciliation:
6130
+
6131
+ ```ts
6132
+ list: {
6133
+ key: ['tickets'],
6134
+ shape: 'infinite-paginated',
6135
+ createAt: 'start',
6136
+ updateMissing: 'skip',
6137
+ membership: {
6138
+ evaluate: (event, queryKey) => membershipFor(event, queryKey),
6139
+ unknown: 'invalidate',
6140
+ },
6141
+ total: {
6142
+ mode: 'reconcile',
6143
+ unknown: 'invalidate',
6144
+ delta: ({ event, present, membership }) => provenDelta(event, present, membership),
6145
+ },
6146
+ }
6147
+ ```
6148
+
6149
+ Membership is `include | exclude | unknown`. An excluded update removes an
6150
+ existing row; an included one follows `updateMissing`. Unknown evidence never
6151
+ guesses and either preserves or invalidates the exact query. The conservative
6152
+ total policy increments only a non-duplicate create and decrements only a
6153
+ delete/update whose membership is observed; unseen IDs are `unknown`. Supply
6154
+ `delta` only when the event itself proves a stronger transition. Every page's
6155
+ numeric `total` changes together while cursor metadata and `pageParams` remain
6156
+ unchanged.
6157
+
5998
6158
  The event entity may be richer than a list row. Keep the full value in detail
5999
6159
  cache, project it for lists, and provide the same comparator the backend uses:
6000
6160
 
@@ -6032,9 +6192,9 @@ deleted payload without guessing. The same resolved detail key drives the
6032
6192
  `isFresh` echo guard. Shape checks also leave neighbouring detail caches alone
6033
6193
  when a list key is intentionally used as a partial query-key prefix.
6034
6194
 
6035
- The helper deliberately does **not** flatten pages, update totals, derive a
6036
- sort order or replace arbitrary `setQueryData` logic. Those are application
6037
- policies; this helper only applies declared CRUD semantics.
6195
+ The helper deliberately does **not** flatten pages, infer filter semantics,
6196
+ derive a sort order or replace arbitrary `setQueryData` logic. Those remain
6197
+ declared application policies; Stitchkit applies their generic cache mechanics.
6038
6198
 
6039
6199
  ## Raw binary lane (Bun)
6040
6200
 
@@ -7643,6 +7803,11 @@ runtime or type-only package outside a case's budget fails with both the case id
7643
7803
  and package name, so an accidental eager import cannot hide behind another
7644
7804
  fixture's transitive dependency.
7645
7805
 
7806
+ That includes `stitchkit/tools/invoker`: a minimal packed consumer imports it
7807
+ without MCP/AI peers and executes validation, output projection and normalized
7808
+ errors on Bun and Node. The broader `stitchkit/tools` barrel deliberately keeps
7809
+ the adapter peer budget.
7810
+
7646
7811
  Beside the matrix, one case is about the ARTIFACT rather than the inventory: a
7647
7812
  program that injects the Socket.IO peer loaders is bundled and started in a
7648
7813
  directory with no `node_modules`, under Node and under Bun with auto-install
@@ -7674,6 +7839,11 @@ const socket = await createSocketIOServer({
7674
7839
  })
7675
7840
  ```
7676
7841
 
7842
+ The packed Next/Webpack gate compiles the browser
7843
+ `peers.client: () => import('socket.io-client')` loader and rejects Webpack's
7844
+ "request is an expression" warning. Stitchkit's runtime fallback remains lazy;
7845
+ its emitted import carries a count-checked ignore directive.
7846
+
7677
7847
  Omit `peers` and nothing changes: the peers stay lazy and are resolved from the
7678
7848
  machine. Both peers must be listed as dependencies of the package you bundle,
7679
7849
  because they now genuinely are.
@@ -10712,7 +10882,7 @@ The browser-and-server entrypoint. Re-exports everything from
10712
10882
  | `contractEndpointMatchers` | function | compile exact pathname matchers for selected HTTP contract operations and expected-401 policy |
10713
10883
  | `PathPrefixArgs` | _type_ | required string-valued keys exposed to a typed dynamic `pathPrefix` callback |
10714
10884
  | `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](../guide/client.md#createhttpclient) |
10715
- | `ApiError` | class | a non-2xx response, with `code` / `status` / `details` / `hint` and optional readonly `traceId` from `x-request-id` |
10885
+ | `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 |
10716
10886
  | `HttpClient` | _type_ | the transport interface `createClient` builds on |
10717
10887
  | `ConfiguredHttpClient` | _type_ | a framework-created `HttpClient` carrying its readonly `baseUrl` for URL builders |
10718
10888
  | `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](../guide/client.md#createhttpclient) |
@@ -11070,8 +11240,9 @@ Also re-exports the error helpers from `stitchkit/contract`.
11070
11240
  | `StreamingSourceContext` | _type_ | what a streaming source is given, including the cancellation `signal` |
11071
11241
  | `StreamingFormat` | _type_ | `'ndjson' \| 'sse'` |
11072
11242
  | `createUnixClientTransport` | function | owned Fetch-compatible Unix-socket transport on Bun and Node; every redirect stays on the socket — [guide](../guide/client.md#unix-domain-sockets) |
11073
- | `UnixClientTransportConfig` | _type_ | absolute socket path plus request/response/header/connection/redirect bounds |
11243
+ | `UnixClientTransportConfig` | _type_ | absolute socket path plus request/header/connection/redirect bounds and an explicit bounded-or-streaming response policy |
11074
11244
  | `UnixClientTransport` | _type_ | `{ fetch, closed, close() }`; `close()` settles owned active work |
11245
+ | `UnixResponseBodyMode` | _type_ | `bounded \| streaming`; bounded is the 16 MiB cumulative default, streaming keeps pull-driven buffering without a lifetime total |
11075
11246
  | `UnixClientTransportError` | class | stable transport failure with `code` and dispatch certainty in `delivery` |
11076
11247
  | `UnixClientTransportErrorCode` | _type_ | finite Unix transport failure-code union |
11077
11248
  | `UnixClientDeliveryState` | _type_ | `not-dispatched \| possibly-dispatched \| response-received`; input to application retry policy, never an implicit retry |
@@ -11119,7 +11290,7 @@ cutovers are covered by the executable
11119
11290
  | `ManagedResourceDependency` | _type_ | a dependency named by id or given as the resource itself — the second form is what `context.use(...)` can type |
11120
11291
  | `ManagedResourcePublished` | _type_ | the value type `context.use(resource)` returns, recovered from that resource's own `start` |
11121
11292
  | `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 |
11122
- | `ManagedServerResourceConfig` | _type_ | the server or a thunk that makes one, stable ID, dependencies and policy for `managedServerResource` |
11293
+ | `ManagedServerResourceConfig` | _type_ | the server or a sync/async factory receiving `ManagedResourceContext`, plus stable ID, dependencies and shutdown policy for `managedServerResource` |
11123
11294
  | `ManagedServerResource` | _type_ | the resource `managedServerResource` returns, whose `start` publishes the `ManagedServerHandle` |
11124
11295
  | `ApplicationHealthHandlerOptions` / `ApplicationHealthHandlerOptionsSchema` | _type_ / schema | liveness/readiness selection and sanitized `Retry-After` policy |
11125
11296
  | `ApplicationOperationalHandlers` / `ApplicationOperationalHandlersOptions` / `ApplicationOperationalHandlersOptionsSchema` | _type_ / schema | conventional status/readiness/liveness route surface and shared retry policy |
@@ -11247,7 +11418,8 @@ Server-only optional application runtime. See the
11247
11418
  | Export | Kind | Summary |
11248
11419
  |--------|------|---------|
11249
11420
  | `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 |
11250
- | `defineAgentProtocol` | function | declare and validate context, input metadata and canonical message parts |
11421
+ | `defineAgentProtocol` | function | declare context, input metadata, canonical parts and optional pre-CAS terminal acceptance (`allow-empty`, `require-output` or callback) |
11422
+ | `hasAgentTerminalOutput` | function | generic `require-output` predicate for non-blank text, generated files, structured provider parts and explicit tool-only policy stops |
11251
11423
  | `AgentMessageSchema` / `AgentRunSchema` / `AgentSnapshotSchema` | schema | versioned canonical engine records |
11252
11424
  | `AgentRuntimeStore` | _type_ | aggregate CAS transaction boundary for message, run and compaction mutations |
11253
11425
  | `createAgentRuntimeStore` | function | build the aggregate store from one coherent transaction driver; framework owns every state transition |
@@ -11260,7 +11432,7 @@ Server-only optional application runtime. See the
11260
11432
  | `createMemoryAgentRuntimeStore` | function | process-local reference adapter, not production durability |
11261
11433
  | `projectAgentHistory` | function | asynchronously project canonical records and resolved multimodal files into provider-valid AI SDK messages |
11262
11434
  | `defineModelRegistry` | function | typed language-model descriptors, capabilities and provider construction |
11263
- | `composeAgentPrompt` | function | ordered prompt contributions and provenance-aware context budget |
11435
+ | `composeAgentPrompt` | function | ordered prompt contributions and provenance-aware signed context budget; irreducible reservation deficits are `oversized`, not compactable history |
11264
11436
  | `structuredCompaction` | function | summarize a provider-valid snapshot range and replace it through CAS |
11265
11437
  | `createAgentSessionCoordinator` | function | strict process-local queue/interrupt/supersede lifecycle |
11266
11438
  | `AgentRuntimeStopPolicy` | _type_ | named custom AI SDK stop condition persisted and published on policy stop |
@@ -11289,7 +11461,8 @@ transport adapters validate the same records. Runtime composition types are `Age
11289
11461
  `AgentSessionCoordinator`, `AgentCompactionContext`, `AgentCompactionResult` and
11290
11462
  `StructuredCompactionConfig`.
11291
11463
 
11292
- Canonical protocol exports are `AgentProtocol`, `AgentProtocolConfig`, `AgentRecordIdSchema`, `AgentRecordVersionSchema`,
11464
+ Canonical protocol exports are `AgentProtocol`, `AgentProtocolConfig`, `AgentTerminalAcceptance`,
11465
+ `AgentTerminalAcceptanceInput`, `hasAgentTerminalOutput`, `AgentRecordIdSchema`, `AgentRecordVersionSchema`,
11293
11466
  `AgentTimestampSchema`, `AgentJsonObjectSchema`, `AgentProviderEnvelopeSchema`,
11294
11467
  `AgentProviderEnvelope`, `AgentMessagePartSchema`, `AgentMessagePart`, `AgentTextPartSchema`,
11295
11468
  `AgentReasoningPartSchema`, `AgentFilePartSchema`, `AgentSourcePartSchema`,
@@ -11485,7 +11658,7 @@ payload.
11485
11658
  | `mountAgent` | function | a Vercel AI SDK `ToolSet` from a service — [guide](../guide/mcp-and-agents.md#ai-agents--mountagent) |
11486
11659
  | `defineRuntimeTool` | function | define one validated pathless operation for explicit MCP, Agent and/or CLI surfaces — [guide](../guide/mcp-and-agents.md#pathless-runtime-tools-and-multimodal-results) |
11487
11660
  | `createRuntimeToolFactory` | function | bind shared identity and Zod-validated per-call context for runtime tools — [guide](../guide/mcp-and-agents.md#pathless-runtime-tools-and-multimodal-results) |
11488
- | `createToolInvoker` | function | compile an exposure-aware in-process dispatcher over the canonical tool runner — [guide](../guide/mcp-and-agents.md#in-process-calls--createtoolinvoker) |
11661
+ | `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](../guide/mcp-and-agents.md#in-process-calls--createtoolinvoker) |
11489
11662
  | `createCli` | function | a command-line program from contracts — [guide](../guide/cli.md) (also on `stitchkit/cli`) |
11490
11663
  | `defineCliCommand` | function | define one typed CLI-only command with optional post-validation `present` and successful `exitCode` policy — [guide](../guide/cli.md#native-binary-commands) (also on `stitchkit/cli`) |
11491
11664
  | `createToolkit` | function | context-typed tool mounts — [guide](../guide/cli.md#typed-context) |
@@ -11881,7 +12054,8 @@ runtime-agnostic pieces of `stitchkit/server` and the error helpers.
11881
12054
  | `NodeSocketLifecycle` | _type_ | Bun-free Socket.IO lifecycle accepted by `serveNode` |
11882
12055
  | `HandlerConfig` / `ServiceDef` / `RawRoute` / `RawRouteContext` | _type_ | runtime-neutral handler types; raw routes default their host server to `unknown` |
11883
12056
  | `SocketIORequestPolicy` / `SocketIOServerConfig` / `SocketIOPeerLoaders` / `SocketIOServerHandle` | _type_ | runtime-neutral handshake policy, config, optional-peer loaders and the Bun-free Node handle with `io`, `attach` and lifecycle |
11884
- | `UnixClientTransportConfig` / `UnixClientTransport` | _type_ | Unix socket bounds and owned Fetch-compatible handle |
12057
+ | `UnixClientTransportConfig` / `UnixClientTransport` | _type_ | Unix socket bounds, explicit response-body mode and owned Fetch-compatible handle |
12058
+ | `UnixResponseBodyMode` | _type_ | finite cumulative `bounded` mode or explicit pull-driven `streaming` mode |
11885
12059
  | `UnixClientTransportError` / `UnixClientTransportErrorCode` / `UnixClientDeliveryState` | class / _type_ | stable failure plus dispatch certainty; no cross-transport fallback |
11886
12060
  | `AppError` + `appError` / `badRequest` / `unauthorized` / `forbidden` / `notFound` / `conflict` / `rateLimited` | — | error helpers (same as `/contract`) |
11887
12061
 
@@ -11930,6 +12104,8 @@ and `react-query-kit` peers.
11930
12104
  | `createCacheBridge` | function | sync socket events into the Query cache — [guide](../guide/realtime.md#cache-bridge) |
11931
12105
  | `createEntityCacheHandlers` | function | created/updated/deleted cache handlers for one entity — [guide](../guide/realtime.md#entity-cache-handlers) |
11932
12106
  | `EntityCacheConfig` | _type_ | config for `createEntityCacheHandlers` |
12107
+ | `EntityCacheMembership` / `EntityCacheMembershipPolicy` | _type_ | per-exact-query `include | exclude | unknown` filter decision and unknown invalidation policy |
12108
+ | `EntityCacheTotalPolicy` / `EntityCacheTotalDeltaInput` | _type_ | evidence-aware reconciliation of numeric totals on paginated cache shapes |
11933
12109
  | `EntityCacheHandlers` | _type_ | the `{ created, updated, deleted }` handlers it returns |
11934
12110
  | `EntityCacheEvent` | _type_ | discriminated created/updated/deleted input for dynamic cache keys |
11935
12111
  | `EntityCacheKey` | _type_ | static `QueryKey` or event-aware key factory |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.68.0",
3
+ "version": "0.68.2",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",
@@ -56,6 +56,10 @@
56
56
  "types": "./dist/tools.d.ts",
57
57
  "import": "./dist/tools.js"
58
58
  },
59
+ "./tools/invoker": {
60
+ "types": "./dist/tool-invoker.d.ts",
61
+ "import": "./dist/tool-invoker.js"
62
+ },
59
63
  "./cli": {
60
64
  "types": "./dist/cli.d.ts",
61
65
  "import": "./dist/cli.js"
@@ -119,9 +123,9 @@
119
123
  "scripts": {
120
124
  "check": "bun x tsc --noEmit",
121
125
  "build:browser": "bun build src/index.ts src/react.ts src/contract/index.ts src/declaration.ts --outdir dist --target node --packages external --splitting --root src",
122
- "build:server": "bun build src/server/index.ts src/node.ts src/tools.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",
123
- "build:js": "bun run build:browser && bun run build:server",
124
- "build:types": "bun x tsc -p tsconfig.build.json --emitDeclarationOnly",
126
+ "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",
127
+ "build:js": "bun run build:browser && bun run build:server && bun scripts/preserve-webpack-ignore.mjs",
128
+ "build:types": "bun x tsc -p tsconfig.build.json --emitDeclarationOnly && bun scripts/rewrite-declaration-specifiers.mjs",
125
129
  "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",
126
130
  "dev": "bun run build:js -- --watch",
127
131
  "prepack": "cp ../../README.md ./README.md && bun ../../scripts/gen-llms.ts && bun run build",
@@ -1,10 +1,10 @@
1
- import {
2
- objectShapeKeys
3
- } from "./index-6djpbnda.js";
4
1
  import {
5
2
  getRequestContext,
6
3
  runWithRequestContext
7
4
  } from "./index-69m2278y.js";
5
+ import {
6
+ objectShapeKeys
7
+ } from "./index-6djpbnda.js";
8
8
  import {
9
9
  formatZodError,
10
10
  isUnsafeKey,