stitchkit 0.68.11 → 0.70.0

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 (125) hide show
  1. package/README.md +30 -1
  2. package/dist/agent-runtime/coding-tool-contract.d.ts +156 -0
  3. package/dist/agent-runtime/coding-tool-contract.d.ts.map +1 -0
  4. package/dist/agent-runtime/coding-tool-files.d.ts +3 -0
  5. package/dist/agent-runtime/coding-tool-files.d.ts.map +1 -0
  6. package/dist/agent-runtime/coding-tool-paths.d.ts +20 -0
  7. package/dist/agent-runtime/coding-tool-paths.d.ts.map +1 -0
  8. package/dist/agent-runtime/coding-tool-search-patch.d.ts +3 -0
  9. package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -0
  10. package/dist/agent-runtime/coding-tool-shell.d.ts +3 -0
  11. package/dist/agent-runtime/coding-tool-shell.d.ts.map +1 -0
  12. package/dist/agent-runtime/coding-tools.d.ts +17 -0
  13. package/dist/agent-runtime/coding-tools.d.ts.map +1 -0
  14. package/dist/agent-runtime/compaction.d.ts +2 -0
  15. package/dist/agent-runtime/compaction.d.ts.map +1 -1
  16. package/dist/agent-runtime/contained-files.d.ts +56 -0
  17. package/dist/agent-runtime/contained-files.d.ts.map +1 -0
  18. package/dist/agent-runtime/control-schema.d.ts +1074 -0
  19. package/dist/agent-runtime/control-schema.d.ts.map +1 -0
  20. package/dist/agent-runtime/conversations.d.ts +128 -0
  21. package/dist/agent-runtime/conversations.d.ts.map +1 -0
  22. package/dist/agent-runtime/event-schema.d.ts +96 -0
  23. package/dist/agent-runtime/event-schema.d.ts.map +1 -1
  24. package/dist/agent-runtime/harness-contract.d.ts +169 -0
  25. package/dist/agent-runtime/harness-contract.d.ts.map +1 -0
  26. package/dist/agent-runtime/harness-control.d.ts +25 -0
  27. package/dist/agent-runtime/harness-control.d.ts.map +1 -0
  28. package/dist/agent-runtime/harness-file-resources.d.ts +33 -0
  29. package/dist/agent-runtime/harness-file-resources.d.ts.map +1 -0
  30. package/dist/agent-runtime/harness-resources.d.ts +5 -0
  31. package/dist/agent-runtime/harness-resources.d.ts.map +1 -0
  32. package/dist/agent-runtime/harness.d.ts +12 -0
  33. package/dist/agent-runtime/harness.d.ts.map +1 -0
  34. package/dist/agent-runtime/history.d.ts +2 -0
  35. package/dist/agent-runtime/history.d.ts.map +1 -1
  36. package/dist/agent-runtime/models.d.ts +199 -0
  37. package/dist/agent-runtime/models.d.ts.map +1 -1
  38. package/dist/agent-runtime/prompt.d.ts +2 -0
  39. package/dist/agent-runtime/prompt.d.ts.map +1 -1
  40. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  41. package/dist/agent-runtime/runtime.d.ts +11 -3
  42. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  43. package/dist/agent-runtime/schemas.d.ts +49 -0
  44. package/dist/agent-runtime/schemas.d.ts.map +1 -1
  45. package/dist/agent-runtime/sqlite.d.ts +2 -0
  46. package/dist/agent-runtime/sqlite.d.ts.map +1 -1
  47. package/dist/agent-runtime/store-driver.d.ts +61 -212
  48. package/dist/agent-runtime/store-driver.d.ts.map +1 -1
  49. package/dist/agent-runtime/store.d.ts +368 -1
  50. package/dist/agent-runtime/store.d.ts.map +1 -1
  51. package/dist/agent-runtime/terminal-commit.d.ts +12 -1
  52. package/dist/agent-runtime/terminal-commit.d.ts.map +1 -1
  53. package/dist/agent-runtime/terminal-status.d.ts +8 -0
  54. package/dist/agent-runtime/terminal-status.d.ts.map +1 -1
  55. package/dist/agent-runtime-browser.d.ts +1 -0
  56. package/dist/agent-runtime-browser.d.ts.map +1 -1
  57. package/dist/agent-runtime-browser.js +217 -1
  58. package/dist/agent-runtime-coding-tools.d.ts +2 -0
  59. package/dist/agent-runtime-coding-tools.d.ts.map +1 -0
  60. package/dist/agent-runtime-coding-tools.js +766 -0
  61. package/dist/agent-runtime-harness.d.ts +2 -0
  62. package/dist/agent-runtime-harness.d.ts.map +1 -0
  63. package/dist/agent-runtime-harness.js +704 -0
  64. package/dist/agent-runtime-openrouter.d.ts +14 -1
  65. package/dist/agent-runtime-openrouter.d.ts.map +1 -1
  66. package/dist/agent-runtime-openrouter.js +211 -0
  67. package/dist/agent-runtime-sqlite-bun.js +4 -3
  68. package/dist/agent-runtime-sqlite-node.js +4 -3
  69. package/dist/agent-runtime.d.ts +5 -3
  70. package/dist/agent-runtime.d.ts.map +1 -1
  71. package/dist/agent-runtime.js +108 -2580
  72. package/dist/application/diagnostic-journal-contract.d.ts +164 -0
  73. package/dist/application/diagnostic-journal-contract.d.ts.map +1 -0
  74. package/dist/application/diagnostic-journal-manager.d.ts +12 -0
  75. package/dist/application/diagnostic-journal-manager.d.ts.map +1 -0
  76. package/dist/application/diagnostic-journal-storage.d.ts +29 -0
  77. package/dist/application/diagnostic-journal-storage.d.ts.map +1 -0
  78. package/dist/application/diagnostic-journal.d.ts +11 -0
  79. package/dist/application/diagnostic-journal.d.ts.map +1 -0
  80. package/dist/application.d.ts +2 -0
  81. package/dist/application.d.ts.map +1 -1
  82. package/dist/application.js +561 -17
  83. package/dist/browser/socket-io.d.ts.map +1 -1
  84. package/dist/cli.js +9 -6
  85. package/dist/{index-t23p2b68.js → index-0yphgata.js} +1 -1
  86. package/dist/{index-8vpzxg55.js → index-10gbbbaa.js} +103 -2
  87. package/dist/{index-hcx9yypn.js → index-38hs3a58.js} +13 -11
  88. package/dist/index-3xnq72rz.js +21 -0
  89. package/dist/index-7rey2b8s.js +73 -0
  90. package/dist/{index-22tjt2rk.js → index-aczggrty.js} +1 -1
  91. package/dist/index-bd17ytae.js +192 -0
  92. package/dist/{index-xyvxez9r.js → index-da1aqnhb.js} +5 -5
  93. package/dist/index-es0h4w26.js +63 -0
  94. package/dist/{index-hqza5nde.js → index-hsabxjz0.js} +78 -77
  95. package/dist/{index-f24xg2cw.js → index-ktsps64f.js} +4 -2
  96. package/dist/{index-2t6zt5cg.js → index-mjx0wt4c.js} +11 -7
  97. package/dist/{index-y2ctppmg.js → index-qzbg46b6.js} +10 -74
  98. package/dist/{index-bt5179zb.js → index-s8nt8c22.js} +16 -11
  99. package/dist/index-tg3m2ec5.js +157 -0
  100. package/dist/{index-hxh98zbm.js → index-vbf2p6me.js} +1 -1
  101. package/dist/index-vc498pst.js +51 -0
  102. package/dist/{index-pgsyp3xh.js → index-vj3vvpaa.js} +1 -192
  103. package/dist/index-vy5bjy07.js +2569 -0
  104. package/dist/{index-hb0mncmj.js → index-wc80at9n.js} +2 -2
  105. package/dist/{index-eqqyd9v8.js → index-wwst0td5.js} +2 -46
  106. package/dist/{index-ysphyxax.js → index-x1th9s8c.js} +23 -2
  107. package/dist/index-xbtcszs7.js +202 -0
  108. package/dist/{index-grgvpbch.js → index-y3w12g8d.js} +4 -2
  109. package/dist/index.js +51 -37
  110. package/dist/internal/ai-sdk-typed.d.ts +14 -0
  111. package/dist/internal/ai-sdk-typed.d.ts.map +1 -0
  112. package/dist/node.js +6 -5
  113. package/dist/observability/index.js +5 -4
  114. package/dist/realtime/request.d.ts +5 -0
  115. package/dist/realtime/request.d.ts.map +1 -1
  116. package/dist/remote.js +7 -6
  117. package/dist/server/index.js +13 -11
  118. package/dist/testing.js +6 -5
  119. package/dist/tool-invoker.js +7 -5
  120. package/dist/tools/agent-tool-error.d.ts +14 -0
  121. package/dist/tools/agent-tool-error.d.ts.map +1 -0
  122. package/dist/tools/agent.d.ts.map +1 -1
  123. package/dist/tools.js +24 -17
  124. package/llms-full.txt +386 -29
  125. package/package.json +10 -2
package/llms-full.txt CHANGED
@@ -59,12 +59,15 @@ own, recorded as an ADR.
59
59
  | `stitchkit/testing` | tests on Bun or Node | stable | in-process generated clients over a real Fetch handler, plus the store and managed-resource conformance kits |
60
60
  | `stitchkit/declaration` | build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
61
61
  | `stitchkit/react` | browser | stable | `createCursorQuery`, `createCacheBridge` |
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 |
62
+ | `stitchkit/agent-runtime` | server | evolving<br>_redefined in 10 of the 15 minors since 0.56.2, most recently 0.69.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
63
+ | `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
64
+ | `stitchkit/agent-runtime/coding-tools` | server (Bun or Node) | evolving | bounded host-authorized direct file and shell tools; a root boundary, not an OS sandbox |
63
65
  | `stitchkit/agent-runtime/openrouter` | server | evolving | isolated OpenRouter language-model adapter |
64
66
  | `stitchkit/agent-runtime/browser` | browser + server | evolving | canonical agent records, events and reconnect cursor without execution or sinks |
65
67
  | `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
66
68
  | `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
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 |
69
+ | `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
70
+ | `stitchkit/application` | server | evolving<br>_redefined in 3 of the 15 minors since 0.56.2, most recently 0.67.0_ | managed resource graph, readiness, admission, schedules and bounded shutdown |
68
71
  | `stitchkit/application/grammy` | server | evolving | isolated grammY polling and webhook lifecycle adapters |
69
72
  | `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
70
73
 
@@ -166,6 +169,8 @@ map — feature → packages:
166
169
  | In-process contract tools (`stitchkit/tools/invoker`) | — |
167
170
  | MCP / agent adapters (`stitchkit/tools`) | `@modelcontextprotocol/server` `ai` |
168
171
  | Agent application runtime (`stitchkit/agent-runtime`) | `ai` |
172
+ | Headless Agent harness (`stitchkit/agent-runtime/harness`) | `ai` |
173
+ | Agent coding tools (`stitchkit/agent-runtime/coding-tools`) | — |
169
174
  | OpenRouter runtime adapter (`stitchkit/agent-runtime/openrouter`) | `ai` `@openrouter/ai-sdk-provider` |
170
175
  | SQLite agent store (`stitchkit/agent-runtime/sqlite/bun` or `/node`) | — (runtime built-in) |
171
176
  | MCP host/client tests | `@modelcontextprotocol/client` |
@@ -213,6 +218,17 @@ For a complete production-shaped app, run `bun create stitchkit my-app`. The
213
218
  canonical generated topology is maintained in
214
219
  [`packages/create-stitchkit/template`](../../packages/create-stitchkit/template).
215
220
 
221
+ For a terminal Agent host instead, run
222
+ `bun create stitchkit my-agent --template agent`, copy `.env.example` to `.env`,
223
+ set `OPENROUTER_API_KEY`, then run `bun run dev` and choose a live tool-capable
224
+ model with `/model`. The provider catalog owns the exact model id and context window and presents
225
+ weekly popularity separately from sourced benchmark observations; `OPENROUTER_MODEL` is only an
226
+ optional preferred row. That profile is a thin `stitchkit.agent.ts` composition over the official
227
+ `stitchkit-tui` package and canonical headless harness:
228
+ durable SQLite history, lazy skills, direct coding tools, approval continuations
229
+ and recovery stay framework-owned primitives, while model choice, permissions,
230
+ executables and OS isolation remain application policy.
231
+
216
232
 
217
233
  ==============================================================================
218
234
  # Guide: Contracts (docs/guide/contracts.md)
@@ -3991,33 +4007,97 @@ provider-reported input usage and cost to decide whether the extra search round
3991
4007
  is beneficial. Controller evidence intentionally omits query text, prompts,
3992
4008
  arguments and application context. → ADR 0129.
3993
4009
 
3994
- ### Executable headless harness and capability map
4010
+ ### Published headless harness and structured runner
4011
+
4012
+ `stitchkit/agent-runtime/harness` publishes the resource-aware composition over
4013
+ `createAgentRuntime`. `createHeadlessAgentHarness` accepts the existing protocol and store,
4014
+ caller-provided model resolution, bounded instruction/skill/resource loading, direct tools and a
4015
+ prompt-budget callback. Resource names are unique; count, UTF-8 bytes and diagnostics are bounded.
4016
+ Invalid resources fail before a provider request. Diagnostics are evidence for the caller: their
4017
+ observer is isolated, and the loader decides whether a reported condition is fatal.
4018
+
4019
+ `createAgentHarnessFileResources` is the optional filesystem implementation. It reads only
4020
+ caller-declared absolute roots, refuses symlinks and reports provenance as
4021
+ `rootId:relative/path`. Instructions enter the prompt immediately. Skills and ordinary resources
4022
+ enter as bounded name/description summaries; `read_resource` loads one exact body later as
4023
+ a normal direct typed tool. Custom loaders remain supported unchanged.
3995
4024
 
3996
- [`packages/core/examples/headless-agent-harness.ts`](../../packages/core/examples/headless-agent-harness.ts)
3997
- is the complete resource-aware recipe. It accepts injected protocol, model,
3998
- tool and store ports, validates resources plus diagnostics, carries provenance
3999
- into the prompt and delegates execution to `createAgentRuntime`. Importing the
4000
- example starts no process, opens no database and discovers no filesystem path.
4025
+ Each run may resolve a different provider adapter without changing the harness. The
4026
+ `profile-applied` observation records the actual `AgentModelDescriptor`, resource kind/name/
4027
+ provenance and sorted direct tool names; it intentionally contains no resource text, prompts,
4028
+ arguments or credentials. Observer failure never changes the canonical run outcome.
4029
+
4030
+ [`packages/core/examples/headless-agent-runner.ts`](../../packages/core/examples/headless-agent-runner.ts)
4031
+ is a reference structured control loop for `submit`, `interrupt`, `snapshot` and bounded `close`.
4032
+ It starts no process and chooses no framing, authentication or transport. Importing either example
4033
+ has no side effect; an external supervisor owns process placement and restart.
4001
4034
 
4002
4035
  | Concern | Public Stitchkit composition | Boundary |
4003
4036
  | --- | --- | --- |
4004
4037
  | execution loop | `createAgentRuntime` | already available; do not copy a second loop |
4005
4038
  | model choice | `defineModelRegistry` and `models.resolve` | provider credentials/discovery stay application-owned |
4006
- | resources | injected loader → `composeAgentPrompt` sections | paths, trust, precedence and watching stay application-owned |
4039
+ | resources | `createHeadlessAgentHarness` → `composeAgentPrompt` | paths, trust, precedence and watching stay application-owned |
4007
4040
  | tools | `mountAgent` + `createAgentToolFenceLifecycle` | auth and domain effects stay application-owned |
4008
4041
  | follow-up | `runs.inputPolicy: 'queue'` | durable FIFO after the current run |
4009
4042
  | interrupt | `interrupt` or `interrupt-next` | `interrupt-next` terminates the active run and gives the new durable admission next priority |
4010
4043
  | recovery | `runtime.recover` + `scanRecoverable` | replay safety and context reconstruction are explicit callbacks |
4011
- | reconnect | canonical snapshot + `advanceAgentRuntimeEventCursor` | transient deltas are replaceable; durable event IDs deduplicate |
4044
+ | reconnect | canonical snapshot + `advanceAgentMultiSessionCursor` | conversation/run-scoped gaps require resync |
4012
4045
  | persistence | memory reference, public driver, or SQLite leaf | product rows/outbox remain outside the runtime store |
4013
-
4014
- Pi's steering queue waits for the current tool calls and injects the steering
4015
- message at its next loop boundary. It is therefore not an alias for
4016
- `interrupt-next`: Stitchkit requests termination of the active durable run,
4017
- waits for its terminal settlement, and executes the prioritized successor.
4018
- Pi follow-up is closest to Stitchkit `queue`, while JSONL trees, branching,
4019
- workspace discovery, permissions and terminal UI remain embedding-application
4020
- features rather than runtime requirements.
4046
+ | executable lifecycle | structured runner example | framing, auth, process placement, restart and OS isolation stay host-owned |
4047
+
4048
+ `createAgentHarnessControlServer` adds transport-neutral correlated requests, shared observers and
4049
+ one exclusive controller lease per conversation. `close()` on a connection detaches only that
4050
+ client; it never closes the harness. Normal `event` delivery stays serialized. A bounded slow
4051
+ consumer is detached and receives `resync-required` through the required synchronous
4052
+ `onOverflow` callback; that callback closes/aborts the underlying transport, which then reconnects
4053
+ and requests a fresh snapshot. It never writes a second frame concurrently with a blocked
4054
+ `deliver`. Browser code uses `createAgentControlView`,
4055
+ `reduceAgentControlSnapshot` and `reduceAgentControlEvent`; the reducer owns no renderer and marks a
4056
+ conversation `resyncRequired` after a transient sequence gap.
4057
+
4058
+ Configure `loop.toolApproval` to use the installed AI SDK approval policy and
4059
+ `loop.toolApprovalSecret` to sign exact requests. A request is stored on the terminal assistant
4060
+ before any effect. `pendingApprovals()` derives unresolved requests from canonical messages;
4061
+ `respondToApproval()` writes one tool-role approval response and queues a successor. The SDK
4062
+ revalidates the signature/tool call/input before the original direct tool reaches its existing
4063
+ fence. Reconnect and SQLite reopen require no promise registry. Remembered policy and a stronger
4064
+ cross-crash exactly-once guarantee remain application concerns.
4065
+
4066
+ `stitchkit/agent-runtime/coding-tools` returns ordinary direct runtime tools named `read_file`,
4067
+ `write_file`, `search_files`, `apply_patch`, `run_command` and optional `read_output`. Every call passes a
4068
+ required host authorization callback. File paths are relative, bounded and contained after
4069
+ descriptor-relative resolution: each ancestor is opened without following symlinks and remains
4070
+ pinned through authorization and the filesystem effect. Reads revalidate the pinned file identity;
4071
+ writes and patches revalidate the pinned parent identity; search and resource discovery descend
4072
+ only through opened directories. Linux uses `/proc/self/fd`; macOS and FreeBSD use `/dev/fd`.
4073
+ Other platforms fail these filesystem operations closed because Node exposes no equivalent
4074
+ portable directory-handle-relative API. Writes/edits reject symlink targets, content is strict
4075
+ UTF-8 and retained bytes are finite. Shell accepts a finite alias mapped by the host to an absolute executable plus an
4076
+ argument array — never a shell command string — and uses only the explicitly supplied environment.
4077
+ Arguments, output and time are bounded, while cancellation terminates the child. The configured
4078
+ root and cwd are path boundaries, not a security sandbox: isolate the process when an executable
4079
+ must not access the rest of the machine.
4080
+
4081
+ `apply_patch` binds the exact source to `baseSha256`, supports dry-run, authorizes the exact
4082
+ replacement count, result digest and byte size, then rechecks the base under a per-target lock
4083
+ before same-directory atomic replacement. It deliberately does not claim
4084
+ multi-file atomicity. With an optional `AgentCodingArtifactStore`, shell output beyond the inline
4085
+ preview continues into an opaque bounded artifact and `read_output` reads slices without
4086
+ exposing a host path. Without a store, the previous finite output-limit behavior is unchanged.
4087
+
4088
+ `run_command` treats every invocation as finite. `shellTimeoutMs` bounds normal execution and
4089
+ `shellTerminationGraceMs` bounds settlement after timeout, caller cancellation, output overflow or
4090
+ parent exit. POSIX hosts launch a dedicated process group and kill every descendant remaining in
4091
+ that group; a process that deliberately escapes the group is outside the guarantee. Node's
4092
+ portable Windows child-process API cannot kill a complete descendant tree without invoking a
4093
+ second host executable, so Windows kills the direct child, destroys retained pipes at the grace
4094
+ deadline and makes no descendant-cleanup claim. A signal already aborted before execution returns
4095
+ `cancelled` without spawning.
4096
+
4097
+ One `createAgentHarnessFileResources` instance represents one immutable discovery generation:
4098
+ concurrent and repeated `load()` calls share it, so a direct resource read cannot cross into a
4099
+ new catalog unexpectedly. Discovery uses the same descriptor-anchored traversal as coding search;
4100
+ construct a new loader to refresh after filesystem changes.
4021
4101
 
4022
4102
  Runtime events preserve reasoning/text/tool lifecycle order. Durable admission,
4023
4103
  checkpoint, run-state and terminal events carry stable identities; transient
@@ -4444,7 +4524,9 @@ or silently accept an unknown future version.
4444
4524
  - `assistant-checkpoint` follows a successful checkpoint CAS;
4445
4525
  - `run-state` follows durable queue/acquire/interrupt transitions;
4446
4526
  - `tool-status` is transient lifecycle presentation with JSON-safe input on
4447
- start and output on completion; internal tool failures remain generic;
4527
+ start and output on completion. A mounted typed failure carries the same safe
4528
+ `{ error, details?, _hint? }` envelope as the durable result; an unknown
4529
+ internal cause remains generic and stays in local observability only;
4448
4530
  - `terminal` follows the winning terminal CAS.
4449
4531
 
4450
4532
  These are post-commit notifications, not a transactional outbox: a process can
@@ -4560,6 +4642,14 @@ before a managed side effect and again before accepting its result. Fence loss
4560
4642
  uses an internal control signal: it stops the old loop and is not sent to the
4561
4643
  model as a tool error.
4562
4644
 
4645
+ `mountAgent` sends failed runner outcomes through the AI SDK's tool-error
4646
+ channel. AgentRuntime persists them with `outcome: 'error'`, publishes the same
4647
+ safe envelope, and replays them as an error result on later turns. Classification
4648
+ comes from the execution channel, never from inspecting output fields: a valid
4649
+ successful result such as `{ error: 'domain value' }` remains successful. Typed
4650
+ `AppError` codes and safe details may reach the model; arbitrary thrown causes
4651
+ are retained for local hooks and reduced to `INTERNAL_SERVER_ERROR` outside.
4652
+
4563
4653
  The framework cannot undo an already-started non-cooperative external effect.
4564
4654
  Pass the stable call/run idempotency identity into business mutations when the
4565
4655
  effect must be replay-safe.
@@ -5163,6 +5253,54 @@ replenishes once; it is flow-control credit, not a durable acknowledgement. The
5163
5253
  application snapshot sink now shares the same latest-value mechanics without
5164
5254
  changing its revision or status contract. → ADR 0119.
5165
5255
 
5256
+ ### Bounded local diagnostic journal
5257
+
5258
+ Use `createDiagnosticJournal` when a process needs finite, ordered local metadata evidence and the
5259
+ deployment log pipeline is not the right boundary:
5260
+
5261
+ ```ts
5262
+ import { createDiagnosticJournal } from 'stitchkit/application'
5263
+ import { z } from 'zod'
5264
+
5265
+ const journal = await createDiagnosticJournal({
5266
+ eventSchema: z.object({
5267
+ kind: z.enum(['resource_failed', 'recovery_started']),
5268
+ resource: z.string().max(80),
5269
+ }).strict(),
5270
+ path: '/var/lib/example/diagnostic.jsonl', // operator configuration, never request data
5271
+ limits: {
5272
+ maxEventBytes: 4 * 1024,
5273
+ maxPendingItems: 128,
5274
+ maxPendingBytes: 512 * 1024,
5275
+ maxFileBytes: 8 * 1024 * 1024,
5276
+ maxFiles: 4,
5277
+ },
5278
+ onFailure: (failure) => internalLogger.error(failure),
5279
+ })
5280
+
5281
+ const result = journal.submit({ kind: 'recovery_started', resource: 'database' })
5282
+ if (result.outcome === 'refused') internalCounter.add(1, { reason: result.reason })
5283
+
5284
+ // During managed-resource close. Timeout ends this wait, not the physical append.
5285
+ await journal.close({ timeoutMs: 5_000 })
5286
+ ```
5287
+
5288
+ The owner schema and JSON serialization run synchronously before admission. Accepted frames carry
5289
+ a process epoch and contiguous sequence and retain their complete bytes inside both pending limits
5290
+ until their append attempt settles. Capacity, invalid, oversized, closed and terminal-failure
5291
+ refusals are explicit; accepted ordered frames are never evicted.
5292
+
5293
+ The absolute path's parent must already exist and be operator-controlled. One manager owns it via
5294
+ an exclusive `.lock`; new files use mode `0600` by default. `maxFiles` includes the active file,
5295
+ and a non-newline startup tail is rotated intact rather than guessed or repaired. An abrupt process
5296
+ death may leave the lock for an operator to remove only after proving the former owner is gone.
5297
+
5298
+ `flush()` means every accepted append through that call's boundary settled. It is not `fsync`, a
5299
+ durable receipt, exactly-once execution or remote delivery. Timeout/cancellation bound only the
5300
+ waiter; the writer retains physical capacity until settlement. There is no reader or upload API.
5301
+ Use a durable application store or deployment-owned log collector when restart recovery, replay or
5302
+ aggregation is required. → [ADR 0134](../decisions/0134-diagnostic-journal-is-bounded-local-evidence.md).
5303
+
5166
5304
  Shutdown performs one phase barrier at a time: stop admission everywhere,
5167
5305
  cancel future schedules, drain admitted work, then close in reverse stable
5168
5306
  topological order. Every hook shares the same grace deadline. Forced cleanup
@@ -6197,7 +6335,10 @@ from the contract and validated on both sides:
6197
6335
  const result = await socket.request(
6198
6336
  'room:join',
6199
6337
  'general',
6200
- { timeoutMs: 5_000 },
6338
+ {
6339
+ timeoutMs: 5_000,
6340
+ onPhase: (phase) => roomJoinMetrics.record(phase),
6341
+ },
6201
6342
  )
6202
6343
  // result: { joined: boolean }
6203
6344
  ```
@@ -6242,6 +6383,22 @@ closed phase:
6242
6383
  | `timeout` | the existing native acknowledgement timeout won |
6243
6384
  | `disconnected` | the request began disconnected or an in-flight disconnect won |
6244
6385
 
6386
+ When a caller needs to join those phases to its own invocation, put `onPhase`
6387
+ on that request's options and keep the caller identity in the hook's closure:
6388
+
6389
+ ```ts
6390
+ await socket.request('room:join', 'general', {
6391
+ timeoutMs: 5_000,
6392
+ onPhase: (phase) => recordPhase({ operationId, phase }),
6393
+ })
6394
+ ```
6395
+
6396
+ The client-wide hook receives every observed request; a request hook receives
6397
+ only its invocation. If the same function is supplied in both places it runs
6398
+ once per phase. The closure is local: Stitchkit does not retain `operationId`,
6399
+ add it to the event or transmit it to the peer. A request hook works without a
6400
+ client-wide hook, and the no-hook path installs no phase listeners.
6401
+
6245
6402
  Engine handoff is not proof of a physical network write. Engine acknowledgement
6246
6403
  receipt is not a remote clock, end-to-end RTT or proof that application
6247
6404
  validation has run. The useful interval is local and monotonic:
@@ -6254,9 +6411,9 @@ with Socket.IO acknowledgement ids, but those ids are never exposed. A timeout
6254
6411
  or disconnect is terminal, a late packet cannot reopen the identity, and sync
6255
6412
  or async observer failures are ignored so telemetry cannot change request
6256
6413
  correctness. With no hook, no request identity, Engine.IO listener or correlation
6257
- map entry is created. The low-level `createSocketIOClient` and non-owning
6258
- `bindRealtimeClient` remain unchanged; this phase surface belongs to the
6259
- canonical composed client that owns both transport and validation.
6414
+ map entry is created. The low-level `createSocketIOClient` implements the same
6415
+ request option, so a non-owning `bindRealtimeClient` over that transport keeps
6416
+ request-scoped observation without opening a second connection.
6260
6417
 
6261
6418
  ## Low-level transport
6262
6419
 
@@ -8737,6 +8894,62 @@ additive** — adopting it changes nothing in your code. (See
8737
8894
  So upgrading is: read the `### ⚠️ Breaking changes` of every version *above* your
8738
8895
  current one *up to* your target, and apply each snippet.
8739
8896
 
8897
+ ## Released migration: 0.70.0
8898
+
8899
+ ### Descriptor-backed Agent filesystem containment
8900
+
8901
+ Built-in coding file/search tools and `createAgentHarnessFileResources` now require a runtime
8902
+ that can address an opened directory descriptor: Linux `/proc/self/fd`, or macOS/FreeBSD
8903
+ `/dev/fd`. This is what keeps a mutable parent rename or outside-symlink replacement from changing
8904
+ the authorized target between validation and the actual effect.
8905
+
8906
+ No call-site change is needed on those platforms. On Windows or another platform without that
8907
+ boundary, move the built-in filesystem operations to a supported worker or replace them with
8908
+ application-owned tools backed by an equivalent native handle API. They fail closed rather than
8909
+ falling back to path spelling. `run_command` remains separately available under its explicit
8910
+ executable alias and authorization policy; this change does not claim an executable sandbox.
8911
+
8912
+ ## Released migration: 0.69.0
8913
+
8914
+ ### Direct coding-tool operation names
8915
+
8916
+ `createAgentCodingTools` no longer prefixes durable operation identity with `coding_`, and the
8917
+ unguarded exact-string edit tool is gone. Update approval maps, presenters and tests together:
8918
+
8919
+ ```ts
8920
+ // before
8921
+ { coding_read_file: 'approved', coding_search: 'approved', coding_patch_file: 'user-approval' }
8922
+
8923
+ // after
8924
+ { read_file: 'approved', search_files: 'approved', apply_patch: 'user-approval' }
8925
+ ```
8926
+
8927
+ The full mapping is `coding_read_file → read_file`, `coding_write_file → write_file`,
8928
+ `coding_search → search_files`, `coding_patch_file → apply_patch`, `coding_shell → run_command`,
8929
+ `coding_read_artifact → read_output` and `harness_read_resource → read_resource`. Replace
8930
+ `coding_edit_file` with `read_file` followed by guarded `apply_patch`; `read_file` now returns the
8931
+ required SHA-256. If the host declares no executable aliases, expect `run_command` to be absent.
8932
+
8933
+ ### Durable Agent approval message variants
8934
+
8935
+ If a renderer, store adapter or export pipeline exhaustively switches over
8936
+ `AgentMessage.role`, add the `tool` branch. If it switches over
8937
+ `AgentMessagePart.type`, add `tool-approval-request` and `tool-approval-response`.
8938
+ They are durable provider-continuation evidence: preserve them in storage and provider history;
8939
+ a UI may render them as approval state or intentionally omit their visual row.
8940
+
8941
+ ```ts
8942
+ // before
8943
+ const unreachable: never = message.role
8944
+
8945
+ // after
8946
+ if (message.role === 'tool') renderToolContinuation(message.parts)
8947
+ else renderExistingRole(message)
8948
+ ```
8949
+
8950
+ No data migration is needed. The schema still accepts all earlier records, and applications that
8951
+ do not exhaustively branch over these unions compile unchanged.
8952
+
8740
8953
  ## Before you bump, if you implement an agent store
8741
8954
 
8742
8955
  One step, and it is mechanical. If your project has an `AgentRuntimeStore` — a
@@ -11298,10 +11511,10 @@ The browser-and-server entrypoint. Re-exports everything from
11298
11511
  | `RealtimeAcknowledgedEvent` | _type_ | event-name union restricted to definitions with an `ack` schema |
11299
11512
  | `RealtimeAcknowledgement` | _type_ | validated acknowledgement output inferred from an event definition |
11300
11513
  | `RealtimeRequestArguments` | _type_ | request arguments inferred from an acknowledged event tuple |
11301
- | `RealtimeRequestOptions` | _type_ | finite positive native acknowledgement `timeoutMs` |
11514
+ | `RealtimeRequestOptions` | _type_ | finite positive native acknowledgement `timeoutMs` plus an optional invocation-scoped `onPhase` observer |
11302
11515
  | `RealtimeRequestPhaseSchema` / `RealtimeRequestPhase` | schema / _type_ | closed `engine-handoff` / `engine-ack-received` / `settled` / `timeout` / `disconnected` lifecycle |
11303
11516
  | `RealtimeRequestPhaseEventSchema` / `RealtimeRequestPhaseEvent` | schema / _type_ | strict metadata-only `{ requestId, event, phase, elapsedMs }` observation |
11304
- | `RealtimeRequestPhaseHook` | _type_ | isolated sync/async observer accepted by `RealtimeClientOptions.onRequestPhase` |
11517
+ | `RealtimeRequestPhaseHook` | _type_ | isolated sync/async observer accepted globally by `RealtimeClientOptions.onRequestPhase` or per invocation by `RealtimeRequestOptions.onPhase` |
11305
11518
  | `RealtimeRequestTimeoutError` | class | stable `REALTIME_REQUEST_TIMEOUT` rejection |
11306
11519
  | `RealtimeRequestDisconnectedError` | class | stable `REALTIME_REQUEST_DISCONNECTED` rejection, including an immediate disconnected call |
11307
11520
  | `RealtimeRequestInvalidAcknowledgementError` | class | invalid ack was reported through `onRejected` and the request rejected |
@@ -11712,6 +11925,29 @@ cutovers are covered by the executable
11712
11925
  | `CreditWindow` / `CreditWindowSnapshot` / `CreditWindowSnapshotSchema` | _type_ / schema | byte-credit handle and absolute accounting record |
11713
11926
  | `CreditAcquireResult` / `CreditLease` | _type_ | reasoned refusal or idempotently releasable byte-credit lease |
11714
11927
 
11928
+ ### Bounded diagnostic journal
11929
+
11930
+ | Export | Kind | Summary |
11931
+ |--------|------|---------|
11932
+ | `createDiagnosticJournal` | function | create one schema-owned FIFO JSONL writer with bounded retained memory, exclusive local path ownership and finite rotation |
11933
+ | `DiagnosticJournalConfig` / `DiagnosticJournal` | _type_ | owner schema/path/limits/failure observer and the synchronous `submit`, bounded-wait `flush`/`close`, status handle |
11934
+ | `DiagnosticJournalLimitsSchema` / `DiagnosticJournalLimits` | schema / _type_ | positive event, pending-item, pending-byte, file-byte and retained-file limits |
11935
+ | `DiagnosticJournalSubmitResultSchema` / `DiagnosticJournalSubmitResult` | schema / _type_ | accepted epoch/sequence or explicit invalid, oversized, capacity, closed or failed refusal |
11936
+ | `DiagnosticJournalStatusSchema` / `DiagnosticJournalStatus` | schema / _type_ | state, limits, exact admission/write/failure counters, pending ownership, rotations, partial tails and last safe sequences |
11937
+ | `DiagnosticJournalFrameSchema` / `DiagnosticJournalFrame` | schema / _type_ | version-1 JSONL frame carrying process epoch, contiguous accepted sequence and schema-validated JSON event |
11938
+ | `DiagnosticJournalWaitResultSchema` / `DiagnosticJournalWaitResult` | schema / _type_ | flush settlement boundary with truthful settled, timed-out or cancelled result |
11939
+ | `DiagnosticJournalCloseResultSchema` / `DiagnosticJournalCloseResult` | schema / _type_ | physical close or caller timeout/cancellation without pretending an active write stopped |
11940
+ | `DiagnosticJournalStateSchema` / `DiagnosticJournalState` | schema / _type_ | `open \| draining \| closed \| failed` |
11941
+ | `DiagnosticJournalRefusalReasonSchema` / `DiagnosticJournalRefusalReason` | schema / _type_ | `closed \| failed \| invalid \| oversized \| item-capacity \| byte-capacity` |
11942
+ | `DiagnosticJournalFailurePhaseSchema` / `DiagnosticJournalFailurePhase` | schema / _type_ | internal `write \| rotation \| close` failure phase exposed only to status and the isolated observer |
11943
+ | `DiagnosticJournalWaitOptions` / `DiagnosticJournalFailure` | _type_ | caller wait signal/timeout and isolated internal failure callback record |
11944
+
11945
+ `accepted` is bounded in-memory admission and `written` is completed append, not `fsync` or durable
11946
+ delivery. The journal has no reader/replay/upload API. See the
11947
+ [guide](../guide/application-kernel.md#bounded-local-diagnostic-journal),
11948
+ [architecture](../architecture/diagnostic-journal.md) and [ADR
11949
+ 0134](../decisions/0134-diagnostic-journal-is-bounded-local-evidence.md).
11950
+
11715
11951
  ### Managed schedules
11716
11952
 
11717
11953
  | Export | Kind | Summary |
@@ -11823,6 +12059,21 @@ Server-only optional application runtime. See the
11823
12059
  | `createMemoryAgentRuntimeStore` | function | process-local reference adapter, not production durability |
11824
12060
  | `projectAgentHistory` | function | asynchronously project canonical records and resolved multimodal files into provider-valid AI SDK messages |
11825
12061
  | `defineModelRegistry` | function | typed language-model descriptors, capabilities and provider construction |
12062
+ | `AgentModelCatalogSchema` / `AgentModelCatalog` | schema / _type_ | provider-neutral complete/partial model catalog with separately sourced popularity, metrics, prices and observation time |
12063
+ | `AgentModelCatalogEntrySchema` / `AgentModelCatalogEntry` | schema / _type_ | one canonical provider model descriptor with optional price, popularity and metric evidence |
12064
+ | `AgentModelPriceSchema` / `AgentModelPrice` | schema / _type_ | normalized per-token input/output pricing and source currency |
12065
+ | `AgentModelPopularitySchema` / `AgentModelPopularity` | schema / _type_ | independently sourced ranked popularity observation with window and timestamp |
12066
+ | `AgentModelMetricSchema` / `AgentModelMetric` | schema / _type_ | independently sourced benchmark measurement with provenance and observation time |
12067
+ | `AgentModelCatalogProvider` | _type_ | abortable live catalog loader supplied by a provider adapter or application |
12068
+ | `AgentModelSearchInputSchema` / `AgentModelSearchInput` | schema / _type_ | bounded catalog text query and result ceiling |
12069
+ | `AgentModelSearchResultSchema` / `AgentModelSearchResult` | schema / _type_ | exact bounded catalog projection with total match count |
12070
+ | `searchAgentModelCatalog` | function | deterministic bounded search over a loaded canonical catalog |
12071
+ | `AgentModelSelectionSchema` / `AgentModelSelection` / `AgentModelSelectionStore` | schema / _type_ | durable per-conversation model choice; runtime resolvers receive run and snapshot to recover the model pinned to input metadata |
12072
+ | `createMemoryAgentModelSelectionStore` | function | process-local selection reference adapter |
12073
+ | `AgentConversationReader` | _type_ | optional bounded conversation-summary and message-history reader; not part of the required runtime store contract |
12074
+ | `AgentConversationSummarySchema` / `AgentConversationSummary` | schema / _type_ | bounded durable conversation list item with version, activity and preview |
12075
+ | `AgentConversationPageSchema` / `AgentConversationPage` | schema / _type_ | cursor-paged conversation summaries |
12076
+ | `AgentConversationMessagePageSchema` / `AgentConversationMessagePage` | schema / _type_ | cursor-paged durable message history |
11826
12077
  | `composeAgentPrompt` | function | ordered prompt contributions and provenance-aware signed context budget; irreducible reservation deficits are `oversized`, not compactable history |
11827
12078
  | `structuredCompaction` | function | summarize a provider-valid snapshot range and replace it through CAS |
11828
12079
  | `createAgentSessionCoordinator` | function | strict process-local queue/interrupt/supersede lifecycle |
@@ -11926,7 +12177,10 @@ History and context-budget exports are `projectAgentHistoryDetailed`,
11926
12177
  `AgentPromptBudget`, `AgentPromptSection`, `AgentPromptSectionContext`, `AgentTokenCount`,
11927
12178
  `AgentTokenCountSchema`, `ComposeAgentPromptOptions` and `ComposedAgentPrompt`. Whole-turn history
11928
12179
  selection never splits a tool chronology and reports why every canonical record was retained or
11929
- removed.
12180
+ removed. `AgentHistoryEvidencePolicy` is the shared opt-in for marked failed-assistant evidence in
12181
+ projection, budgeting and structured compaction; `isAssistantHistoryEvidence` applies it. The
12182
+ compatibility default omits it. Approval message schemas are
12183
+ `AgentToolApprovalRequestPartSchema` and `AgentToolApprovalResponsePartSchema`.
11930
12184
 
11931
12185
  Model exports are `AgentLanguageModelProvider`, `AgentModelCapability`,
11932
12186
  `AgentModelCapabilitySchema`, `AgentModelDescriptor`,
@@ -11953,12 +12207,71 @@ Managed effects and operator telemetry additionally export `AgentToolFenceConfig
11953
12207
  may accompany checkpoint/terminal writes and tool context; internal causes are redacted unless an
11954
12208
  operator-only observability sink explicitly opts in.
11955
12209
 
12210
+ ## `stitchkit/agent-runtime/harness`
12211
+
12212
+ Server-only evolving facade over the canonical Agent runtime. It requires the optional `ai` peer
12213
+ and introduces no store, queue or model-provider implementation of its own.
12214
+
12215
+ | Export | Kind | Summary |
12216
+ |--------|------|---------|
12217
+ | `createHeadlessAgentHarness` | function | compose one `createAgentRuntime` with caller-supplied model resolution, bounded resources, tools and prompt policy; adds canonical `snapshot` |
12218
+ | `HeadlessAgentHarness` / `HeadlessAgentHarnessConfig` | _type_ | runtime facade and injected ownership boundary |
12219
+ | `HeadlessAgentModelResolver` | _type_ | per-run preflight/resolve port returning the actual `AgentResolvedModel` |
12220
+ | `AgentHarnessResourceSchema` / `AgentHarnessResource` | schema / _type_ | strict instruction, skill or resource with name, text and provenance |
12221
+ | `AgentHarnessResourceKindSchema` / `AgentHarnessResourceKind` | schema / _type_ | closed `instruction`, `skill` or `resource` vocabulary |
12222
+ | `AgentHarnessResourceResult` | _type_ | one loader result containing resources and diagnostics |
12223
+ | `AgentHarnessResourceDiagnosticSchema` / `AgentHarnessResourceDiagnostic` | schema / _type_ | bounded caller evidence; observer failure is isolated |
12224
+ | `AgentHarnessLimitsSchema` / `AgentHarnessLimits` | schema / _type_ | resource count, total UTF-8 bytes and diagnostic ceilings |
12225
+ | `AgentHarnessProfileEventSchema` / `AgentHarnessProfileEvent` | schema / _type_ | actual model descriptor, non-content resource provenance and sorted direct tool identities applied to one run |
12226
+ | `createAgentHarnessFileResources` | function | discover explicit instruction/skill/resource roots with symlink containment, bounded summaries and direct exact reads |
12227
+ | `AgentHarnessFileRootSchema` / `AgentHarnessFileRoot` | schema / _type_ | caller-owned absolute path, public root ID and resource kind |
12228
+ | `AgentHarnessFileLimitsSchema` / `AgentHarnessFileLimits` | schema / _type_ | file count, depth, per-file and aggregate byte ceilings |
12229
+ | `AgentHarnessFileResources` | _type_ | loader plus direct `read_resource` definition for lazy exact content |
12230
+ | `createAgentHarnessControlServer` | function | transport-neutral correlated requests, observer attachments and exclusive controller leases |
12231
+ | `AgentHarnessControlServer` / `AgentHarnessControlConnection` | _type_ | host server and detachable connection lifecycle; `deliver` is serialized, while required out-of-band `onOverflow` closes/aborts a slow transport before reconnect |
12232
+ | `AgentHarnessControlServerConfig` | _type_ | explicit per-connection pending-event bound for failure-isolated control delivery |
12233
+ | `AgentHarnessPendingApproval` / `AgentHarnessApprovalDecision` | _type_ | exact durable pending request and allow/deny successor input |
12234
+
12235
+ Resources default to at most 64 entries, 1 MiB of total UTF-8 text and 128 diagnostics. Duplicate
12236
+ names and exceeded bounds fail before the provider step. Recovery remains the underlying runtime's
12237
+ explicit policy; use the Bun or Node SQLite leaf for durable reopen.
12238
+
12239
+ ## `stitchkit/agent-runtime/coding-tools`
12240
+
12241
+ Server-only evolving, peer-free direct runtime tools. `createAgentCodingTools(config)` returns
12242
+ `read_file`, `write_file`, `search_files`, `apply_patch`, optional `run_command` and, when an
12243
+ artifact store is supplied, `read_output`.
12244
+
12245
+ | Export | Kind | Summary |
12246
+ |--------|------|---------|
12247
+ | `createAgentCodingTools` | function | construct direct host-authorized bounded file, search, guarded patch, shell and artifact runtime-tool definitions; filesystem operations require Linux `/proc/self/fd` or macOS/FreeBSD `/dev/fd` descriptor paths and otherwise fail closed |
12248
+ | `AgentCodingToolDefinition` | _type_ | peer-free structural direct-tool shape accepted by the canonical runtime-tool surface |
12249
+ | `AgentCodingToolConfig` | _type_ | absolute root, required authorization callback, finite executable alias map, exact child environment and optional limits |
12250
+ | `AgentCodingToolAuthorizationSchema` / `AgentCodingToolAuthorization` | schema / _type_ | discriminated read/write/search/patch/shell/artifact decision presented to host policy before effect |
12251
+ | `AgentCodingToolLimitsSchema` / `AgentCodingToolLimits` | schema / _type_ | explicit path/read/write/argument-count/argument-byte/output/artifact/timeout/termination-grace ceilings |
12252
+ | `AgentCodingArtifactStore` | _type_ | host-owned opaque artifact write and bounded read boundary |
12253
+ | `FileReadInputSchema` / `FileReadOutputSchema` | schema | bounded strict-UTF-8 byte slice; offsets must align with UTF-8 code-point boundaries |
12254
+ | `FileWriteInputSchema` / `FileWriteOutputSchema` | schema | create-only by default or explicit atomic replacement; symlink targets fail closed |
12255
+ | `createShellInputSchema` / `ShellOutputSchema` | schema | enumerated executable alias plus arguments and concrete relative cwd; explicit exited/timeout/output-limit/cancelled outcome |
12256
+
12257
+ File/search operations pin directory descriptors across authorization and the actual effect;
12258
+ resource discovery uses the same ancestor-safe traversal. This closes parent rename/symlink races
12259
+ without claiming an executable sandbox. The default ceilings are 4,096 path bytes, 256 KiB read/write/output, 128 shell arguments, 64 KiB
12260
+ of aggregate argument text, 4 MiB per artifact and 30 seconds. The root is a path-resolution
12261
+ boundary, not an OS sandbox; executable behavior, process
12262
+ isolation, credentials and external-effect idempotency remain host responsibilities.
12263
+
11956
12264
  ## `stitchkit/agent-runtime/browser`
11957
12265
 
11958
12266
  Browser-safe canonical agent data. It re-exports the run, message, part, usage,
11959
12267
  terminal and provider-envelope schemas/types listed under
11960
12268
  `stitchkit/agent-runtime`, together with all runtime delivery event schemas,
11961
- `AgentRuntimeEventCursorSchema`, `advanceAgentRuntimeEventCursor` and
12269
+ `AgentRuntimeEventCursorSchema`, `advanceAgentRuntimeEventCursor`,
12270
+ `AgentControlRequestSchema` / `AgentControlRequest`, `AgentControlResponseSchema` /
12271
+ `AgentControlResponse`, `AgentControlDeliverySchema` / `AgentControlDelivery`, `AgentMultiSessionCursorSchema` /
12272
+ `AgentMultiSessionCursor`, `AgentConversationView`, `AgentControlView`,
12273
+ `advanceAgentMultiSessionCursor`, `createAgentControlView`, `reduceAgentControlSnapshot`,
12274
+ `reduceAgentControlEvent` and
11962
12275
  `agentDurableEventId`. It imports no model provider, executor, store, event sink
11963
12276
  or Node context module.
11964
12277
 
@@ -11972,7 +12285,9 @@ Use this entrypoint from client components and shared DTO packages. The full
11972
12285
  | Export | Kind | Summary |
11973
12286
  |--------|------|---------|
11974
12287
  | `openRouterProvider` | function | isolated `@openrouter/ai-sdk-provider` language-model factory |
12288
+ | `openRouterModelCatalog` | function | complete tool-capable text catalog plus independent weekly popularity and available benchmark observations |
11975
12289
  | `OpenRouterProviderSettings` | _type_ | official provider settings accepted by the factory |
12290
+ | `OpenRouterModelCatalogOptions` / `OpenRouterCatalogFetch` | _type_ | credential, timeout, clock and injected fetch boundary for catalog loading |
11976
12291
 
11977
12292
  ## `stitchkit/agent-runtime/sqlite/bun`
11978
12293
 
@@ -11981,13 +12296,55 @@ loaded by the neutral, browser or Node runtime surfaces.
11981
12296
 
11982
12297
  | Export | Kind | Summary |
11983
12298
  |--------|------|---------|
11984
- | `createBunSqliteAgentRuntimeStore` | function | open an owned Bun SQLite connection, initialize/validate schema v1 and return `{ store, close }` |
12299
+ | `createBunSqliteAgentRuntimeStore` | function | open an owned Bun SQLite connection, initialize/validate schema v1 and return `{ store, conversations, close }` |
11985
12300
  | `BunSqliteAgentRuntimeStoreConfig` | _type_ | database filename plus optional create and initialization policies |
11986
12301
  | `createSqliteAgentRuntimeStore` | function | build the normalized store over an injected synchronous SQLite boundary |
11987
12302
  | `initializeAgentRuntimeSqlite` | function | initialize or validate only Stitchkit's namespaced SQLite schema |
11988
12303
  | `AgentRuntimeSqliteDatabase` / `AgentRuntimeSqliteStatement` / `AgentRuntimeSqliteValue` | _type_ | minimal runtime-neutral synchronous SQLite boundary |
11989
12304
  | `SqliteAgentRuntimeStore` / `SqliteAgentRuntimeStoreConfig` | _type_ | durable store handle, owned connection lifecycle and initialization policy |
11990
12305
 
12306
+ ---
12307
+
12308
+ ## `stitchkit-tui`
12309
+
12310
+ Separate optional evolving Bun/OpenTUI package over a caller-composed headless harness.
12311
+
12312
+ | Export | Kind | Summary |
12313
+ |--------|------|---------|
12314
+ | `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 |
12315
+ | `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 |
12316
+ | `defineTuiCommand` / `resolveTuiCommand` | function | typed composable slash-command registry; unknown slash input remains an ordinary model prompt |
12317
+ | `createAgentTuiController` | function | single admission, selection, approval, interruption and conversation-switch owner over the harness |
12318
+ | `startAgentTuiSessionHost` / `createAgentTuiClient` | function | authenticated mode-`0600` Unix-socket host/client for status, submit and interrupt through that controller |
12319
+ | `listAgentTuiSessions` | function | discover live local terminal session IDs and their current conversation |
12320
+ | `createAgentTuiComposer` / `navigateAgentTuiHistory` | function | multiline draft and reversible prompt-history state |
12321
+ | `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 |
12322
+ | `createAgentTuiDiagnosticRecorder` / `AgentTuiDiagnosticEventSchema` | function / schema | bounded per-session metadata journal that rejects prompt, reasoning, tool-input and provider-cause payloads before disk admission |
12323
+
12324
+ The `stitchkit-agent` binary loads `stitchkit.agent.ts` by default and also exposes `sessions`,
12325
+ `status`, `send` and `interrupt`. `--workspace` addresses a host outside the caller's cwd,
12326
+ `send --idempotency-key` accepts caller-owned retry identity, and `interrupt` defaults to the
12327
+ active run returned by `status`. Session descriptors and sockets are local control credentials,
12328
+ not a remote API.
12329
+ Interactive `/resume` and `/sessions` open the durable conversation picker. `/clear` creates a new
12330
+ conversation and keeps the previous one available there; it is not a viewport-only operation.
12331
+ The slash palette owns its highlighted selection: Up/Down move it, Tab completes it, Enter runs
12332
+ the exact command and Escape dismisses it. Partial input is never submitted while the palette is
12333
+ active; unknown slash text with no match remains an ordinary model prompt.
12334
+
12335
+ ### `stitchkit-tui/core`
12336
+
12337
+ Renderer-neutral state only. This entrypoint imports neither React/OpenTUI nor the agent runtime.
12338
+
12339
+ | Export | Kind | Summary |
12340
+ |--------|------|---------|
12341
+ | `createTerminalCollection` / `reduceTerminalCollection` | function | identity-stable live collection selection, reconciliation, windowing and resize |
12342
+ | `createTerminalFeedViewport` / `reduceTerminalFeedViewport` | function | generic follow-tail, history anchoring, unseen and bounded visible-range state |
12343
+ | `createTerminalPaneState` / `reduceTerminalPaneState` | function | bounded split-pane focus, resize and single-pane collapse |
12344
+ | `createTerminalCommandPalette` / `terminalCommandMatches` | function | bounded command filtering and keyboard selection over a collision-validated registry |
12345
+ | `resolveExactTerminalCommand` / `validateTerminalCommands` | function | exact dispatch and fail-closed name/alias validation |
12346
+ | `createTerminalOperationState` / `reduceTerminalOperationState` | function | confirmation and single-pending-operation lifecycle |
12347
+
11991
12348
  ## `stitchkit/agent-runtime/sqlite/node`
11992
12349
 
11993
12350
  Node 22.5+ built-in SQLite persistence. It shares the schema and semantics of
@@ -12100,7 +12457,7 @@ payload.
12100
12457
  | `bindStdioProcessSignals` | function | explicitly bind OS signals to one close-only stdio handle — [guide](../guide/testing-and-deployment.md#stdio-process-signals) |
12101
12458
  | `buildMcpServer` | function | build an `McpServer` from contract/runtime surfaces; no-auth configs omit the second argument |
12102
12459
  | `mountMcp` | function | add contract tools to an existing `McpServer` — [guide](../guide/mcp-and-agents.md#mountmcp) |
12103
- | `mountAgent` | function | a Vercel AI SDK `ToolSet` from a service — [guide](../guide/mcp-and-agents.md#ai-agents--mountagent) |
12460
+ | `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](../guide/mcp-and-agents.md#ai-agents--mountagent) |
12104
12461
  | `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) |
12105
12462
  | `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) |
12106
12463
  | `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) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.68.11",
3
+ "version": "0.70.0",
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",
@@ -84,6 +84,14 @@
84
84
  "types": "./dist/agent-runtime.d.ts",
85
85
  "import": "./dist/agent-runtime.js"
86
86
  },
87
+ "./agent-runtime/harness": {
88
+ "types": "./dist/agent-runtime-harness.d.ts",
89
+ "import": "./dist/agent-runtime-harness.js"
90
+ },
91
+ "./agent-runtime/coding-tools": {
92
+ "types": "./dist/agent-runtime-coding-tools.d.ts",
93
+ "import": "./dist/agent-runtime-coding-tools.js"
94
+ },
87
95
  "./agent-runtime/browser": {
88
96
  "types": "./dist/agent-runtime-browser.d.ts",
89
97
  "import": "./dist/agent-runtime-browser.js"
@@ -135,7 +143,7 @@
135
143
  "scripts": {
136
144
  "check": "bun x tsc --noEmit",
137
145
  "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",
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",
146
+ "build:server": "bun build src/server/index.ts src/node.ts src/tools.ts src/tool-invoker.ts src/cli.ts src/remote.ts src/files.ts src/testing.ts src/observability/index.ts src/agent-runtime.ts src/agent-runtime-harness.ts src/agent-runtime-coding-tools.ts src/agent-runtime-openrouter.ts src/agent-runtime-sqlite-bun.ts src/agent-runtime-sqlite-node.ts src/application.ts src/application-grammy.ts src/application-opentelemetry.ts --outdir dist --target node --packages external --splitting --root src",
139
147
  "build:js": "bun run build:browser && bun run build:server && bun scripts/preserve-webpack-ignore.mjs",
140
148
  "build:types": "bun x tsc -p tsconfig.build.json --emitDeclarationOnly && bun scripts/rewrite-declaration-specifiers.mjs",
141
149
  "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",