stitchkit 0.113.2 → 0.114.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/CHANGELOG.md +20 -0
- package/dist/contract/errors.d.ts +1 -0
- package/dist/contract/errors.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/browser.js +2 -2
- package/dist/entrypoints/agent-runtime/coding-tools.js +4 -4
- package/dist/entrypoints/agent-runtime/harness.js +5 -5
- package/dist/entrypoints/agent-runtime/realtime.js +2 -2
- package/dist/entrypoints/agent-runtime/sandbox.js +4 -4
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +6 -6
- package/dist/entrypoints/agent-runtime/sqlite/node.js +6 -6
- package/dist/entrypoints/agent-runtime/testing.js +6 -6
- package/dist/entrypoints/agent-runtime.js +11 -11
- package/dist/entrypoints/application/grammy.js +1 -1
- package/dist/entrypoints/application.js +2 -2
- package/dist/entrypoints/cli.js +8 -8
- package/dist/entrypoints/contract.js +2 -2
- package/dist/entrypoints/files.js +1 -1
- package/dist/entrypoints/index.js +5 -5
- package/dist/entrypoints/node.js +7 -7
- package/dist/entrypoints/observability.js +1 -1
- package/dist/entrypoints/realtime.js +3 -3
- package/dist/entrypoints/remote.js +1 -1
- package/dist/entrypoints/server.js +8 -8
- package/dist/entrypoints/telegram/screens.js +1 -1
- package/dist/entrypoints/telegram.d.ts +1 -0
- package/dist/entrypoints/telegram.d.ts.map +1 -1
- package/dist/entrypoints/telegram.js +241 -1
- package/dist/entrypoints/testing.js +3 -3
- package/dist/entrypoints/tools/connections.js +5 -5
- package/dist/entrypoints/tools/invoker.js +5 -5
- package/dist/entrypoints/tools/mcp.js +7 -7
- package/dist/entrypoints/tools.js +13 -13
- package/dist/{index-cn7xenet.js → index-095ya5hm.js} +5 -5
- package/dist/{index-6ez1r4j2.js → index-1csp1hwm.js} +4 -4
- package/dist/{index-sps9s3aj.js → index-2bqf0a74.js} +1 -1
- package/dist/{index-grn4brx1.js → index-3za04re9.js} +1 -1
- package/dist/{index-09dyy94r.js → index-523tq7y4.js} +1 -1
- package/dist/{index-8swt2h9y.js → index-7fc0c2np.js} +1 -1
- package/dist/{index-2s7wv547.js → index-86nbfysb.js} +3 -3
- package/dist/{index-5gmrx6sc.js → index-98hv3sba.js} +1 -1
- package/dist/{index-4e36ts8b.js → index-9dyd8xzf.js} +1 -1
- package/dist/{index-zbs0g0v2.js → index-aykhzcnf.js} +1 -1
- package/dist/{index-0pfk3c1p.js → index-bjcjqj46.js} +1 -1
- package/dist/{index-vgtzdykw.js → index-cqmqyjax.js} +1 -1
- package/dist/{index-bv51s0f4.js → index-ega3yz4c.js} +1 -1
- package/dist/{index-awbed0mk.js → index-fy4av0hq.js} +1 -1
- package/dist/{index-xvj9h8yh.js → index-hs35ss3p.js} +11 -3
- package/dist/{index-0gbn42hr.js → index-htxh46ej.js} +3 -3
- package/dist/{index-shg5xc9t.js → index-jk29rwkr.js} +1 -1
- package/dist/{index-e40rzw1m.js → index-k42ckyzx.js} +1 -1
- package/dist/{index-xtc8k5n9.js → index-k7z3j3hr.js} +47 -16
- package/dist/{index-pd578538.js → index-qcn84byh.js} +1 -0
- package/dist/{index-vf9c59t3.js → index-rhzkndr5.js} +2 -2
- package/dist/{index-z8fnfj42.js → index-tpwbct8j.js} +1 -1
- package/dist/{index-7ysby53h.js → index-v1tswj0z.js} +1 -1
- package/dist/{index-a31p9ekx.js → index-v6vb5qx8.js} +4 -4
- package/dist/{index-5zxe0f3h.js → index-vtann8bz.js} +3 -3
- package/dist/{index-kvga921h.js → index-vwhrnp67.js} +4 -4
- package/dist/{index-ptjx84pr.js → index-zktz242w.js} +2 -2
- package/dist/telegram/outbound-budget.d.ts +99 -0
- package/dist/telegram/outbound-budget.d.ts.map +1 -0
- package/dist/telegram/send-failure.d.ts +6 -1
- package/dist/telegram/send-failure.d.ts.map +1 -1
- package/dist/tools/cli/command.d.ts +2 -1
- package/dist/tools/cli/command.d.ts.map +1 -1
- package/dist/tools/cli/format.d.ts +5 -1
- package/dist/tools/cli/format.d.ts.map +1 -1
- package/dist/tools/cli/run-native.d.ts.map +1 -1
- package/llms/cli.2.txt +281 -0
- package/llms/cli.txt +18 -285
- package/llms/server.4.txt +6 -1
- package/llms/stitchkit.txt +4 -4
- package/llms/telegram.txt +64 -2
- package/llms/{upgrading-0.103.13-0.113.0.txt → upgrading-0.104.0-0.114.0.txt} +45 -84
- package/llms/upgrading-0.37.0-0.44.0.txt +444 -0
- package/llms/{upgrading-0.44.0-0.60.0.txt → upgrading-0.44.0-0.61.0.txt} +140 -271
- package/llms/{upgrading-0.61.0-0.74.0.txt → upgrading-0.62.0-0.78.0.txt} +137 -140
- package/llms/{upgrading-0.75.0-0.103.0.txt → upgrading-0.79.0-0.103.13.txt} +84 -137
- package/llms/upgrading.txt +5 -5
- package/llms-full.txt +134 -11
- package/llms.txt +9 -9
- package/package.json +1 -1
- package/llms/upgrading-0.37.0.txt +0 -176
package/llms-full.txt
CHANGED
|
@@ -67,7 +67,7 @@ own, recorded as an ADR.
|
|
|
67
67
|
| `stitchkit/process/owner-loss` | bundled server entry (Bun, POSIX) | evolving | narrow bootstrap that keeps the process runner lazy while carrying its owner-loss guard in a single-file bundle |
|
|
68
68
|
| `stitchkit/files/packaging` | build time (Bun or Node) | evolving | installed native asset graph, integrity, Bun packaging plugin and the artifact loader check; no runtime install policy |
|
|
69
69
|
| `stitchkit/files` | server (Bun or Node) | stable | peer-free managed local-file boundary |
|
|
70
|
-
| `stitchkit/telegram` | server (Bun or Node) | evolving | peer-free Telegram platform primitives — Mini App `initData` verification, send-failure classification, resumable broadcasts, the operator channel with dedupe, a Bot API transport that separates a request that never left from an unknown outcome, local Bot API files, webhook ownership and durable webhook update intake |
|
|
70
|
+
| `stitchkit/telegram` | server (Bun or Node) | evolving | peer-free Telegram platform primitives — Mini App `initData` verification, send-failure classification, one outbound budget per bot token with weighted albums and shared 429 pauses, resumable broadcasts, the operator channel with dedupe, a Bot API transport that separates a request that never left from an unknown outcome, local Bot API files, webhook ownership and durable webhook update intake |
|
|
71
71
|
| `stitchkit/telegram/html` | browser and server | evolving | Telegram's HTML as a tree — clean any markup to what Telegram accepts, cut long text into valid parts by what the reader sees, check markup before it is sent |
|
|
72
72
|
| `stitchkit/telegram/screens` | server (Bun or Node) | evolving | a bot's menus as declared screens over grammY — typed paths, actions and input, message reconciliation, state in any `StorageAdapter`, a test chat |
|
|
73
73
|
| `stitchkit/tracking` | browser **and** server | evolving | visitor-tracking mechanics — `createTrackingClient`, the tab-shared outbox, the page-leave beacon, attribution, the contract factory; no event vocabulary, no React |
|
|
@@ -77,12 +77,12 @@ own, recorded as an ADR.
|
|
|
77
77
|
| `stitchkit/geo` | server (Bun or Node) | evolving | managed GeoIP reader generations, last-known-good reload and the optional MaxMind adapter |
|
|
78
78
|
| `stitchkit/oauth` | browser **and** server | evolving | provider-neutral Authorization Code + PKCE request and one-shot callback transaction mechanics |
|
|
79
79
|
| `stitchkit/google` | server (Bun or Node) | evolving | optional Google code exchange and verified OIDC identity adapter |
|
|
80
|
-
| `stitchkit/observability` | server | stable<br>_redefined in 2 of the
|
|
80
|
+
| `stitchkit/observability` | server | stable<br>_redefined in 2 of the 59 minors since 0.56.2, most recently 0.92.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
|
|
81
81
|
| `stitchkit/testing` | tests on Bun or Node | stable | in-process generated clients over a real Fetch handler, the managed-resource conformance kit and manual time for schedules and retries |
|
|
82
82
|
| `stitchkit/declaration` | browser + build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
|
|
83
83
|
| `stitchkit/react` | browser + server rendering | stable | `createCursorQuery`, `createCacheBridge`, QueryClient and `ApiError` retry policy |
|
|
84
84
|
| `stitchkit/react/keyboard` | browser | evolving | which part of a screen gets a key — ordered layers, one Escape per level, list zones with real focus; see [keyboard guide](keyboard.md) |
|
|
85
|
-
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 24 of the
|
|
85
|
+
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 24 of the 59 minors since 0.56.2, most recently 0.113.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
|
|
86
86
|
| `stitchkit/agent-runtime/sandbox` | server | evolving | optional Linux Bubblewrap sessions, durable workspaces and a host HTTP credential gateway; see [sandbox guide](sandbox.md) |
|
|
87
87
|
| `stitchkit/agent-runtime/testing` | tests on Bun or Node | evolving | credential-free replay, scripted provider faults, deterministic race controls and the agent-store conformance kit |
|
|
88
88
|
| `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
|
|
@@ -94,7 +94,7 @@ own, recorded as an ADR.
|
|
|
94
94
|
| `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
|
|
95
95
|
| `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
|
|
96
96
|
| `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
|
|
97
|
-
| `stitchkit/application` | browser + server | evolving<br>_redefined in 14 of the
|
|
97
|
+
| `stitchkit/application` | browser + server | evolving<br>_redefined in 14 of the 59 minors since 0.56.2, most recently 0.110.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
|
|
98
98
|
| `stitchkit/application/grammy` | server | evolving | a grammY bot as application resources — configuration, then polling with updates admitted by batch — and the webhook adapter |
|
|
99
99
|
| `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
|
|
100
100
|
| `stitchkit/application/schemas` | browser + server | evolving | the application's snapshot, health and shutdown schemas alone, without the kernel |
|
|
@@ -10012,9 +10012,11 @@ const doctor = defineCliCommand({
|
|
|
10012
10012
|
it the canonical JSON output is unchanged. `exitCode` classifies a successfully
|
|
10013
10013
|
validated result and must return an integer in `0..255`; failed `ToolResult`
|
|
10014
10014
|
envelopes and the application-wide `exitCodes` mapping remain authoritative for
|
|
10015
|
-
failures. A throwing
|
|
10016
|
-
|
|
10017
|
-
|
|
10015
|
+
failures. A throwing or invalid exit-status callback becomes a normalized
|
|
10016
|
+
`INTERNAL_SERVER_ERROR`. A throwing or non-string `present` preserves the validated
|
|
10017
|
+
result on stdout and reports `CLI_PRESENTATION_FAILED` separately, as described
|
|
10018
|
+
under [Aggregate views](#aggregate-views). Void native commands cannot declare
|
|
10019
|
+
either callback.
|
|
10018
10020
|
|
|
10019
10021
|
`--version`, a selected native command and its command help run before
|
|
10020
10022
|
`resolveAuth`, services, context or runtime-tool factories. Top-level help is
|
|
@@ -10229,6 +10231,7 @@ newline-terminated JSON record on its respective stream; progress and CLI usage
|
|
|
10229
10231
|
diagnostics remain ordinary stderr text. This keeps stdout pipeable and
|
|
10230
10232
|
`2>/dev/null` clean. The process exit code carries the error class (`0` ok,
|
|
10231
10233
|
`VALIDATION_ERROR → 1`, `UNAUTHORIZED → 2`, `FORBIDDEN → 3`, `NOT_FOUND → 4`,
|
|
10234
|
+
`CLI_PRESENTATION_FAILED → 8`,
|
|
10232
10235
|
…) — override per app with `exitCodes`.
|
|
10233
10236
|
|
|
10234
10237
|
### A narrower question than "all of them"
|
|
@@ -10450,7 +10453,7 @@ would answer a question nobody asked.
|
|
|
10450
10453
|
|
|
10451
10454
|
Three rules worth knowing before you rely on them:
|
|
10452
10455
|
|
|
10453
|
-
- **A field the result does not carry is
|
|
10456
|
+
- **A field the result does not carry is a presentation error.** A group of zero
|
|
10454
10457
|
over a misspelled field is indistinguishable from a true empty answer, and the
|
|
10455
10458
|
caller reads it as data. The message names the fields that *are* there.
|
|
10456
10459
|
- **An aggregate needs a collection** — the result itself when it is an array,
|
|
@@ -10464,6 +10467,17 @@ Three rules worth knowing before you rely on them:
|
|
|
10464
10467
|
A failed call still reports its own error and exit code. An aggregate over an
|
|
10465
10468
|
error is not an answer to the question that was asked.
|
|
10466
10469
|
|
|
10470
|
+
If the command succeeds but its requested view cannot be built, the CLI writes
|
|
10471
|
+
the complete original result to stdout, using the normal JSON format (`--json`
|
|
10472
|
+
still selects compact output). It writes a separate structured
|
|
10473
|
+
`CLI_PRESENTATION_FAILED` diagnostic to stderr and exits with `8`, configurable
|
|
10474
|
+
through `exitCodes`. Its `details.operationSucceeded: true` and `retryable: false`
|
|
10475
|
+
distinguish a presentation refusal from a failed operation; `details.cause`
|
|
10476
|
+
preserves the safe reason. Recover the answer from stdout instead of repeating
|
|
10477
|
+
the mutation. Domain retry hints are not appended to this diagnostic. CLI
|
|
10478
|
+
argument errors detected before execution still exit with `2`
|
|
10479
|
+
and have no successful result to preserve.
|
|
10480
|
+
|
|
10467
10481
|
## Named profiles
|
|
10468
10482
|
|
|
10469
10483
|
A CLI that talks to a deployed server needs an address and a credential per
|
|
@@ -12935,6 +12949,11 @@ and our payload is wrong, which is the case a list of substrings quietly counts
|
|
|
12935
12949
|
against the user. An unrecognised refusal leaves the recipient reachable: losing
|
|
12936
12950
|
a working subscriber forever costs more than one wasted send.
|
|
12937
12951
|
|
|
12952
|
+
`bot-to-bot-disabled` is permanent but deliberately not `recipientUnreachable`:
|
|
12953
|
+
Telegram returns it when either bot has not enabled Bot to Bot messaging, so the
|
|
12954
|
+
missing setting may be the sender's. Do not retry it, and do not close the
|
|
12955
|
+
recipient's row on it.
|
|
12956
|
+
|
|
12938
12957
|
`TELEGRAM_SEND_FAILURE_REASONS` lists every reason. A table keyed by
|
|
12939
12958
|
`TelegramSendFailureReason` — error codes, the text a person reads — fails to
|
|
12940
12959
|
compile when a release adds one, instead of falling through to a default:
|
|
@@ -13097,7 +13116,7 @@ core never models them (ADR 0002). But stitchkit itself emits a set of its own:
|
|
|
13097
13116
|
`FILE_INSPECTION_REJECTED`, `FILE_TOO_LARGE`, `FILE_EXISTS`,
|
|
13098
13117
|
`REALTIME_CONTRACT_VIOLATION`, `APPLICATION_NOT_ACCEPTING`, `NOT_IMPLEMENTED`,
|
|
13099
13118
|
`WAIT_TIMEOUT`,
|
|
13100
|
-
`WAIT_FAILED`, `CLI_COMMAND_UNAVAILABLE`, `DOWNLOAD_NOT_FOUND`, `VIEW_HTTP_ERROR`,
|
|
13119
|
+
`WAIT_FAILED`, `CLI_COMMAND_UNAVAILABLE`, `CLI_PRESENTATION_FAILED`, `DOWNLOAD_NOT_FOUND`, `VIEW_HTTP_ERROR`,
|
|
13101
13120
|
`CONNECTION_TIMEOUT`, `CONNECTION_RESPONSE_TOO_LARGE`,
|
|
13102
13121
|
`CONNECTION_REQUEST_FAILED`, `UPSTREAM_TOOL_ERROR`,
|
|
13103
13122
|
`OPERATION_NOT_SUCCEEDED`, `STREAM_ITEM_INVALID`, `STREAM_FRAME_TOO_LARGE`,
|
|
@@ -15514,6 +15533,67 @@ The error line contract, for whatever recognises a failure from the journal: a
|
|
|
15514
15533
|
line whose `level` is `50` or more is an error. There is no separate `fatal`;
|
|
15515
15534
|
an unrecoverable end is an `error` line followed by a non-zero exit.
|
|
15516
15535
|
|
|
15536
|
+
## One token, one outbound budget
|
|
15537
|
+
|
|
15538
|
+
Telegram counts a bot's bulk messages per token, not per campaign, handler or
|
|
15539
|
+
module. `telegramOutboundBudget` is that budget once: every alias of one token
|
|
15540
|
+
in the process gets the same object, another token gets another, and every send
|
|
15541
|
+
through it spends its weight. → [ADR 0274](../decisions/0274-a-telegram-token-has-one-outbound-budget.md).
|
|
15542
|
+
|
|
15543
|
+
```ts
|
|
15544
|
+
import { telegramOutboundBudget } from 'stitchkit/telegram'
|
|
15545
|
+
|
|
15546
|
+
const budget = telegramOutboundBudget({
|
|
15547
|
+
token: env.BOT_TOKEN,
|
|
15548
|
+
messagesPerSecond: 24,
|
|
15549
|
+
})
|
|
15550
|
+
|
|
15551
|
+
// The one transformer of the bot's client. No second limiter, no second
|
|
15552
|
+
// scheduler: campaigns, replies and every other send of this token share it.
|
|
15553
|
+
api.config.use((previous, method, payload, signal) =>
|
|
15554
|
+
budget.run(method, payload, signal, () => previous(method, payload, signal)),
|
|
15555
|
+
)
|
|
15556
|
+
```
|
|
15557
|
+
|
|
15558
|
+
- **The token is the identity, not the sender.** Two bot objects built from one
|
|
15559
|
+
token share the budget; two different tokens do not. The registry keeps a
|
|
15560
|
+
128-bit identity, never the credential, and `stats()` contains no token.
|
|
15561
|
+
- **A message is the unit.** `sendMediaGroup` and `sendPaidMedia` cost their
|
|
15562
|
+
media length, `copyMessages` and `forwardMessages` cost their message ids, and
|
|
15563
|
+
a follow-up call to action after an album costs one more. Reads and edits
|
|
15564
|
+
(`getMe`, `getFile`, `editMessage*`, `deleteMessage`, `sendChatAction`) do not
|
|
15565
|
+
spend the budget.
|
|
15566
|
+
- **The first send after idle is immediate; the rest are spaced.** This is a
|
|
15567
|
+
strict budget, not a bucket that saves a burst: at 24/s the next send is due
|
|
15568
|
+
one interval later. A 429 pauses the whole token; when it resumes, one send
|
|
15569
|
+
is released at the deadline and the queue continues one interval at a time,
|
|
15570
|
+
never as a stampede.
|
|
15571
|
+
- **It paces; it does not retry.** `run` calls the send once. A 429 pauses the
|
|
15572
|
+
token for Telegram's `retry_after` (or `retryAfterFallbackMs` when Telegram
|
|
15573
|
+
gave none) and rethrows; the caller's retry policy decides what happens next.
|
|
15574
|
+
A 429 from an edit or a read is still a fact about the token and pauses later
|
|
15575
|
+
sends too. A network failure is rethrown unchanged and stays `unknown`; a 5xx
|
|
15576
|
+
is rethrown unchanged and stays `server-error`. Neither is retried by the
|
|
15577
|
+
budget or pauses the token — repeating a send whose outcome is unknown is a
|
|
15578
|
+
decision, not a primitive's silent guess.
|
|
15579
|
+
- **A wait can be cancelled.** `run`/`acquire` take an `AbortSignal`; a
|
|
15580
|
+
cancelled waiter spends no slot and calls no provider. A granted send that is
|
|
15581
|
+
then aborted is not evidence that Telegram did not accept it — keep the
|
|
15582
|
+
outcome unknown rather than retrying it as a definite failure.
|
|
15583
|
+
- **Non-send retries wait without spending.** An edit or delete retry that got
|
|
15584
|
+
a 429 first records the pause with `budget.pauseAfter(error)` (the `run` path
|
|
15585
|
+
does this itself), then uses `await budget.waitUntilResumed(signal)`; it shares
|
|
15586
|
+
the token's pause but does not take a message slot.
|
|
15587
|
+
|
|
15588
|
+
`telegramBroadcastSender` and `telegramOperatorSender` still send through
|
|
15589
|
+
`callTelegramBotApi`; they are not a second budget. Their returned function does
|
|
15590
|
+
not expose the method and payload, so a product that uses one wraps the concrete
|
|
15591
|
+
`sendMessage`/`copyMessage` call in `budget.run` where it knows both, or passes
|
|
15592
|
+
its own sender. There is no generic wrapper around the opaque sender.
|
|
15593
|
+
`runTelegramBroadcast` keeps its per-run `ratePerSecond` and the operator
|
|
15594
|
+
channel keeps its per-chat `minIntervalMs`; those are caps of their own jobs,
|
|
15595
|
+
not another token quota. The token budget is the binding shared cap.
|
|
15596
|
+
|
|
15517
15597
|
## The operator channel
|
|
15518
15598
|
|
|
15519
15599
|
The chat where people read about new users, payments and failures is not the
|
|
@@ -16347,6 +16427,48 @@ analytics policy belong to the application.
|
|
|
16347
16427
|
|
|
16348
16428
|
# Upgrading stitchkit
|
|
16349
16429
|
|
|
16430
|
+
## Released migration: 0.114.0
|
|
16431
|
+
|
|
16432
|
+
**Who must act:** code with an exhaustive `switch` or `Record` over
|
|
16433
|
+
`TelegramSendFailureReason` or `TELEGRAM_SEND_FAILURE_REASONS`. Code that only
|
|
16434
|
+
reads `retryable` and `recipientUnreachable` needs no change.
|
|
16435
|
+
|
|
16436
|
+
`classifyTelegramSendFailure` now returns `reason: 'bot-to-bot-disabled'` for a
|
|
16437
|
+
`400 USER_BOT_TO_BOT_DISABLED` ([ADR 0274](../decisions/0274-a-telegram-token-has-one-outbound-budget.md)).
|
|
16438
|
+
It is permanent for that send, so it is not retried; it is **not**
|
|
16439
|
+
`recipientUnreachable`, because Telegram disables bot-to-bot messaging when
|
|
16440
|
+
either bot has not enabled its Bot to Bot setting, and the missing setting may
|
|
16441
|
+
be the sender's.
|
|
16442
|
+
|
|
16443
|
+
1. Add the reason to every exhaustive mapping:
|
|
16444
|
+
|
|
16445
|
+
```ts
|
|
16446
|
+
// before
|
|
16447
|
+
const code: Record<TelegramSendFailureReason, string> = { /* … */ unknown: 'E_UNKNOWN' }
|
|
16448
|
+
// after
|
|
16449
|
+
const code: Record<TelegramSendFailureReason, string> = {
|
|
16450
|
+
/* … */ 'bot-to-bot-disabled': 'E_BOT_TO_BOT', unknown: 'E_UNKNOWN',
|
|
16451
|
+
}
|
|
16452
|
+
```
|
|
16453
|
+
|
|
16454
|
+
Search pattern: `TelegramSendFailureReason`, `TELEGRAM_SEND_FAILURE_REASONS`
|
|
16455
|
+
and every `switch` over a send-failure reason.
|
|
16456
|
+
2. Type-check: the exhaustive table without the new member fails to compile.
|
|
16457
|
+
3. If the application wants one outbound budget per bot token, opt in at the
|
|
16458
|
+
one transformer that already owns its Bot API calls:
|
|
16459
|
+
|
|
16460
|
+
```ts
|
|
16461
|
+
import { telegramOutboundBudget } from 'stitchkit/telegram'
|
|
16462
|
+
|
|
16463
|
+
const budget = telegramOutboundBudget({ token: env.BOT_TOKEN })
|
|
16464
|
+
api.config.use((previous, method, payload, signal) =>
|
|
16465
|
+
budget.run(method, payload, signal, () => previous(method, payload, signal)),
|
|
16466
|
+
)
|
|
16467
|
+
```
|
|
16468
|
+
|
|
16469
|
+
Remove the old limiter rather than running it beside this one. See the
|
|
16470
|
+
[Telegram guide](telegram.md#one-token-one-outbound-budget).
|
|
16471
|
+
|
|
16350
16472
|
## Released migration: 0.113.0
|
|
16351
16473
|
|
|
16352
16474
|
**Who must act:** custom `AgentRuntimeStoreDriver` adapters and custom `AgentRuntimeStore` implementations of `seedConversationInput`. The built-in memory and SQLite stores already implement the contract.
|
|
@@ -23272,7 +23394,7 @@ available from `stitchkit/contract`.
|
|
|
23272
23394
|
Peer-free server-only Telegram platform primitives — the Bot API's own
|
|
23273
23395
|
protocols and the jobs every bot rewrote around them. Importing this resolves no
|
|
23274
23396
|
bot library; `stitchkit/application/grammy` remains the lifecycle adapter for an
|
|
23275
|
-
injected grammY bot. → ADR 0143, ADR 0201 — [guide](../guide/telegram.md)
|
|
23397
|
+
injected grammY bot. → ADR 0143, ADR 0201, ADR 0274 — [guide](../guide/telegram.md)
|
|
23276
23398
|
|
|
23277
23399
|
| Export | Kind | Summary |
|
|
23278
23400
|
|--------|------|---------|
|
|
@@ -23287,7 +23409,8 @@ injected grammY bot. → ADR 0143, ADR 0201 — [guide](../guide/telegram.md)
|
|
|
23287
23409
|
| `createTelegramBotTransport` / `TelegramBotTransportOptions` | function / _type_ | a `fetch` for the Bot API senders that connects before it writes, so a failure before the first byte is `TelegramNotDispatchedError`; connection attempt and budget, answer timeout and size, injectable resolver and socket factory — [guide](../guide/telegram.md#a-transport-that-knows-whether-a-request-left) |
|
|
23288
23410
|
| `TelegramFetch` / `TelegramBotTransportOpen` / `TelegramBotTransportResolve` / `TelegramBotTransportSocket` | _types_ | the `(url, init) => Promise<Response>` the senders take; the transport's socket factory, resolver and the structural socket it needs (a Node `net.Socket` or `tls.TLSSocket` fits) |
|
|
23289
23411
|
| `TelegramNotDispatchedError` / `TelegramNotDispatchedStage` | class / _type_ | a request that provably never left (`lookup`, `connect` or `request`), so repeating it cannot duplicate a message |
|
|
23290
|
-
| `TelegramSendFailureReason` / `TELEGRAM_SEND_FAILURE_REASONS` | _type_ / constant | `blocked-by-user` / `user-deactivated` / `chat-not-found` / `not-started` / `rate-limited` / `message-invalid` / `server-error` / `not-dispatched` / `unknown`, and the same as a list; a `Record<TelegramSendFailureReason, …>` over them fails to compile when a reason is added |
|
|
23412
|
+
| `TelegramSendFailureReason` / `TELEGRAM_SEND_FAILURE_REASONS` | _type_ / constant | `blocked-by-user` / `user-deactivated` / `chat-not-found` / `not-started` / `bot-to-bot-disabled` / `rate-limited` / `message-invalid` / `server-error` / `not-dispatched` / `unknown`, and the same as a list; a `Record<TelegramSendFailureReason, …>` over them fails to compile when a reason is added |
|
|
23413
|
+
| `telegramOutboundBudget` / `TelegramOutboundBudget` / `TelegramOutboundBudgetConfig` / `TelegramOutboundBudgetStats` | function / _type_ | one token-wide outbound budget: one object per token in the process, strict 24 messages/s by default, weighted albums and multi-message copies, `run(method, payload, signal, send)` as the transformer adapter, `pause`/`pauseAfter` for 429, `waitUntilResumed` for non-send retries and `stats`; it paces and never retries, and no public value carries the token |
|
|
23291
23414
|
| `runTelegramBroadcast` | function | a resumable broadcast by `name` under a state `directory`: audience and journal durably recorded, pacing at `ratePerSecond` (25), exact retry delays within the finite declared budget, injected classifier, uncertain send outcomes never replayed, `dryRun`, one fenced runner per name |
|
|
23292
23415
|
| `TelegramBroadcastConfig` / `TelegramBroadcastSend` / `TelegramBroadcastReport` / `TelegramBroadcastRunOutcome` / `TelegramBroadcastOutcome` / `TelegramBroadcastRecipient` | _type_ | `name`, `directory`, `recipients()`, `send({ recipient, attempt })`, `maxAttempts`, `signal`, `onProgress`; counts `delivered` / `unreachable` / `failed` / `uncertain` / `pending` and `finished` / `stopped` / `halted` / `dry-run` |
|
|
23293
23416
|
| `TelegramBroadcastFailureSchema` / `TelegramBroadcastFailure` | schema / _type_ | injected `classify` answers retry-after/transient/permanent/ambiguous; exact provider delay is bounded by `maxRetryDelayMs` without shortening, unknown outcome remains uncertain and is never replayed |
|
package/llms.txt
CHANGED
|
@@ -9,7 +9,7 @@ Build with stitchkit: define a contract once, then `implement` it and serve it (
|
|
|
9
9
|
Load the slice for each entrypoint your code imports — `import … from 'stitchkit/server'` → `llms/server.txt`; the root `stitchkit` import → `llms/stitchkit.txt`. A slice holds that entrypoint's API reference section and the guide pages whose home it is; every guide lives in exactly one slice, and a slice that needs another's guide names it under "Also read". Each file is at most 50.0 KB; a longer one continues in numbered parts, each naming the next at its top. Moving across versions: load `llms/upgrading.txt` and the range slices it lists between your version and the target. `llms-full.txt` inlines everything; it is far larger than a context window, so do not read it whole.
|
|
10
10
|
|
|
11
11
|
## Entrypoint slices
|
|
12
|
-
- **stitchkit**: [llms/stitchkit.txt](llms/stitchkit.txt) 47.
|
|
12
|
+
- **stitchkit**: [llms/stitchkit.txt](llms/stitchkit.txt) 47.6 KB → [llms/stitchkit.2.txt](llms/stitchkit.2.txt) 38.1 KB
|
|
13
13
|
- **stitchkit/live**: [llms/live.txt](llms/live.txt) 21.2 KB
|
|
14
14
|
- **stitchkit/react**: [llms/react.txt](llms/react.txt) 8.6 KB
|
|
15
15
|
- **stitchkit/react/keyboard**: [llms/react-keyboard.txt](llms/react-keyboard.txt) 9.2 KB
|
|
@@ -18,12 +18,12 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
|
|
|
18
18
|
- **stitchkit/tools/contract**: [llms/tools-contract.txt](llms/tools-contract.txt) 0.2 KB
|
|
19
19
|
- **stitchkit/tools/invoker**: [llms/tools-invoker.txt](llms/tools-invoker.txt) 0.2 KB
|
|
20
20
|
- **stitchkit/tools/connections**: [llms/tools-connections.txt](llms/tools-connections.txt) 3.9 KB
|
|
21
|
-
- **stitchkit/cli**: [llms/cli.txt](llms/cli.txt)
|
|
21
|
+
- **stitchkit/cli**: [llms/cli.txt](llms/cli.txt) 33.9 KB → [llms/cli.2.txt](llms/cli.2.txt) 36.4 KB
|
|
22
22
|
- **stitchkit/cli/publish**: [llms/cli-publish.txt](llms/cli-publish.txt) 1.5 KB
|
|
23
23
|
- **stitchkit/remote**: [llms/remote.txt](llms/remote.txt) 1.0 KB
|
|
24
24
|
- **stitchkit/contract**: [llms/contract.txt](llms/contract.txt) 31.9 KB
|
|
25
25
|
- **stitchkit/primitives**: [llms/primitives.txt](llms/primitives.txt) 11.7 KB
|
|
26
|
-
- **stitchkit/server**: [llms/server.txt](llms/server.txt) 44.2 KB → [llms/server.2.txt](llms/server.2.txt) 20.5 KB → [llms/server.3.txt](llms/server.3.txt) 45.6 KB → [llms/server.4.txt](llms/server.4.txt) 38.
|
|
26
|
+
- **stitchkit/server**: [llms/server.txt](llms/server.txt) 44.2 KB → [llms/server.2.txt](llms/server.2.txt) 20.5 KB → [llms/server.3.txt](llms/server.3.txt) 45.6 KB → [llms/server.4.txt](llms/server.4.txt) 38.6 KB → [llms/server.5.txt](llms/server.5.txt) 22.9 KB
|
|
27
27
|
- **stitchkit/observability**: [llms/observability.txt](llms/observability.txt) 46.9 KB
|
|
28
28
|
- **stitchkit/agent-runtime**: [llms/agent-runtime.txt](llms/agent-runtime.txt) 43.2 KB → [llms/agent-runtime.2.txt](llms/agent-runtime.2.txt) 45.9 KB → [llms/agent-runtime.3.txt](llms/agent-runtime.3.txt) 42.2 KB
|
|
29
29
|
- **stitchkit/agent-runtime/testing**: [llms/agent-runtime-testing.txt](llms/agent-runtime-testing.txt) 2.6 KB
|
|
@@ -42,7 +42,7 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
|
|
|
42
42
|
- **stitchkit/testing**: [llms/testing.txt](llms/testing.txt) 33.6 KB
|
|
43
43
|
- **stitchkit/agent-runtime/sandbox**: [llms/agent-runtime-sandbox.txt](llms/agent-runtime-sandbox.txt) 8.3 KB
|
|
44
44
|
- **stitchkit/files**: [llms/files.txt](llms/files.txt) 5.7 KB
|
|
45
|
-
- **stitchkit/telegram**: [llms/telegram.txt](llms/telegram.txt)
|
|
45
|
+
- **stitchkit/telegram**: [llms/telegram.txt](llms/telegram.txt) 40.6 KB
|
|
46
46
|
- **stitchkit/telegram/html**: [llms/telegram-html.txt](llms/telegram-html.txt) 2.7 KB
|
|
47
47
|
- **stitchkit/telegram/screens**: [llms/telegram-screens.txt](llms/telegram-screens.txt) 21.2 KB
|
|
48
48
|
- **stitchkit/tracking**: [llms/tracking.txt](llms/tracking.txt) 18.1 KB
|
|
@@ -64,11 +64,11 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
|
|
|
64
64
|
|
|
65
65
|
## Upgrading slices
|
|
66
66
|
- **Upgrading — how to move across versions**: [llms/upgrading.txt](llms/upgrading.txt) 12.7 KB
|
|
67
|
-
- **Upgrading 0.
|
|
68
|
-
- **Upgrading 0.
|
|
69
|
-
- **Upgrading 0.
|
|
70
|
-
- **Upgrading 0.44.0 → 0.
|
|
71
|
-
- **Upgrading 0.37.0 → 0.
|
|
67
|
+
- **Upgrading 0.104.0 → 0.114.0**: [llms/upgrading-0.104.0-0.114.0.txt](llms/upgrading-0.104.0-0.114.0.txt) 43.6 KB
|
|
68
|
+
- **Upgrading 0.79.0 → 0.103.13**: [llms/upgrading-0.79.0-0.103.13.txt](llms/upgrading-0.79.0-0.103.13.txt) 46.3 KB
|
|
69
|
+
- **Upgrading 0.62.0 → 0.78.0**: [llms/upgrading-0.62.0-0.78.0.txt](llms/upgrading-0.62.0-0.78.0.txt) 42.2 KB
|
|
70
|
+
- **Upgrading 0.44.0 → 0.61.0**: [llms/upgrading-0.44.0-0.61.0.txt](llms/upgrading-0.44.0-0.61.0.txt) 41.4 KB
|
|
71
|
+
- **Upgrading 0.37.0 → 0.44.0**: [llms/upgrading-0.37.0-0.44.0.txt](llms/upgrading-0.37.0-0.44.0.txt) 14.7 KB
|
|
72
72
|
|
|
73
73
|
## Guide (web)
|
|
74
74
|
- [Getting started](https://github.com/max-listov/stitchkit/blob/master/docs/guide/getting-started.md): install, entrypoints, and a first contract → server → client app
|
package/package.json
CHANGED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
# Upgrading 0.37.0 → 0.37.0 — stitchkit docs slice
|
|
2
|
-
|
|
3
|
-
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
|
-
> `llms.txt` in this package.
|
|
5
|
-
|
|
6
|
-
Contains: Guide: Upgrading, 0.37.0 → 0.37.0 (docs/guide/upgrading.md)
|
|
7
|
-
|
|
8
|
-
==============================================================================
|
|
9
|
-
# Guide: Upgrading, 0.37.0 → 0.37.0 (docs/guide/upgrading.md)
|
|
10
|
-
==============================================================================
|
|
11
|
-
|
|
12
|
-
## The 0.37 migration
|
|
13
|
-
|
|
14
|
-
Tool presentation is no longer an executable Zod parser. Replace the removed
|
|
15
|
-
flatten helpers with the JSON Schema compiler, and choose the explicit
|
|
16
|
-
`MountableTool` surface when using the advanced collection API:
|
|
17
|
-
|
|
18
|
-
```ts
|
|
19
|
-
// before
|
|
20
|
-
const flat = flattenUnionsDeep(zodSchema)
|
|
21
|
-
mountable.schema
|
|
22
|
-
|
|
23
|
-
// after
|
|
24
|
-
const flat = flattenToolJsonSchema(
|
|
25
|
-
z.toJSONSchema(zodSchema, { target: 'draft-07', io: 'input' }),
|
|
26
|
-
)
|
|
27
|
-
mountable.presentationSchema // model/MCP/manifest JSON Schema
|
|
28
|
-
mountable.argumentSchema // executable CLI argument adapter only
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
Contract and native handlers keep their original Zod schemas; MCP and agent SDK
|
|
32
|
-
adapters now forward raw arguments so defaults, coercions, refinements and
|
|
33
|
-
transforms execute exactly once inside Stitchkit. There are no compatibility
|
|
34
|
-
exports for `flattenDiscriminatedUnion`, `flattenUnionsDeep` or
|
|
35
|
-
`MountableTool.schema`. → ADR 0050
|
|
36
|
-
|
|
37
|
-
Tool-call hooks now take one options object. Migrate all three callbacks; there
|
|
38
|
-
are no positional overloads:
|
|
39
|
-
|
|
40
|
-
```ts
|
|
41
|
-
// before
|
|
42
|
-
beforeToolCall: (toolName, args, context, endpoint) => {}
|
|
43
|
-
afterToolCall: (toolName, args, result, durationMs, context, endpoint, error) => {}
|
|
44
|
-
onToolError: (toolName, error, context, endpoint) => {}
|
|
45
|
-
|
|
46
|
-
// after
|
|
47
|
-
beforeToolCall: ({ toolName, args, context, endpoint }) => {}
|
|
48
|
-
afterToolCall: ({ toolName, args, result, durationMs, context, endpoint, error }) => {}
|
|
49
|
-
onToolError: ({ toolName, error, context, endpoint }) => {}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### MCP schema validation
|
|
53
|
-
|
|
54
|
-
The standalone validator now takes one object and live MCP configs carry the
|
|
55
|
-
same rules under `schemaValidation`. Migrate every positional call and every
|
|
56
|
-
`onIncompatibleSchema` field; there is no old-shape overload:
|
|
57
|
-
|
|
58
|
-
```ts
|
|
59
|
-
// before
|
|
60
|
-
validateMcpSchemas(services, 'throw', logger, { requireTypedProperties: true })
|
|
61
|
-
createMcpHandler({ services, onIncompatibleSchema: 'throw' })
|
|
62
|
-
|
|
63
|
-
// after
|
|
64
|
-
validateMcpSchemas({ services, policy: 'throw', logger, requireTypedProperties: true })
|
|
65
|
-
createMcpHandler({ services, schemaValidation: { policy: 'throw' } })
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Put `extend` and `flattenUnionInput` beside `services`, not inside
|
|
69
|
-
`schemaValidation`. The handler applies the profile to the exact prepared schema
|
|
70
|
-
it advertises. Add `requirePortableFormats: true` when every custom JSON Schema
|
|
71
|
-
format must be rejected before a client sees it.
|
|
72
|
-
|
|
73
|
-
Native MCP registration also changed shape in 0.37. Move protected tools to the
|
|
74
|
-
framework registrar; keep an SDK-raw tool only by naming the opt-out:
|
|
75
|
-
|
|
76
|
-
```ts
|
|
77
|
-
// before
|
|
78
|
-
nativeTools: (server, auth) => server.registerTool(name, config, handler)
|
|
79
|
-
|
|
80
|
-
// after — lifecycle, hooks and schema policy apply
|
|
81
|
-
nativeTools: ({ registerTool }, auth) => registerTool({
|
|
82
|
-
name, description, identity, input, output, handler,
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
// after — intentionally raw
|
|
86
|
-
nativeTools: ({ rawServer }, auth) => rawServer.registerTool(name, config, handler)
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
If a tool hook annotated `endpoint` as `MethodDef`, remove that annotation or
|
|
90
|
-
use `OperationIdentity`: native operations have service/action/scope/method but
|
|
91
|
-
no HTTP path.
|
|
92
|
-
|
|
93
|
-
### Node-facing server types
|
|
94
|
-
|
|
95
|
-
`stitchkit/server` remains Bun-concrete: an explicitly annotated `RawRoute`
|
|
96
|
-
still receives `BunServer`. `stitchkit/node` no longer drags Bun declarations
|
|
97
|
-
into a Node project. Its raw routes default the host server to `unknown`, and
|
|
98
|
-
its Socket.IO handle exposes only Node capabilities:
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
// before — Node entry still leaked Bun-only fields and ambient types
|
|
102
|
-
const route: RawRoute = { handler: (_req, ctx) => ctx.server?.upgrade(...) }
|
|
103
|
-
const socket = await createSocketIOServer(config)
|
|
104
|
-
socket.websocket
|
|
105
|
-
|
|
106
|
-
// after — name a custom embedding host only when one exists
|
|
107
|
-
const route: RawRoute<MyHostServer> = {
|
|
108
|
-
handler: (_req, ctx) => useHost(ctx.server),
|
|
109
|
-
}
|
|
110
|
-
const socket = await createSocketIOServer(config)
|
|
111
|
-
socket.io
|
|
112
|
-
socket.attach(nodeHttpServer)
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Node consumers can remove `@types/bun` unless another dependency independently
|
|
116
|
-
requires it.
|
|
117
|
-
|
|
118
|
-
### Managed server shutdown
|
|
119
|
-
|
|
120
|
-
`createServer()` and `serveNode()` now return the same structural managed
|
|
121
|
-
lifecycle. Replace every direct runtime stop and parallel Socket.IO close:
|
|
122
|
-
|
|
123
|
-
```ts
|
|
124
|
-
// before — split ownership
|
|
125
|
-
const socket = await createSocketIOServer(config)
|
|
126
|
-
const server = createServer({
|
|
127
|
-
services,
|
|
128
|
-
websocket: socket.websocket,
|
|
129
|
-
rawRoutes: [socket.route],
|
|
130
|
-
})
|
|
131
|
-
server.stop()
|
|
132
|
-
await socket.io.close()
|
|
133
|
-
|
|
134
|
-
// after — one owner and one total deadline
|
|
135
|
-
const socket = await createSocketIOServer(config)
|
|
136
|
-
const server = createServer({ services, socket })
|
|
137
|
-
const result = await server.shutdown({ gracePeriodMs: 30_000 })
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
On Node, keep the same `socket` field and replace `handle.close()` with
|
|
141
|
-
`handle.shutdown()`. Runtime-specific diagnostics move under `handle.runtime`;
|
|
142
|
-
do not use it as a second shutdown path. Standalone CLI/tools that create a
|
|
143
|
-
Socket.IO handle without an HTTP server call `await socket.close()`.
|
|
144
|
-
|
|
145
|
-
If Bun Socket.IO shares the port with a raw lane, keep the explicit composition
|
|
146
|
-
but let the server mount the Socket.IO route:
|
|
147
|
-
|
|
148
|
-
```ts
|
|
149
|
-
createServer({
|
|
150
|
-
services,
|
|
151
|
-
socket,
|
|
152
|
-
websocket: composeWebSocketHandlers([
|
|
153
|
-
webSocketLane({ match: isRaw, handlers: rawHandlers }),
|
|
154
|
-
socketIoLane(socket.websocket),
|
|
155
|
-
]),
|
|
156
|
-
rawRoutes: [rawUpgradeRoute],
|
|
157
|
-
})
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
Move native Bun `routes` entries to `rawRoutes`. Native routes run before the
|
|
161
|
-
Fetch handler and therefore cannot participate in admission or drain. Wire
|
|
162
|
-
`SIGTERM`/`SIGINT` in the application; the first signal starts `shutdown()`, and
|
|
163
|
-
a later signal may abort the same controller. Close MCP, databases and queues
|
|
164
|
-
after the server result—those resources remain application-owned.
|
|
165
|
-
|
|
166
|
-
Move a handshake policy from the Node-only callback shape inside
|
|
167
|
-
`serverOptions` to the runtime-neutral top-level policy. It receives a Web
|
|
168
|
-
`Request`, may be async, and returns whether to admit the handshake:
|
|
169
|
-
|
|
170
|
-
```ts
|
|
171
|
-
// before
|
|
172
|
-
serverOptions: { allowRequest: (request, done) => done(null, allowed(request)) }
|
|
173
|
-
|
|
174
|
-
// after
|
|
175
|
-
allowRequest: (request) => allowed(request)
|
|
176
|
-
```
|