stitchkit 0.70.6 → 0.72.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.
- package/README.md +1 -1
- package/dist/agent-runtime/coding-tool-contract.d.ts +11 -1
- package/dist/agent-runtime/coding-tool-contract.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-files.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-listing.d.ts +15 -0
- package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -0
- package/dist/agent-runtime/coding-tool-paths.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-refusals.d.ts +59 -0
- package/dist/agent-runtime/coding-tool-refusals.d.ts.map +1 -0
- package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tools.d.ts +3 -1
- package/dist/agent-runtime/coding-tools.d.ts.map +1 -1
- package/dist/agent-runtime/compaction.d.ts +35 -0
- package/dist/agent-runtime/compaction.d.ts.map +1 -1
- package/dist/agent-runtime/contained-files.d.ts +21 -2
- package/dist/agent-runtime/contained-files.d.ts.map +1 -1
- package/dist/agent-runtime/provider-failure.d.ts +66 -0
- package/dist/agent-runtime/provider-failure.d.ts.map +1 -0
- package/dist/agent-runtime/run-execution.d.ts.map +1 -1
- package/dist/agent-runtime/runtime.d.ts +31 -1
- package/dist/agent-runtime/runtime.d.ts.map +1 -1
- package/dist/agent-runtime/schemas.d.ts +1 -0
- package/dist/agent-runtime/schemas.d.ts.map +1 -1
- package/dist/agent-runtime-coding-tools.js +438 -124
- package/dist/agent-runtime-harness.js +4 -4
- package/dist/agent-runtime-openrouter.d.ts +19 -0
- package/dist/agent-runtime-openrouter.d.ts.map +1 -1
- package/dist/agent-runtime-openrouter.js +2 -1
- package/dist/agent-runtime.d.ts +3 -2
- package/dist/agent-runtime.d.ts.map +1 -1
- package/dist/agent-runtime.js +118 -14
- package/dist/application/admission.d.ts +22 -2
- package/dist/application/admission.d.ts.map +1 -1
- package/dist/application/channel.d.ts +28 -0
- package/dist/application/channel.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-contract.d.ts +20 -0
- package/dist/application/diagnostic-journal-contract.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-lock.d.ts +17 -0
- package/dist/application/diagnostic-journal-lock.d.ts.map +1 -0
- package/dist/application/diagnostic-journal-manager.d.ts +2 -1
- package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-storage.d.ts +4 -1
- package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
- package/dist/application/diagnostic-journal.d.ts +4 -2
- package/dist/application/diagnostic-journal.d.ts.map +1 -1
- package/dist/application-opentelemetry.js +1 -1
- package/dist/application.d.ts +3 -3
- package/dist/application.d.ts.map +1 -1
- package/dist/application.js +134 -21
- package/dist/browser/resumable.d.ts +56 -0
- package/dist/browser/resumable.d.ts.map +1 -0
- package/dist/cli.js +5 -5
- package/dist/{index-cx84zg25.js → index-118v0z41.js} +1 -1
- package/dist/{index-zpyj7hsv.js → index-3cwck0rm.js} +98 -33
- package/dist/{index-ejv31h14.js → index-7qy2ex0m.js} +1 -1
- package/dist/{index-trrf7nch.js → index-ezmn6ac6.js} +3 -3
- package/dist/{index-ekkt4gy9.js → index-jqtsc9mj.js} +2 -2
- package/dist/{index-hxtm2xr2.js → index-k2zczx1g.js} +1 -1
- package/dist/{index-by57nwhc.js → index-m668wzyc.js} +10 -2
- package/dist/{index-w9m1wznn.js → index-nemjkxjp.js} +118 -1
- package/dist/{index-tnazr5tc.js → index-pz7ytdga.js} +3 -3
- package/dist/{index-1z5xxfst.js → index-rqpdar1e.js} +102 -5
- package/dist/{index-qm87g51s.js → index-s4c8wy8m.js} +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +103 -14
- package/dist/node.js +2 -2
- package/dist/observability/index.js +1 -1
- package/dist/primitives/audit.d.ts +52 -0
- package/dist/primitives/audit.d.ts.map +1 -0
- package/dist/primitives/deadline.d.ts +39 -0
- package/dist/primitives/deadline.d.ts.map +1 -0
- package/dist/primitives/decimal.d.ts +10 -0
- package/dist/primitives/decimal.d.ts.map +1 -0
- package/dist/primitives/delivery.d.ts +96 -0
- package/dist/primitives/delivery.d.ts.map +1 -0
- package/dist/primitives/event.d.ts +42 -0
- package/dist/primitives/event.d.ts.map +1 -0
- package/dist/primitives/export-operation.d.ts +89 -0
- package/dist/primitives/export-operation.d.ts.map +1 -0
- package/dist/primitives/index.d.ts +12 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/lifecycle.d.ts +90 -0
- package/dist/primitives/lifecycle.d.ts.map +1 -0
- package/dist/primitives/migration-checks.d.ts +15 -0
- package/dist/primitives/migration-checks.d.ts.map +1 -0
- package/dist/primitives/money.d.ts +43 -0
- package/dist/primitives/money.d.ts.map +1 -0
- package/dist/primitives/owner-scope.d.ts +30 -0
- package/dist/primitives/owner-scope.d.ts.map +1 -0
- package/dist/primitives/permission.d.ts +28 -0
- package/dist/primitives/permission.d.ts.map +1 -0
- package/dist/primitives/quantity.d.ts +57 -0
- package/dist/primitives/quantity.d.ts.map +1 -0
- package/dist/primitives.d.ts +3 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +750 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -2
- package/dist/server/request.d.ts +19 -0
- package/dist/server/request.d.ts.map +1 -1
- package/dist/telegram/init-data.d.ts +134 -0
- package/dist/telegram/init-data.d.ts.map +1 -0
- package/dist/telegram/send-failure.d.ts +73 -0
- package/dist/telegram/send-failure.d.ts.map +1 -0
- package/dist/telegram.d.ts +3 -0
- package/dist/telegram.d.ts.map +1 -0
- package/dist/telegram.js +224 -0
- package/dist/tool-invoker.js +4 -4
- package/dist/tools.js +7 -7
- package/llms-full.txt +510 -10
- package/llms.txt +1 -0
- package/native/darwin-arm64.node +0 -0
- package/native/darwin-x64.node +0 -0
- package/package.json +11 -3
package/llms-full.txt
CHANGED
|
@@ -48,6 +48,7 @@ own, recorded as an ADR.
|
|
|
48
48
|
|--------|--------|----------|-------|
|
|
49
49
|
| `stitchkit` | browser **and** server | stable | `defineContract`, `createClient`, `createHttpClient`, `createSocketIOClient`, `parseSSE`, the error model |
|
|
50
50
|
| `stitchkit/contract` | browser **and** server | stable | the contract layer alone — `defineContract`, errors, pagination |
|
|
51
|
+
| `stitchkit/primitives` | browser **and** server | evolving | generic values and declarations for lifecycle, access, audit, delivery and exports |
|
|
51
52
|
| `stitchkit/server` | server (Bun) | stable | `createServer`, `implement`, hooks, auth, Socket.IO server, server primitives |
|
|
52
53
|
| `stitchkit/node` | server (Node ≥ 22) | stable | `serveNode` + the runtime-agnostic core — the Node mirror of `/server` |
|
|
53
54
|
| `stitchkit/tools` | server | stable | `createMcpHandler`, `mountMcp`, `mountAgent`, the OAuth provider, native tools |
|
|
@@ -55,11 +56,12 @@ own, recorded as an ADR.
|
|
|
55
56
|
| `stitchkit/cli` | server | stable | `createCli` — the CLI transport, light (no MCP SDK / `ai`) |
|
|
56
57
|
| `stitchkit/remote` | browser **and** server | stable | peer-free `implementRemote` for thin HTTP proxy processes |
|
|
57
58
|
| `stitchkit/files` | server (Bun or Node) | stable | peer-free managed local-file boundary |
|
|
59
|
+
| `stitchkit/telegram` | server (Bun or Node) | evolving | peer-free Telegram platform primitives — Mini App `initData` verification and Bot API send-failure classification |
|
|
58
60
|
| `stitchkit/observability` | server | stable | request/tool event projections — `createObservability`, trace context, sanitisation |
|
|
59
61
|
| `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
62
|
| `stitchkit/declaration` | build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
|
|
61
63
|
| `stitchkit/react` | browser | stable | `createCursorQuery`, `createCacheBridge` |
|
|
62
|
-
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 10 of the
|
|
64
|
+
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 10 of the 17 minors since 0.56.2, most recently 0.69.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
|
|
63
65
|
| `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
|
|
64
66
|
| `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 |
|
|
65
67
|
| `stitchkit/agent-runtime/openrouter` | server | evolving | isolated OpenRouter language-model adapter |
|
|
@@ -67,7 +69,7 @@ own, recorded as an ADR.
|
|
|
67
69
|
| `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
|
|
68
70
|
| `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
|
|
69
71
|
| `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
|
|
70
|
-
| `stitchkit/application` | server | evolving<br>_redefined in
|
|
72
|
+
| `stitchkit/application` | server | evolving<br>_redefined in 4 of the 17 minors since 0.56.2, most recently 0.72.0_ | managed resource graph, readiness, admission, schedules and bounded shutdown |
|
|
71
73
|
| `stitchkit/application/grammy` | server | evolving | isolated grammY polling and webhook lifecycle adapters |
|
|
72
74
|
| `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
|
|
73
75
|
|
|
@@ -180,6 +182,7 @@ map — feature → packages:
|
|
|
180
182
|
| **Socket.IO server on Node** | `socket.io` |
|
|
181
183
|
| Socket.IO client | `socket.io-client` (runtime peer; unrelated root declarations remain peer-free) |
|
|
182
184
|
| grammY lifecycle adapters (`stitchkit/application/grammy`) | `grammy` |
|
|
185
|
+
| Telegram platform primitives (`stitchkit/telegram`) | — (peer-free) |
|
|
183
186
|
| OpenTelemetry gauges (`stitchkit/application/opentelemetry`) | `@opentelemetry/api` |
|
|
184
187
|
|
|
185
188
|
```bash
|
|
@@ -2563,6 +2566,49 @@ Set `finalLine: 'require-newline'` when the final newline is part of the
|
|
|
2563
2566
|
protocol's truncation proof. The default `allow` continues to accept one valid
|
|
2564
2567
|
final JSON document without a newline.
|
|
2565
2568
|
|
|
2569
|
+
## Resumable streams
|
|
2570
|
+
|
|
2571
|
+
A stream that survives a dropped connection needs four things beyond opening it:
|
|
2572
|
+
re-open, back off before retrying, resume from where it stopped rather than
|
|
2573
|
+
restart, and stop for good on a terminal item. `resumableIterator` owns those
|
|
2574
|
+
four; your code keeps every decision that is about your data.
|
|
2575
|
+
|
|
2576
|
+
```ts
|
|
2577
|
+
import { resumableIterator } from 'stitchkit'
|
|
2578
|
+
|
|
2579
|
+
for await (const event of resumableIterator<Event, string>({
|
|
2580
|
+
async open(cursor) {
|
|
2581
|
+
const url = cursor ? `/api/events?after=${cursor}` : '/api/events'
|
|
2582
|
+
return parseNDJSON(await fetch(url, { signal }))
|
|
2583
|
+
},
|
|
2584
|
+
advance: (event) => event.id, // what "where it stopped" means
|
|
2585
|
+
isTerminal: (event) => event.done, // which item ends the stream
|
|
2586
|
+
retry: { minDelayMs: 500, maxDelayMs: 30_000, jitter: 0.5 },
|
|
2587
|
+
signal,
|
|
2588
|
+
onAttempt: ({ number, delayMs, error }) => log.warn({ number, delayMs, error }),
|
|
2589
|
+
})) {
|
|
2590
|
+
render(event)
|
|
2591
|
+
}
|
|
2592
|
+
```
|
|
2593
|
+
|
|
2594
|
+
`open` receives the cursor produced by the last **delivered** item, so a source
|
|
2595
|
+
that fails after three items re-opens after the third, not from the beginning.
|
|
2596
|
+
A source that simply ends without a terminal item is treated as a dropped
|
|
2597
|
+
connection — that is the case a hand-written loop usually mistakes for
|
|
2598
|
+
completion, and it is why the stream stops resuming.
|
|
2599
|
+
|
|
2600
|
+
**Jitter is not a detail.** Without it every consumer that lost the same server
|
|
2601
|
+
retries at the same instant and the fleet arrives together on a server that has
|
|
2602
|
+
just come back. The randomisation only ever *shortens* a delay, so `maxDelayMs`
|
|
2603
|
+
stays a real ceiling. `createBackoff({ minDelayMs, maxDelayMs, jitter })` is the
|
|
2604
|
+
same policy as a standalone value — `next()` and `reset()` — when you need the
|
|
2605
|
+
delays without the iterator.
|
|
2606
|
+
|
|
2607
|
+
A delivered item resets the backoff, so a stream that reconnects, works for an
|
|
2608
|
+
hour and drops again starts its next retry at `minDelayMs` rather than the
|
|
2609
|
+
ceiling it reached last time. Aborting the signal ends the iteration promptly,
|
|
2610
|
+
including in the middle of a wait.
|
|
2611
|
+
|
|
2566
2612
|
|
|
2567
2613
|
==============================================================================
|
|
2568
2614
|
# Guide: MCP & agents (docs/guide/mcp-and-agents.md)
|
|
@@ -4101,7 +4147,8 @@ responses and results with a different call or tool name are invalid; dropping a
|
|
|
4101
4147
|
approval input fails the run with a private diagnostic rather than starting a fresh model turn.
|
|
4102
4148
|
|
|
4103
4149
|
`stitchkit/agent-runtime/coding-tools` returns ordinary direct runtime tools named `read_file`,
|
|
4104
|
-
`write_file`, `
|
|
4150
|
+
`write_file`, `edit_file`, `list_directory`, `glob`, `search_files`, `run_command` and optional
|
|
4151
|
+
`read_output`. Every call passes a
|
|
4105
4152
|
required host authorization callback. File paths are relative, bounded and contained after
|
|
4106
4153
|
descriptor-relative resolution: each ancestor is opened without following symlinks and remains
|
|
4107
4154
|
pinned through authorization and the filesystem effect. Reads revalidate the pinned file identity;
|
|
@@ -4117,10 +4164,32 @@ Arguments, output and time are bounded, while cancellation terminates the child.
|
|
|
4117
4164
|
root and cwd are path boundaries, not a security sandbox: isolate the process when an executable
|
|
4118
4165
|
must not access the rest of the machine.
|
|
4119
4166
|
|
|
4120
|
-
`
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4167
|
+
`edit_file` replaces one exact snippet. `oldText` is itself the freshness guard for the region it
|
|
4168
|
+
changes, so the digest is the optional `expectedSha256` and an edit is one call; pass the digest
|
|
4169
|
+
`read_file` returned when you want the whole-file guarantee, and read the `sha256` it returns to
|
|
4170
|
+
chain the next edit without re-reading. The read, the occurrence count and the construction of the
|
|
4171
|
+
new content all happen inside one per-target lock, so two concurrent edits of different snippets in
|
|
4172
|
+
one file cannot each build a file from the same base and have the second erase the first — the lock
|
|
4173
|
+
is process-local, which covers many agents in one process and not two processes over one workspace.
|
|
4174
|
+
It authorizes the exact replacement count, result digest and byte size, and deliberately does not
|
|
4175
|
+
claim multi-file atomicity.
|
|
4176
|
+
|
|
4177
|
+
`write_file` creates missing parent directories inside the root and names them in
|
|
4178
|
+
`createdDirectories`; the walk that finds them runs before authorization and reports them in the
|
|
4179
|
+
authorization payload, so no directory is created before a host approves it.
|
|
4180
|
+
|
|
4181
|
+
**Every ordinary outcome is a refusal a model can act on** — a missing file is `NOT_FOUND`, an
|
|
4182
|
+
existing file without `overwrite` is `CONFLICT`, an ambiguous snippet is `CONFLICT` carrying its
|
|
4183
|
+
occurrence count, a path outside the root is `FORBIDDEN` — each with a `hint` naming the next move.
|
|
4184
|
+
Host-level causes stay scrubbed to `INTERNAL_SERVER_ERROR` and name nothing outside the workspace.
|
|
4185
|
+
→ ADR 0139
|
|
4186
|
+
|
|
4187
|
+
`list_directory` marks excluded directories rather than hiding them, and `glob` reports
|
|
4188
|
+
`skippedDirectories` beside its matches: an empty result from a tree whose files all live under an
|
|
4189
|
+
excluded directory is not "no files", and a model told only "nothing found" concludes the wrong
|
|
4190
|
+
thing. `search_files` takes `regex`, `context` lines and an `include` pattern; regex is bounded by
|
|
4191
|
+
refusing backreferences and lookaround and capping line length rather than by a timeout, because a
|
|
4192
|
+
JavaScript `RegExp` cannot be interrupted once it starts backtracking. With an optional `AgentCodingArtifactStore`, shell output beyond the inline
|
|
4124
4193
|
preview continues into an opaque bounded artifact and `read_output` reads slices without
|
|
4125
4194
|
exposing a host path. Without a store, the previous finite output-limit behavior is unchanged.
|
|
4126
4195
|
|
|
@@ -4807,6 +4876,40 @@ replace a leading summary on the next compaction.
|
|
|
4807
4876
|
Set `maxAttempts` to allow bounded conflict recovery. Every retry reloads the snapshot, reselects the
|
|
4808
4877
|
eligible range and recomputes the summary; the stale summary is never retried.
|
|
4809
4878
|
|
|
4879
|
+
### Compacting without the store
|
|
4880
|
+
|
|
4881
|
+
The *selection* inside compaction needs no store, no version and no runtime, so
|
|
4882
|
+
it is published on its own as `selectCompactableHistory` — for an application
|
|
4883
|
+
that drives the model itself and keeps its own history (→ ADR 0142):
|
|
4884
|
+
|
|
4885
|
+
```ts
|
|
4886
|
+
import { selectCompactableHistory } from 'stitchkit/agent-runtime'
|
|
4887
|
+
|
|
4888
|
+
const { leadingSummary, compactable, retained } = selectCompactableHistory({
|
|
4889
|
+
messages,
|
|
4890
|
+
keepRecentTurns: 3,
|
|
4891
|
+
})
|
|
4892
|
+
if (compactable.length > 0) {
|
|
4893
|
+
const summary = await summarize(compactable, leadingSummary)
|
|
4894
|
+
messages = [summary, ...retained] // replace the old summary, never stack one
|
|
4895
|
+
}
|
|
4896
|
+
```
|
|
4897
|
+
|
|
4898
|
+
`compactable` is the oldest **whole complete** turns and `retained` is
|
|
4899
|
+
everything the model must still hear; together they are the input, in order. A
|
|
4900
|
+
turn holding a tool call whose result never arrived is never eligible, and
|
|
4901
|
+
neither is anything after it: half a turn hands the provider a call with no
|
|
4902
|
+
result, which most of them refuse outright.
|
|
4903
|
+
|
|
4904
|
+
`structuredCompaction` calls this same function, so the published selection and
|
|
4905
|
+
the runtime's cannot drift into two behaviours. What it adds is the part that
|
|
4906
|
+
does need the store — writing the result back under a version check.
|
|
4907
|
+
|
|
4908
|
+
Deciding *when* to compact is yours: `AgentRuntimeRunContext.contextUsage`
|
|
4909
|
+
carries the last step's prompt size beside the model's window, and dividing them
|
|
4910
|
+
is one line where the threshold is decided. The core does not own that ratio, on
|
|
4911
|
+
purpose — see ADR 0142 for what it publishes and what it declines to.
|
|
4912
|
+
|
|
4810
4913
|
## Observability
|
|
4811
4914
|
|
|
4812
4915
|
`createAgentObservability` emits a separate operator-only `AgentRunEvent`. It
|
|
@@ -5550,6 +5653,110 @@ retry rules do **not** disappear. They were never process-local glue and remain
|
|
|
5550
5653
|
application-owned.
|
|
5551
5654
|
|
|
5552
5655
|
|
|
5656
|
+
==============================================================================
|
|
5657
|
+
# Guide: Generic application primitives (docs/guide/primitives.md)
|
|
5658
|
+
==============================================================================
|
|
5659
|
+
|
|
5660
|
+
---
|
|
5661
|
+
title: Generic application primitives
|
|
5662
|
+
description: Declare lifecycle, access, exact values, audit, delivery and exports without moving application infrastructure into Stitchkit.
|
|
5663
|
+
type: guide
|
|
5664
|
+
status: active
|
|
5665
|
+
created: 2026-09-01
|
|
5666
|
+
updated: 2026-09-01
|
|
5667
|
+
---
|
|
5668
|
+
|
|
5669
|
+
# Generic application primitives
|
|
5670
|
+
|
|
5671
|
+
`stitchkit/primitives` is an optional browser-safe leaf. It declares values and policies; it does
|
|
5672
|
+
not own a database, transaction, scheduler, durable queue, transport or document generator.
|
|
5673
|
+
|
|
5674
|
+
## Lifecycle and access
|
|
5675
|
+
|
|
5676
|
+
```ts
|
|
5677
|
+
import { defineLifecycle, defineOwnerScope, definePermissionMatrix } from 'stitchkit/primitives';
|
|
5678
|
+
import { z } from 'zod';
|
|
5679
|
+
|
|
5680
|
+
const lifecycle = defineLifecycle({
|
|
5681
|
+
name: 'document',
|
|
5682
|
+
states: ['draft', 'published'],
|
|
5683
|
+
roles: ['author'],
|
|
5684
|
+
transitions: {
|
|
5685
|
+
publish: {
|
|
5686
|
+
from: 'draft',
|
|
5687
|
+
to: 'published',
|
|
5688
|
+
by: ['author'],
|
|
5689
|
+
payload: z.object({ note: z.string() }),
|
|
5690
|
+
},
|
|
5691
|
+
},
|
|
5692
|
+
});
|
|
5693
|
+
|
|
5694
|
+
const permissions = definePermissionMatrix({
|
|
5695
|
+
roles: ['reader', 'author'],
|
|
5696
|
+
operations: ['read', 'publish'],
|
|
5697
|
+
grants: {
|
|
5698
|
+
reader: { read: true, publish: false },
|
|
5699
|
+
author: { read: true, publish: true },
|
|
5700
|
+
},
|
|
5701
|
+
});
|
|
5702
|
+
```
|
|
5703
|
+
|
|
5704
|
+
Persist `transition(...).event` in the same application transaction as the next state. A state is
|
|
5705
|
+
an immutable branded value; `transition()` produces the next one. `availableTransitions()` and
|
|
5706
|
+
`transition()` read the same declaration.
|
|
5707
|
+
|
|
5708
|
+
`defineOwnerScope` resolves one owner from authenticated identity. Reading across owners is a
|
|
5709
|
+
separate `acrossAllOwners(identity)` call and permission. Pass the resulting branded `OwnerScope`
|
|
5710
|
+
to the data adapter. This proves the scope was explicit; Stitchkit cannot prove what SQL an
|
|
5711
|
+
arbitrary adapter emits. `scanOwnerFilterRisks` maps existing caller-named manual filters before a
|
|
5712
|
+
migration.
|
|
5713
|
+
|
|
5714
|
+
## Exact values and deadlines
|
|
5715
|
+
|
|
5716
|
+
`defineMoney(currency)` stores integer minor units as a JSON string. Arithmetic keeps the currency
|
|
5717
|
+
literal in the type; division and rational shares return an explicit remainder. It does not own
|
|
5718
|
+
exchange rates.
|
|
5719
|
+
|
|
5720
|
+
`defineUnitSystem` stores exact canonical decimal strings. Every conversion is an application
|
|
5721
|
+
rational with an id. A converted `QuantityProjection` is `derived` and carries both its source and
|
|
5722
|
+
conversion id; a form/database value can be marked `recorded`. Whether a derived projection is
|
|
5723
|
+
persisted or recomputed is an application decision.
|
|
5724
|
+
|
|
5725
|
+
`defineDeadlinePolicy` requires an explicit `now`, IANA timezone and elapsed/calendar-day boundary.
|
|
5726
|
+
It returns the due instant, signed remaining days, overdue days and caller-owned category key.
|
|
5727
|
+
`queryBoundary(now)` returns instants suitable for a data-adapter predicate; reminders and
|
|
5728
|
+
escalations are not included.
|
|
5729
|
+
|
|
5730
|
+
## Audit and delivery
|
|
5731
|
+
|
|
5732
|
+
Put an audit decision beside each operation:
|
|
5733
|
+
|
|
5734
|
+
```ts
|
|
5735
|
+
meta: { audit: audit.record(z.object({ changed: z.array(z.string()) })) }
|
|
5736
|
+
// or
|
|
5737
|
+
meta: { audit: audit.omit('read-only projection') }
|
|
5738
|
+
```
|
|
5739
|
+
|
|
5740
|
+
`assertAuditDeclared(contract)` refuses silence. `createAuditRecord()` validates the change and
|
|
5741
|
+
returns a `DomainEvent`; the same id/value can feed both the journal and delivery.
|
|
5742
|
+
|
|
5743
|
+
`defineDomainEventDelivery().plan(event)` is pure. Save that event and its destinations in the
|
|
5744
|
+
application's transaction. After commit, call `dispatch(event.id)`: the dispatcher accepts only an
|
|
5745
|
+
id and obtains actual work from `DomainEventOutbox.claim`. A transport returns `delivered`,
|
|
5746
|
+
`retryable`, `terminal` or `unknown`; the dispatcher calls the matching outbox transition. Only
|
|
5747
|
+
`retry` may schedule another claim, while `unknown` is held for inspection instead of guessed into
|
|
5748
|
+
a retry. The application owns retention and scheduling. There is deliberately no scheduler or
|
|
5749
|
+
distributed lease.
|
|
5750
|
+
|
|
5751
|
+
## Exports
|
|
5752
|
+
|
|
5753
|
+
`defineExportOperation` supplies one input and one result schema to an ordinary contract endpoint.
|
|
5754
|
+
A small result can be `ready` with a `ManagedFileRef`; a larger result can be `pending` with the id
|
|
5755
|
+
of the application's existing async operation. The input, scope, metadata and tool identity do not
|
|
5756
|
+
change. The application creates bytes and owns operation persistence; the managed-file boundary
|
|
5757
|
+
streams them.
|
|
5758
|
+
|
|
5759
|
+
|
|
5553
5760
|
==============================================================================
|
|
5554
5761
|
# Guide: Application migration recipes (docs/guide/application-migration-recipes.md)
|
|
5555
5762
|
==============================================================================
|
|
@@ -7445,6 +7652,68 @@ const payload = await verifyJwt(token, env.JWT_SECRET)
|
|
|
7445
7652
|
`extractToken(req, cookieName?)` reads a bearer token from the `Authorization`
|
|
7446
7653
|
header, or from the named cookie.
|
|
7447
7654
|
|
|
7655
|
+
## Telegram Mini Apps
|
|
7656
|
+
|
|
7657
|
+
A Mini App hands its backend an `initData` query string that Telegram signed
|
|
7658
|
+
with a key derived from the bot token. `verifyTelegramInitData` checks that
|
|
7659
|
+
signature and reports what the string says — and refuses with a **reason**,
|
|
7660
|
+
because an application answers a stale string differently from a forged one.
|
|
7661
|
+
|
|
7662
|
+
```ts
|
|
7663
|
+
import { verifyTelegramInitData } from 'stitchkit/telegram'
|
|
7664
|
+
import { unauthorized } from 'stitchkit/contract'
|
|
7665
|
+
import { env } from './env'
|
|
7666
|
+
|
|
7667
|
+
const result = await verifyTelegramInitData({
|
|
7668
|
+
initData,
|
|
7669
|
+
botToken: env.BOT_TOKEN,
|
|
7670
|
+
maxAgeSeconds: 3600, // a signed string is otherwise valid forever
|
|
7671
|
+
})
|
|
7672
|
+
if (!result.valid) {
|
|
7673
|
+
// 'missing-hash' | 'signature-mismatch' | 'malformed' | 'expired'
|
|
7674
|
+
throw unauthorized(result.reason === 'expired' ? 'Reopen the app' : 'Invalid session')
|
|
7675
|
+
}
|
|
7676
|
+
const telegramId = result.data.user?.id
|
|
7677
|
+
```
|
|
7678
|
+
|
|
7679
|
+
Three things it does that a hand-written check usually does not:
|
|
7680
|
+
|
|
7681
|
+
- the **signature is checked first**, before `auth_date` or anything else is
|
|
7682
|
+
read — an expiry inside an unverified payload is a number the sender chose;
|
|
7683
|
+
- digests are compared **without an early exit**, so the time a rejection takes
|
|
7684
|
+
is not a measurement of how much of the digest was right;
|
|
7685
|
+
- `raw` keeps every signed pair, so a field Telegram adds after this release
|
|
7686
|
+
does not need a release to reach.
|
|
7687
|
+
|
|
7688
|
+
`maxAgeSeconds` is optional and there is no default: only the application knows
|
|
7689
|
+
how long its own session is worth. Omitting it means the string never expires,
|
|
7690
|
+
which is a decision rather than an oversight.
|
|
7691
|
+
|
|
7692
|
+
The module is server-only and pulls in no bot library — the token never belongs
|
|
7693
|
+
in a browser bundle. `stitchkit/application/grammy` remains the lifecycle
|
|
7694
|
+
adapter for an injected grammY bot. Its companion,
|
|
7695
|
+
`classifyTelegramSendFailure`, names why a send was refused and separates *retry
|
|
7696
|
+
this send* from *stop addressing this recipient*:
|
|
7697
|
+
|
|
7698
|
+
```ts
|
|
7699
|
+
import { classifyTelegramSendFailure } from 'stitchkit/telegram'
|
|
7700
|
+
|
|
7701
|
+
try {
|
|
7702
|
+
await bot.api.sendMessage(chatId, text)
|
|
7703
|
+
} catch (error) {
|
|
7704
|
+
const failure = classifyTelegramSendFailure(error)
|
|
7705
|
+
if (failure.recipientUnreachable) await markUnreachable(chatId, failure.reason)
|
|
7706
|
+
else if (failure.retryable) await requeue(chatId, failure.retryAfterSeconds)
|
|
7707
|
+
}
|
|
7708
|
+
```
|
|
7709
|
+
|
|
7710
|
+
The two flags are separate because one answer cannot serve both. A rate limit is
|
|
7711
|
+
retryable and implicates nobody; a blocked user is unreachable and no retry
|
|
7712
|
+
helps; a message Telegram could not parse is *neither* — the recipient is fine
|
|
7713
|
+
and our payload is wrong, which is the case a list of substrings quietly counts
|
|
7714
|
+
against the user. An unrecognised refusal leaves the recipient reachable: losing
|
|
7715
|
+
a working subscriber forever costs more than one wasted send.
|
|
7716
|
+
|
|
7448
7717
|
## Cookies
|
|
7449
7718
|
|
|
7450
7719
|
```ts
|
|
@@ -9172,6 +9441,133 @@ additive** — adopting it changes nothing in your code. (See
|
|
|
9172
9441
|
So upgrading is: read the `### ⚠️ Breaking changes` of every version *above* your
|
|
9173
9442
|
current one *up to* your target, and apply each snippet.
|
|
9174
9443
|
|
|
9444
|
+
## Released migration: 0.72.0
|
|
9445
|
+
|
|
9446
|
+
Nothing you *pass* changed. Both items are about types you read or build, and
|
|
9447
|
+
both stop the compiler rather than surprising you at runtime.
|
|
9448
|
+
|
|
9449
|
+
### If you read `perKey` off `BoundedAdmissionPolicy`
|
|
9450
|
+
|
|
9451
|
+
`perKey` is now a union: the flat ceiling it always was, or `{ maxKeys, limits }`
|
|
9452
|
+
where the ceiling is resolved from the key. Declaring one is unchanged; reading
|
|
9453
|
+
one needs a narrowing.
|
|
9454
|
+
|
|
9455
|
+
```ts
|
|
9456
|
+
// before
|
|
9457
|
+
const ceiling = policy.perKey?.maxConcurrent
|
|
9458
|
+
|
|
9459
|
+
// after
|
|
9460
|
+
const ceiling =
|
|
9461
|
+
policy.perKey && !('limits' in policy.perKey) ? policy.perKey.maxConcurrent : undefined
|
|
9462
|
+
```
|
|
9463
|
+
|
|
9464
|
+
A shape carrying members of both branches — `{ maxKeys, maxConcurrent, limits }` —
|
|
9465
|
+
is refused at construction. It does *not* fail to typecheck: an excess-property
|
|
9466
|
+
check against a union admits any property some member declares, so this one is
|
|
9467
|
+
caught by `createBoundedAdmission`, not by `tsc`.
|
|
9468
|
+
|
|
9469
|
+
### If you build a snapshot or a status by hand
|
|
9470
|
+
|
|
9471
|
+
`CreditWindowSnapshot` gained `waiting` (producers parked in the new waiting
|
|
9472
|
+
`acquire`) and `DiagnosticJournalStatus` gained `lock`. Both are produced by the
|
|
9473
|
+
framework, so reading them is unaffected — but a test double stops compiling:
|
|
9474
|
+
|
|
9475
|
+
```ts
|
|
9476
|
+
// before
|
|
9477
|
+
const snapshot: CreditWindowSnapshot = { state: 'open', capacityBytes: 100, /* … */ }
|
|
9478
|
+
|
|
9479
|
+
// after
|
|
9480
|
+
const snapshot: CreditWindowSnapshot = { state: 'open', capacityBytes: 100, /* … */ waiting: 0 }
|
|
9481
|
+
```
|
|
9482
|
+
|
|
9483
|
+
## Released migration: 0.71.0
|
|
9484
|
+
|
|
9485
|
+
The Agent coding tools. Two of the three changes are visible to the compiler;
|
|
9486
|
+
the third is the one to read carefully, because nothing will point at it.
|
|
9487
|
+
|
|
9488
|
+
### If you implement `authorize`
|
|
9489
|
+
|
|
9490
|
+
The operation union gained `edit`, `list` and `glob` and lost `patch`. An
|
|
9491
|
+
exhaustive matcher stops compiling and the compiler shows you every arm. **A
|
|
9492
|
+
matcher with a default branch does not**, and that is the dangerous case:
|
|
9493
|
+
|
|
9494
|
+
```ts
|
|
9495
|
+
// before — and after this upgrade, silently wrong in both directions
|
|
9496
|
+
if (request.operation === 'patch') return reviewPatch(request)
|
|
9497
|
+
return true // now also authorizes edit, list and glob
|
|
9498
|
+
// …or: return false // now also kills edit_file
|
|
9499
|
+
```
|
|
9500
|
+
|
|
9501
|
+
```ts
|
|
9502
|
+
// after
|
|
9503
|
+
switch (request.operation) {
|
|
9504
|
+
case 'edit': return reviewEdit(request) // the old `patch` payload, unchanged
|
|
9505
|
+
case 'list':
|
|
9506
|
+
case 'glob': return true // or your own policy
|
|
9507
|
+
// …existing read / write / search / shell / artifact-read arms
|
|
9508
|
+
}
|
|
9509
|
+
```
|
|
9510
|
+
|
|
9511
|
+
`write` gained `createsDirectories` — the workspace-relative directories the
|
|
9512
|
+
call would create, outermost first, reported **before** anything is created. A
|
|
9513
|
+
host that wants to refuse implicit directory creation now can.
|
|
9514
|
+
|
|
9515
|
+
### If you call `apply_patch`
|
|
9516
|
+
|
|
9517
|
+
It is `edit_file`, and it is one call:
|
|
9518
|
+
|
|
9519
|
+
```ts
|
|
9520
|
+
// before
|
|
9521
|
+
const read = await readFile({ path })
|
|
9522
|
+
await applyPatch({ path, baseSha256: read.sha256, oldText, newText, dryRun: true })
|
|
9523
|
+
await applyPatch({ path, baseSha256: read.sha256, oldText, newText, dryRun: false })
|
|
9524
|
+
|
|
9525
|
+
// after
|
|
9526
|
+
await editFile({ path, oldText, newText })
|
|
9527
|
+
```
|
|
9528
|
+
|
|
9529
|
+
`expectedSha256` is optional and still refuses a stale base with `CONFLICT` when
|
|
9530
|
+
you pass it; `edit_file` returns the resulting `sha256`, so a chain of edits
|
|
9531
|
+
never needs to re-read. If you key an approval policy or a UI label on the string
|
|
9532
|
+
`apply_patch`, update the key — nothing will fail loudly.
|
|
9533
|
+
|
|
9534
|
+
### If you match on `INTERNAL_SERVER_ERROR` from a coding tool
|
|
9535
|
+
|
|
9536
|
+
Ordinary outcomes no longer arrive that way. A missing file is `NOT_FOUND`, an
|
|
9537
|
+
existing file without `overwrite` is `CONFLICT`, an ambiguous snippet is
|
|
9538
|
+
`CONFLICT` with the occurrence count, a path outside the root is `FORBIDDEN`.
|
|
9539
|
+
Code that treated any coding-tool failure as an internal fault will now see
|
|
9540
|
+
codes it did not before; code that showed the model an empty error now has a
|
|
9541
|
+
sentence and a `hint` to show it. Host-level causes are unchanged and still
|
|
9542
|
+
scrubbed.
|
|
9543
|
+
|
|
9544
|
+
### If you write files into new directories
|
|
9545
|
+
|
|
9546
|
+
Nothing to change: `write_file` creates missing parents inside the root. Read
|
|
9547
|
+
`createdDirectories` in the result if you want to notice a typo — a path that
|
|
9548
|
+
was a failure before is now a successful write into a new tree.
|
|
9549
|
+
|
|
9550
|
+
### If you want a step to know its context budget
|
|
9551
|
+
|
|
9552
|
+
Opt in by reading it; nothing is injected for you:
|
|
9553
|
+
|
|
9554
|
+
```ts
|
|
9555
|
+
loop: {
|
|
9556
|
+
prepareStep: ({ contextUsage }) => {
|
|
9557
|
+
const used = contextUsage?.usedTokens
|
|
9558
|
+
if (used?.provenance === 'unavailable') return {} // no step has landed yet
|
|
9559
|
+
const fraction = (used?.value ?? 0) / (contextUsage?.contextWindow ?? 1)
|
|
9560
|
+
// …render it wherever you put it
|
|
9561
|
+
return {}
|
|
9562
|
+
},
|
|
9563
|
+
}
|
|
9564
|
+
```
|
|
9565
|
+
|
|
9566
|
+
Put it at the **tail** of the conversation rather than in the system
|
|
9567
|
+
instructions unless you have a reason: changing the system prompt on every step
|
|
9568
|
+
invalidates the provider's prefix cache for the whole conversation, and on a long
|
|
9569
|
+
run that is a multiple of the input cost.
|
|
9570
|
+
|
|
9175
9571
|
## Released migration: 0.70.0
|
|
9176
9572
|
|
|
9177
9573
|
### Descriptor-backed Agent filesystem containment
|
|
@@ -11811,6 +12207,8 @@ The browser-and-server entrypoint. Re-exports everything from
|
|
|
11811
12207
|
| `createRetainedTopics` | function | retained last-value store for sticky events — [guide](../guide/realtime.md#sticky-events) |
|
|
11812
12208
|
| `parseSSE` | function | parse an SSE `Response` into an async generator — [guide](../guide/client.md#sse) |
|
|
11813
12209
|
| `parseNDJSON` | function | parse bounded fatal-UTF-8 NDJSON; blank keep-alives are skipped and `finalLine: 'require-newline'` can make the delimiter mandatory — [guide](../guide/client.md#ndjson) |
|
|
12210
|
+
| `resumableIterator` | function | re-open a long-lived stream from the last delivered cursor, with jittered backoff, a caller-owned terminal item and prompt abort — [guide](../guide/client.md#resumable-streams) |
|
|
12211
|
+
| `createBackoff` | function | exponential backoff with subtractive jitter as a value: `next()` / `reset()` |
|
|
11814
12212
|
| `ContractStreamFrameSchema` / `ContractStreamFrame` | schema / _type_ | default on-the-wire `data` / safe `error` / `end` envelope of a contract-first stream |
|
|
11815
12213
|
| `ContractStreamFraming` / `ContractStreamCompletion` | _types_ | opt-in item-vs-envelope framing and terminal-vs-stream-end completion policies |
|
|
11816
12214
|
| `StreamFinalLinePolicy` | _type_ | permissive or newline-required final NDJSON line policy |
|
|
@@ -11854,6 +12252,10 @@ The browser-and-server entrypoint. Re-exports everything from
|
|
|
11854
12252
|
| `RetainedTopics` | _type_ | the `createRetainedTopics` handle |
|
|
11855
12253
|
| `ParseSSEOptions` | _type_ | options for `parseSSE` |
|
|
11856
12254
|
| `ParseNDJSONOptions` | _type_ | options for `parseNDJSON` |
|
|
12255
|
+
| `BackoffPolicySchema` / `BackoffPolicy` | schema / _type_ | `minDelayMs`, `maxDelayMs` and a `0`–`1` jitter fraction; a ceiling below the floor is refused |
|
|
12256
|
+
| `Backoff` | _type_ | the backoff handle returned by `createBackoff` |
|
|
12257
|
+
| `ResumableIteratorConfig` | _type_ | caller-owned `open` / `advance` / `isTerminal`, retry policy, abort signal and `onAttempt` observer |
|
|
12258
|
+
| `ResumableAttempt` | _type_ | attempt number, the delay about to be waited and the error that caused it |
|
|
11857
12259
|
|
|
11858
12260
|
### Trace (client)
|
|
11859
12261
|
|
|
@@ -11965,6 +12367,51 @@ from the root `stitchkit`.
|
|
|
11965
12367
|
|
|
11966
12368
|
---
|
|
11967
12369
|
|
|
12370
|
+
## `stitchkit/primitives`
|
|
12371
|
+
|
|
12372
|
+
Browser-and-server-safe declarations for facts an application wants to define once. See the
|
|
12373
|
+
[primitives guide](../guide/primitives.md). Storage, transactions, data-adapter predicates,
|
|
12374
|
+
schedules, transports and file generation remain application-owned.
|
|
12375
|
+
|
|
12376
|
+
| Export | Kind | Summary |
|
|
12377
|
+
|--------|------|---------|
|
|
12378
|
+
| `defineLifecycle` | function | immutable finite-state transition declaration, role/payload validation, available-action projection and transition event |
|
|
12379
|
+
| `LifecycleState` / `LifecycleTransitionDefinition` / `LifecycleDefinition` | _types_ | branded state value and the declaration inferred from application strings |
|
|
12380
|
+
| `LifecycleTransitionInput` / `LifecycleTransitionResult` / `LifecycleTransitionSuccess` / `LifecycleTransitionFailure` | _types_ | typed execution input and distinct transition/state, role and payload outcomes |
|
|
12381
|
+
| `LifecycleTransitionEventSchema` / `LifecycleTransitionEvent` | schema / _type_ | canonical event returned for application-atomic persistence |
|
|
12382
|
+
| `defineOwnerScope` | function | resolve one owner from identity or require the explicit `acrossAllOwners` capability |
|
|
12383
|
+
| `OwnerScope` / `OwnerScopeDefinition` / `OwnerScopeResolution` | _types_ | branded adapter input and its resolved/refused outcomes |
|
|
12384
|
+
| `definePermissionMatrix` | function | exhaustive role × operation decisions with server check and client capability projection |
|
|
12385
|
+
| `PermissionGrantMatrix` / `PermissionCheckResult` | _types_ | compile-time complete matrix and unknown/allowed/denied runtime result |
|
|
12386
|
+
| `defineMoney` / `createMoneySchema` | functions | fixed-currency JSON-safe minor-unit value and Zod schema |
|
|
12387
|
+
| `addMoney` / `subtractMoney` / `multiplyMoney` / `shareMoney` / `splitMoney` | functions | exact same-currency arithmetic with explicit indivisible remainder |
|
|
12388
|
+
| `Money` / `MoneyShare` / `MoneySplit` | _types_ | currency-literal value and remainder-bearing operation results |
|
|
12389
|
+
| `defineUnitSystem` / `createQuantitySchema` / `addQuantity` | functions | exact decimal quantities and caller-declared finite conversions |
|
|
12390
|
+
| `Quantity` / `UnitConversion` / `QuantityProjection` | _types_ | unit-literal value, rational conversion and recorded/derived provenance |
|
|
12391
|
+
| `QuantityProjectionSchema` | schema | transport-safe recorded/derived quantity union |
|
|
12392
|
+
| `defineDeadlinePolicy` | function | elapsed- or calendar-day projection with explicit timezone, threshold, current time and caller category keys |
|
|
12393
|
+
| `DeadlineResultSchema` / `DeadlineResult` | schema / _type_ | due instant, remaining/overdue days and projected category |
|
|
12394
|
+
| `audit` | constant | constructors for explicit `record(changeSchema)` or `omit(reason)` endpoint metadata |
|
|
12395
|
+
| `assertAuditDeclared` | function | refuse a contract operation with no audit decision |
|
|
12396
|
+
| `createAuditRecord` | function | validate one declared change and return the canonical event value |
|
|
12397
|
+
| `AuditPolicy` / `AuditRecordPolicy` / `AuditOmitPolicy` / `CreateAuditRecordInput` | _types_ | audit declaration and record input contracts |
|
|
12398
|
+
| `AuditRecordSchema` / `AuditRecord` | schema / _type_ | domain-event-shaped audit record |
|
|
12399
|
+
| `createDomainEventSchema` | function | wrap a typed payload in the canonical event envelope |
|
|
12400
|
+
| `DomainEventSchema` / `DomainEvent` | schema / _type_ | generic event with stable id, time, subject and optional actor |
|
|
12401
|
+
| `DomainEventActorSchema` / `DomainEventActor` | schema / _type_ | structured actor identity and application role |
|
|
12402
|
+
| `DomainEventSubjectSchema` / `DomainEventSubject` | schema / _type_ | generic subject type/id pair |
|
|
12403
|
+
| `defineDomainEventDelivery` | function | plan routes and dispatch only application-outbox claims by committed event id |
|
|
12404
|
+
| `DomainEventDestinationSchema` / `DomainEventDestination` | schema / _type_ | transport-neutral destination identity |
|
|
12405
|
+
| `DomainEventDeliveryOutcomeSchema` / `DomainEventDeliveryOutcome` | schema / _type_ | delivered, retryable, terminal or unknown transport result |
|
|
12406
|
+
| `DomainEventDeliveryClaimSchema` / `DomainEventDeliveryClaim` | schema / _type_ | application-owned atomic outbox claim |
|
|
12407
|
+
| `DomainEventOutbox` / `DomainEventRoute` / `DomainEventTransport` | _types_ | host capabilities composed by process-local delivery |
|
|
12408
|
+
| `DomainEventDeliveryPlan` / `DomainEventDispatchResult` | _types_ | transaction input and bounded dispatch summary |
|
|
12409
|
+
| `defineExportOperation` / `createExportResultSchema` | functions | one typed contract operation returning a ready managed file or pending operation id |
|
|
12410
|
+
| `scanMoneyNumberRisks` / `scanOwnerFilterRisks` | functions | source-text migration diagnostics with caller-owned identifiers |
|
|
12411
|
+
| `SourceText` / `SourceRisk` | _types_ | migration scanner input and exact path/line evidence |
|
|
12412
|
+
|
|
12413
|
+
---
|
|
12414
|
+
|
|
11968
12415
|
## `stitchkit/server`
|
|
11969
12416
|
|
|
11970
12417
|
Server-only. Builds and runs the HTTP server, and carries the server primitives.
|
|
@@ -12143,6 +12590,7 @@ Also re-exports the error helpers from `stitchkit/contract`.
|
|
|
12143
12590
|
| `generateTraceId` | function | a fresh trace id |
|
|
12144
12591
|
| `resolveTraceId` | function | the default per-request trace-id resolver |
|
|
12145
12592
|
| `extractIp` | function | the caller IP from a request |
|
|
12593
|
+
| `isPublicIp` | function | whether an address belongs to the public internet; anything unparseable is not |
|
|
12146
12594
|
| `resolveSocketIp` | function | the caller IP for a Socket.IO handshake (proxy-aware) |
|
|
12147
12595
|
| `getClientInfo` | function | caller IP + user-agent |
|
|
12148
12596
|
| `EventBus` | _type_ | the `createEventBus` handle |
|
|
@@ -12213,7 +12661,9 @@ cutovers are covered by the executable
|
|
|
12213
12661
|
| Export | Kind | Summary |
|
|
12214
12662
|
|--------|------|---------|
|
|
12215
12663
|
| `createBoundedAdmission` | function | process-local no-queue global/per-key concurrency and rate leases, optionally composed with application admission |
|
|
12216
|
-
| `BoundedAdmissionPolicySchema` / `BoundedAdmissionPolicy` | schema / _type_ | finite global budget and optional finite per-key budget with `maxKeys
|
|
12664
|
+
| `BoundedAdmissionPolicySchema` / `BoundedAdmissionPolicy` | schema / _type_ | finite global budget and optional finite per-key budget with `maxKeys`, declared either as one flat ceiling or as a resolver — never both |
|
|
12665
|
+
| `BoundedAdmissionPerKeyLimitsSchema` / `BoundedAdmissionPerKeyLimits` | schema / _type_ | one key's resolved ceiling: `maxConcurrent` and optional `rate` |
|
|
12666
|
+
| `BoundedAdmissionPerKeyLimitResolver` | _type_ | `(key) => limits`, resolved on a key's first admission and cached until the key is evicted |
|
|
12217
12667
|
| `BoundedRateBudgetSchema` / `BoundedRateBudget` | schema / _type_ | `{ limit, intervalMs }` monotonic sliding-window budget |
|
|
12218
12668
|
| `BoundedAdmissionStateSchema` / `BoundedAdmissionState` | schema / _type_ | `accepting \| draining \| closed` |
|
|
12219
12669
|
| `BoundedAdmissionRefusalReasonSchema` / `BoundedAdmissionRefusalReason` | schema / _type_ | exact local/upstream refusal vocabulary |
|
|
@@ -12240,6 +12690,8 @@ cutovers are covered by the executable
|
|
|
12240
12690
|
| `createCreditWindow` | function | finite byte-credit lease window with exact once-only replenishment |
|
|
12241
12691
|
| `CreditWindow` / `CreditWindowSnapshot` / `CreditWindowSnapshotSchema` | _type_ / schema | byte-credit handle and absolute accounting record |
|
|
12242
12692
|
| `CreditAcquireResult` / `CreditLease` | _type_ | reasoned refusal or idempotently releasable byte-credit lease |
|
|
12693
|
+
| `CreditAcquireWaitOptions` | _type_ | `signal` / `timeoutMs` for the waiting `acquire` overload; absent budget waits until credit, close or abort |
|
|
12694
|
+
| `CreditWaitResult` / `CreditWaitRefusalReason` | _type_ | waiting-acquire outcome; `insufficient-credit` is absent by construction, `timed-out` and `aborted` replace it |
|
|
12243
12695
|
|
|
12244
12696
|
### Bounded diagnostic journal
|
|
12245
12697
|
|
|
@@ -12248,6 +12700,7 @@ cutovers are covered by the executable
|
|
|
12248
12700
|
| `createDiagnosticJournal` | function | create one schema-owned FIFO JSONL writer with bounded retained memory, exclusive local path ownership and finite rotation |
|
|
12249
12701
|
| `DiagnosticJournalConfig` / `DiagnosticJournal` | _type_ | owner schema/path/limits/failure observer and the synchronous `submit`, bounded-wait `flush`/`close`, status handle |
|
|
12250
12702
|
| `DiagnosticJournalLimitsSchema` / `DiagnosticJournalLimits` | schema / _type_ | positive event, pending-item, pending-byte, file-byte and retained-file limits |
|
|
12703
|
+
| `DiagnosticJournalLockPolicySchema` / `DiagnosticJournalLockPolicy` | schema / _type_ | `refuse` (default) or `reclaim-stale`, which reclaims only a lock whose recorded owner is provably gone |
|
|
12251
12704
|
| `DiagnosticJournalSubmitResultSchema` / `DiagnosticJournalSubmitResult` | schema / _type_ | accepted epoch/sequence or explicit invalid, oversized, capacity, closed or failed refusal |
|
|
12252
12705
|
| `DiagnosticJournalStatusSchema` / `DiagnosticJournalStatus` | schema / _type_ | state, limits, exact admission/write/failure counters, pending ownership, rotations, partial tails and last safe sequences |
|
|
12253
12706
|
| `DiagnosticJournalFrameSchema` / `DiagnosticJournalFrame` | schema / _type_ | version-1 JSONL frame carrying process epoch, contiguous accepted sequence and schema-validated JSON event |
|
|
@@ -12397,6 +12850,8 @@ Server-only optional application runtime. See the
|
|
|
12397
12850
|
| `AgentConversationMessagePageSchema` / `AgentConversationMessagePage` | schema / _type_ | cursor-paged durable message history |
|
|
12398
12851
|
| `composeAgentPrompt` | function | ordered prompt contributions and provenance-aware signed context budget; irreducible reservation deficits are `oversized`, not compactable history |
|
|
12399
12852
|
| `structuredCompaction` | function | summarize a provider-valid snapshot range and replace it through CAS |
|
|
12853
|
+
| `selectCompactableHistory` | function | which oldest whole complete turns may be summarised away — the half of compaction that needs no store (→ ADR 0142) |
|
|
12854
|
+
| `SelectCompactableHistoryOptions` / `CompactableHistory` | _type_ | message list, retained-turn count and evidence policy in; `leadingSummary`, `compactable` and `retained` out |
|
|
12400
12855
|
| `createAgentSessionCoordinator` | function | strict process-local queue/interrupt/supersede lifecycle |
|
|
12401
12856
|
| `AgentRuntimeStopPolicy` | _type_ | named custom AI SDK stop condition persisted and published on policy stop |
|
|
12402
12857
|
| `AgentRuntimePrepareStep` | _type_ | per-run controlled step callback with typed domain context and managed run signal/fence |
|
|
@@ -12425,6 +12880,29 @@ transport adapters validate the same records. Runtime composition types are `Age
|
|
|
12425
12880
|
`AgentSessionCoordinator`, `AgentCompactionContext`, `AgentCompactionResult` and
|
|
12426
12881
|
`StructuredCompactionConfig`.
|
|
12427
12882
|
|
|
12883
|
+
A provider refusal is classified rather than phrased. `classifyProviderFailure` returns an
|
|
12884
|
+
`AgentProviderFailure` — an `AgentProviderFailureReason` (`insufficient-credits`, `rate-limited`,
|
|
12885
|
+
`model-unavailable`, `context-overflow`, `timeout`, `cancelled`, `unknown`), the provider's `status`
|
|
12886
|
+
when it supplied one, whether the same request is `retryable` unchanged, and the `evidence` the
|
|
12887
|
+
answer rests on: `status` is the provider stating its own answer, `message` is us reading its prose,
|
|
12888
|
+
and `none` is an honest refusal to guess. The sentence a user reads stays with the application —
|
|
12889
|
+
its tone and its decision about what to admit are not the core's to make. `isToolResultFailure`
|
|
12890
|
+
recognises a failure carried inside a *successful* tool result, in both the bare and the
|
|
12891
|
+
`{ value: … }` envelope. Both are plain functions and need no runtime. → ADR 0141
|
|
12892
|
+
|
|
12893
|
+
`normalizeOpenRouterUsage` is the same normalisation `openRouterProvider`
|
|
12894
|
+
applies, exported so an application calling the SDK directly gets provenance-correct numbers
|
|
12895
|
+
without adopting the runtime.
|
|
12896
|
+
|
|
12897
|
+
`AgentContextUsage` reaches every step through `AgentRuntimeRunContext.contextUsage`: how full the
|
|
12898
|
+
model's context is, as `usedTokens` (an `AgentUsageValue`, so it carries the provenance that says
|
|
12899
|
+
where the number came from) beside the model's declared `contextWindow`. It is the **last completed
|
|
12900
|
+
step's prompt size**, not the run's cumulative input tokens — cumulative counts every step's prompt
|
|
12901
|
+
again and is a multiple of the real fill. Before the first step lands there is no provider-reported
|
|
12902
|
+
number and the provenance is `unavailable`, which is a different fact from zero. No fraction is
|
|
12903
|
+
exposed: dividing is one line where it is rendered, and the output reserve belongs to the
|
|
12904
|
+
consumer's prompt budget rather than to this layer.
|
|
12905
|
+
|
|
12428
12906
|
Canonical protocol exports are `AgentProtocol`, `AgentProtocolConfig`, `AgentTerminalAcceptance`,
|
|
12429
12907
|
`AgentTerminalAcceptanceInput`, `hasAgentTerminalOutput`, `AgentRecordIdSchema`, `AgentRecordVersionSchema`,
|
|
12430
12908
|
`AgentTimestampSchema`, `AgentJsonObjectSchema`, `AgentProviderEnvelopeSchema`,
|
|
@@ -12566,12 +13044,14 @@ explicit policy; use the Bun or Node SQLite leaf for durable reopen.
|
|
|
12566
13044
|
## `stitchkit/agent-runtime/coding-tools`
|
|
12567
13045
|
|
|
12568
13046
|
Server-only evolving, peer-free direct runtime tools. `createAgentCodingTools(config)` returns
|
|
12569
|
-
`read_file`, `write_file`, `
|
|
13047
|
+
`read_file`, `write_file`, `edit_file`, `list_directory`, `glob`, `search_files`, optional
|
|
13048
|
+
`run_command` and, when an
|
|
12570
13049
|
artifact store is supplied, `read_output`.
|
|
12571
13050
|
|
|
12572
13051
|
| Export | Kind | Summary |
|
|
12573
13052
|
|--------|------|---------|
|
|
12574
|
-
| `createAgentCodingTools` | function | construct direct host-authorized bounded file, search,
|
|
13053
|
+
| `createAgentCodingTools` | function | construct direct host-authorized bounded file, listing, glob, search, exact-snippet edit, shell and artifact runtime-tool definitions; every ordinary refusal is a typed code with an instructive `hint`, and filesystem operations use Linux `/proc/self/fd` or the packaged macOS Node-API backend and otherwise fail closed |
|
|
13054
|
+
| `AGENT_CODING_TOOL_NAMES` | const | the mounted tool names — `read_file`, `write_file`, `edit_file`, `list_directory`, `glob`, `search_files`, `run_command`, `read_output` |
|
|
12575
13055
|
| `AgentCodingToolDefinition` | _type_ | peer-free structural direct-tool shape accepted by the canonical runtime-tool surface |
|
|
12576
13056
|
| `AgentCodingToolConfig` | _type_ | absolute root, required authorization callback, finite executable alias map, exact child environment and optional limits |
|
|
12577
13057
|
| `AgentCodingToolAuthorizationSchema` / `AgentCodingToolAuthorization` | schema / _type_ | discriminated read/write/search/patch/shell/artifact decision presented to host policy before effect |
|
|
@@ -13094,6 +13574,26 @@ available from `stitchkit/contract`.
|
|
|
13094
13574
|
|
|
13095
13575
|
---
|
|
13096
13576
|
|
|
13577
|
+
## `stitchkit/telegram`
|
|
13578
|
+
|
|
13579
|
+
Peer-free server-only Telegram platform primitives. Importing this resolves no
|
|
13580
|
+
bot library; `stitchkit/application/grammy` remains the lifecycle adapter for an
|
|
13581
|
+
injected grammY bot. → ADR 0143
|
|
13582
|
+
|
|
13583
|
+
| Export | Kind | Summary |
|
|
13584
|
+
|--------|------|---------|
|
|
13585
|
+
| `verifyTelegramInitData` | function | verify a Mini App `initData` signature against the bot token in constant time, before reading anything out of it |
|
|
13586
|
+
| `VerifyTelegramInitDataOptions` | _type_ | raw `initData`, bot token, optional `maxAgeSeconds` bound and injected clock |
|
|
13587
|
+
| `TelegramInitDataVerification` | _type_ | `{ valid: true, data }` or a refusal carrying its reason |
|
|
13588
|
+
| `TelegramInitData` | _type_ | verified `user`/`receiver`, `authDate`, `ageSeconds`, `queryId`, `startParam`, `chatType`, `chatInstance` and every signed pair in `raw` |
|
|
13589
|
+
| `TelegramInitDataUser` | _type_ | camelCase user record inferred from Telegram's signed `user` payload |
|
|
13590
|
+
| `TelegramInitDataRefusal` | _type_ | `missing-hash` / `signature-mismatch` / `malformed` / `expired` — an expired string is not a forged one |
|
|
13591
|
+
| `classifyTelegramSendFailure` | function | name a refused Bot API send and separate "retry this send" from "stop addressing this recipient" |
|
|
13592
|
+
| `TelegramSendFailure` | _type_ | reason, `status`, Telegram-stated `retryAfterSeconds`, `retryable`, `recipientUnreachable` and which evidence produced the answer |
|
|
13593
|
+
| `TelegramSendFailureReason` | _type_ | `blocked-by-user` / `user-deactivated` / `chat-not-found` / `not-started` / `rate-limited` / `message-invalid` / `server-error` / `unknown` |
|
|
13594
|
+
|
|
13595
|
+
---
|
|
13596
|
+
|
|
13097
13597
|
## `stitchkit/declaration`
|
|
13098
13598
|
|
|
13099
13599
|
Zod-only, dependency-free. The **project declaration**: the single
|