stitchkit 0.108.5 → 0.109.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/browser/cancellation.d.ts +4 -5
  3. package/dist/browser/cancellation.d.ts.map +1 -1
  4. package/dist/browser/client-executors.d.ts.map +1 -1
  5. package/dist/browser/client.d.ts +1 -1
  6. package/dist/browser/client.d.ts.map +1 -1
  7. package/dist/browser/http.d.ts +1 -1
  8. package/dist/browser/http.d.ts.map +1 -1
  9. package/dist/browser/session.d.ts +1 -1
  10. package/dist/browser/session.d.ts.map +1 -1
  11. package/dist/browser/transport.d.ts +1 -1
  12. package/dist/browser/transport.d.ts.map +1 -1
  13. package/dist/entrypoints/cli.js +1 -1
  14. package/dist/entrypoints/index.js +2 -2
  15. package/dist/entrypoints/react.js +1 -1
  16. package/dist/entrypoints/remote.js +2 -2
  17. package/dist/entrypoints/telegram.d.ts +2 -2
  18. package/dist/entrypoints/telegram.d.ts.map +1 -1
  19. package/dist/entrypoints/telegram.js +868 -137
  20. package/dist/entrypoints/testing.js +2 -2
  21. package/dist/entrypoints/tools.js +1 -1
  22. package/dist/{index-7jvwrjqa.js → index-00v1qz76.js} +20 -17
  23. package/dist/{index-05s01c94.js → index-5cw390s6.js} +96 -16
  24. package/dist/{index-p5kx5vqd.js → index-e32vy8jw.js} +22 -11
  25. package/dist/telegram/update-intake-work.d.ts +39 -0
  26. package/dist/telegram/update-intake-work.d.ts.map +1 -0
  27. package/dist/telegram/update-intake.d.ts +47 -9
  28. package/dist/telegram/update-intake.d.ts.map +1 -1
  29. package/dist/telegram/update-store-check.d.ts.map +1 -1
  30. package/dist/telegram/update-store-postgres.d.ts +2 -2
  31. package/dist/telegram/update-store-postgres.d.ts.map +1 -1
  32. package/dist/telegram/update-store-sqlite.d.ts +2 -2
  33. package/dist/telegram/update-store-sqlite.d.ts.map +1 -1
  34. package/dist/telegram/update-store.d.ts +52 -3
  35. package/dist/telegram/update-store.d.ts.map +1 -1
  36. package/dist/tools/cli/args-fields.d.ts +7 -1
  37. package/dist/tools/cli/args-fields.d.ts.map +1 -1
  38. package/dist/tools/cli/args.d.ts.map +1 -1
  39. package/llms/cli.txt +9 -1
  40. package/llms/stitchkit.txt +10 -3
  41. package/llms/telegram.txt +59 -8
  42. package/llms/{upgrading-0.100.0-0.108.0.txt → upgrading-0.101.0-0.109.0.txt} +70 -72
  43. package/llms/upgrading-0.37.0.txt +176 -0
  44. package/llms/{upgrading-0.37.0-0.58.0.txt → upgrading-0.44.0-0.60.0.txt} +229 -169
  45. package/llms/{upgrading-0.59.0-0.71.0.txt → upgrading-0.61.0-0.73.0.txt} +122 -229
  46. package/llms/{upgrading-0.72.0-0.99.0.txt → upgrading-0.74.0-0.100.0.txt} +72 -122
  47. package/llms/upgrading.txt +5 -4
  48. package/llms-full.txt +145 -12
  49. package/llms.txt +9 -8
  50. package/package.json +1 -1
package/llms-full.txt CHANGED
@@ -75,12 +75,12 @@ own, recorded as an ADR.
75
75
  | `stitchkit/geo` | server (Bun or Node) | evolving | managed GeoIP reader generations, last-known-good reload and the optional MaxMind adapter |
76
76
  | `stitchkit/oauth` | browser **and** server | evolving | provider-neutral Authorization Code + PKCE request and one-shot callback transaction mechanics |
77
77
  | `stitchkit/google` | server (Bun or Node) | evolving | optional Google code exchange and verified OIDC identity adapter |
78
- | `stitchkit/observability` | server | stable<br>_redefined in 2 of the 53 minors since 0.56.2, most recently 0.92.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
78
+ | `stitchkit/observability` | server | stable<br>_redefined in 2 of the 54 minors since 0.56.2, most recently 0.92.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
79
79
  | `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 |
80
80
  | `stitchkit/declaration` | browser + build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
81
81
  | `stitchkit/react` | browser + server rendering | stable | `createCursorQuery`, `createCacheBridge`, QueryClient and `ApiError` retry policy |
82
82
  | `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) |
83
- | `stitchkit/agent-runtime` | server | evolving<br>_redefined in 23 of the 53 minors since 0.56.2, most recently 0.105.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
83
+ | `stitchkit/agent-runtime` | server | evolving<br>_redefined in 23 of the 54 minors since 0.56.2, most recently 0.105.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
84
84
  | `stitchkit/agent-runtime/sandbox` | server | evolving | optional Linux Bubblewrap sessions, durable workspaces and a host HTTP credential gateway; see [sandbox guide](sandbox.md) |
85
85
  | `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 |
86
86
  | `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
@@ -92,7 +92,7 @@ own, recorded as an ADR.
92
92
  | `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
93
93
  | `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
94
94
  | `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
95
- | `stitchkit/application` | browser + server | evolving<br>_redefined in 13 of the 53 minors since 0.56.2, most recently 0.105.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
95
+ | `stitchkit/application` | browser + server | evolving<br>_redefined in 13 of the 54 minors since 0.56.2, most recently 0.105.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
96
96
  | `stitchkit/application/grammy` | server | evolving | a grammY bot as application resources — configuration, then polling with updates admitted by batch — and the webhook adapter |
97
97
  | `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
98
98
  | `stitchkit/application/schemas` | browser + server | evolving | the application's snapshot, health and shutdown schemas alone, without the kernel |
@@ -2785,6 +2785,13 @@ preserve facts the generic client cannot invent — for example a Unix transport
2785
2785
  an effect from `UNKNOWN_ERROR` alone; inspect the owned adapter's cause and retry
2786
2786
  only when it proves that dispatch did not happen.
2787
2787
 
2788
+ The same evidence survives when caller abort or the request deadline wins the
2789
+ race: the public code remains `REQUEST_ABORTED` or `REQUEST_TIMEOUT`, while
2790
+ the exact rejection produced by the transport remains in `ApiError.cause`.
2791
+ That cause is internal diagnostic data — it is not included by JSON/string
2792
+ rendering — so delivery state and trace metadata remain available without
2793
+ putting transport payloads or credentials in a client-facing error.
2794
+
2788
2795
  For an endpoint without contract arguments, pass only the options object:
2789
2796
 
2790
2797
  ```ts
@@ -9648,7 +9655,7 @@ string, the schema says what it should be:
9648
9655
  | `z.enum([...])` | `--size large` |
9649
9656
  | `z.array(z.string())`| `--tag a --tag b` → `["a","b"]` |
9650
9657
  | `z.object({...})` | `--opts '{"k":"v"}'` (JSON) or `--opts.k v` |
9651
- | `z.record(z.string(), z.unknown())` | `--data '{"code":"007"}'` (JSON) |
9658
+ | `z.record(z.string(), z.unknown())` | `--data '{"code":"007"}'` or `--data.code=007` → `"007"` |
9652
9659
  | `.optional()` / `.default()` | not required |
9653
9660
 
9654
9661
  Primitive literals use the same coercion through optional, nullable and default wrappers and as
@@ -9659,6 +9666,14 @@ Object and record JSON keeps the same behavior when a CLI discovers a tool throu
9659
9666
  `propertyNames`, `minProperties` and `maxProperties` constraints still run before dispatch; CLI
9660
9667
  coercion does not execute application transforms.
9661
9668
 
9669
+ A dotted leaf follows the leaf schema, including through optional/nullable wrappers and restored
9670
+ MCP object guards. A declared number or boolean is coerced; a string stays byte-for-byte lexical.
9671
+ For a free `z.record(z.string(), z.unknown())`, argv provides no JSON type tag, so the dotted
9672
+ value also stays a string: `007`, `+007`, `1e3`, `true` and `false` keep those spellings.
9673
+ Use the whole-object JSON form when a free record value must be a JSON number or boolean. This
9674
+ avoids silently changing identifiers while keeping `z.record(..., z.number())` and
9675
+ `z.record(..., z.boolean())` explicitly typed.
9676
+
9662
9677
  After a bare boolean flag, the next token is its value when it is exactly
9663
9678
  `true` or `false` — `--active false` turns it off, as it reads. Any other word
9664
9679
  there stays a positional, and `--` makes a literal `false` one too. The same
@@ -15264,9 +15279,10 @@ import { Database } from 'bun:sqlite'
15264
15279
  import type { Update } from 'grammy/types'
15265
15280
 
15266
15281
  const webhook = { token: env.BOT_TOKEN, url: env.WEBHOOK_URL, secret: env.WEBHOOK_SECRET }
15282
+ const updateStore = sqliteTelegramUpdateStore({ database: new Database(env.UPDATES_DB) })
15267
15283
 
15268
15284
  const intake = createTelegramUpdateIntake<Update>({
15269
- store: sqliteTelegramUpdateStore({ database: new Database(env.UPDATES_DB) }),
15285
+ store: updateStore,
15270
15286
  handle: (update) => bot.handleUpdate(update),
15271
15287
  onFailure: (failure) => logger.warn('Update failed', { ...failure }),
15272
15288
  })
@@ -15310,13 +15326,55 @@ fix (a refused message, a blocked user) is abandoned; `maxAttempts` (5) ends
15310
15326
  the rest. Delivery is at least once: a handler that finished but could not be
15311
15327
  recorded as finished runs again.
15312
15328
 
15329
+ Use `handleAttempt` when the handler needs the immutable attempt fence and an
15330
+ ownership-loss signal. A signal asks slow work to stop; the fence is what
15331
+ authorizes a domain write. Check it through a transaction-bound reference store
15332
+ inside the same database transaction as that write:
15333
+
15334
+ ```ts
15335
+ handleAttempt: async (update, { fence, ownerLost }) => {
15336
+ ownerLost.throwIfAborted()
15337
+ await database.transaction(async (tx) => {
15338
+ const transactionStore = postgresTelegramUpdateStore({
15339
+ query: (text, parameters) => tx.query(text, parameters),
15340
+ createTable: false,
15341
+ })
15342
+ if (!(await transactionStore.owns(fence, Date.now()))) return
15343
+ await applyDomainTransition(tx, update)
15344
+ })
15345
+ }
15346
+ ```
15347
+
15348
+ The fence contains the claim's own `{ updateId, attempt, claimId }`. The opaque
15349
+ `claimId` is persisted and never reused, so an old handler cannot adopt either
15350
+ a newer attempt or a pruned and recreated `updateId`. Existing `handle(update)`
15351
+ remains unchanged, including direct functions whose own optional second
15352
+ argument has a different meaning.
15353
+
15354
+ For a final obligation, configure `handleExhaustion`. The reference store keeps
15355
+ the terminal record unacknowledged until this handler resolves, including
15356
+ across restart; a throw leaves it for the next sweep. Delivery is at least once,
15357
+ so use the complete `{ updateId, attempt, claimId }` as an idempotency key in
15358
+ the consumer database:
15359
+
15360
+ ```ts
15361
+ handleExhaustion: ({ updateId, attempt, claimId, update, error }) =>
15362
+ recordFinalFailureOnce({ key: `telegram:${updateId}:${attempt}:${claimId}`, update, error })
15363
+ ```
15364
+
15365
+ This reuses the update row and table. Without `handleExhaustion`, terminal
15366
+ abandonment retains its previous behavior.
15367
+
15313
15368
  With grammY the handler is `bot.handleUpdate`, which wraps a middleware's error
15314
15369
  in a `BotError`; the intake unwraps it, so `retry`, `onFailure` and the error
15315
15370
  stored with the update are what the middleware threw — a `retry` that returns
15316
15371
  `false` for the bot's own terminal error sees that error.
15317
15372
 
15318
- The store is an interface of six atomic steps (`TelegramUpdateStore`), so the
15319
- bot's own database holds it:
15373
+ The base store remains the six atomic steps of `TelegramUpdateStore`. A
15374
+ `TelegramUpdateFencedStore` adds `claimOwned`, `renewOwned`, `owns` and
15375
+ `settleOwned`; `TelegramUpdateDurableStore` adds the final-obligation methods.
15376
+ Reference stores implement both, so the bot's own database holds the fence and
15377
+ final obligation without a second queue:
15320
15378
 
15321
15379
  | Store | Takes |
15322
15380
  |---|---|
@@ -15343,7 +15401,12 @@ postgresTelegramUpdateStore({
15343
15401
  Each rule is one conditional statement, so a claim is atomic across every
15344
15402
  process sharing the table. By default the table is created on first use; where
15345
15403
  migrations own the schema, `postgresTelegramUpdateStoreSchema(table)` is the
15346
- statement to put in one.
15404
+ statement to put in one. Apply it before using `handleAttempt` or
15405
+ `handleExhaustion`; it adds `claim_id` idempotently. Legacy `handle(update)`
15406
+ uses base PostgreSQL operations that do not reference that column. SQLite adds
15407
+ the column automatically and tolerates two rolling processes racing the
15408
+ migration. A direct base-store claim with `durableExhaustion: true` also opts
15409
+ into the column-backed durable capability.
15347
15410
 
15348
15411
  A store of your own — over an ORM, another database — is put through the same
15349
15412
  rules the shipped ones are, concurrent claims included:
@@ -15798,6 +15861,73 @@ analytics policy belong to the application.
15798
15861
 
15799
15862
  # Upgrading stitchkit
15800
15863
 
15864
+ ## Released migration: 0.109.0
15865
+
15866
+ ### free CLI record leaves are lexical
15867
+
15868
+ **Who must act:** scripts that pass dotted values into a free `record<string, unknown>` and rely on
15869
+ stitchkit guessing numbers or booleans from their spelling. Declared object leaves and whole-object
15870
+ JSON keep their typed behavior.
15871
+
15872
+ Free record values have no schema type to justify coercion. They now preserve argv text, so values
15873
+ such as `007`, `1e3`, `true` and `false` arrive exactly as written.
15874
+ See [ADR 0257](../decisions/0257-cli-dotted-values-follow-their-declared-schema.md).
15875
+
15876
+ 1. Pass typed free-record values as one JSON object:
15877
+
15878
+ ```sh
15879
+ # before: produced { count: 5 } by spelling-based inference
15880
+ app command --data.count=5
15881
+ # after: JSON says explicitly that 5 is a number
15882
+ app command --data='{"count":5}'
15883
+ ```
15884
+
15885
+ 2. If dotted flags are the intended interface, declare their object shape; a `z.number()` or
15886
+ `z.boolean()` leaf still coerces and validates its own CLI value.
15887
+
15888
+ ### Opting into Telegram attempt fencing
15889
+
15890
+ Existing `handle(update)` callbacks and the six-method `TelegramUpdateStore` need no change. The
15891
+ new capability is opt-in
15892
+ ([ADR 0256](../decisions/0256-a-telegram-attempt-is-fenced-by-a-persisted-claim.md)).
15893
+
15894
+ 1. To fence a domain write, move only that handler to the explicit context-aware option:
15895
+
15896
+ ```ts
15897
+ createTelegramUpdateIntake({
15898
+ store,
15899
+ handleAttempt: async (update, { fence, ownerLost }) => {
15900
+ ownerLost.throwIfAborted()
15901
+ await domainTransaction(async (tx) => {
15902
+ if (await transactionStore(tx).owns(fence, Date.now())) await apply(tx, update)
15903
+ })
15904
+ },
15905
+ })
15906
+ ```
15907
+
15908
+ 2. A direct grammY handler remains `handle: bot.handleUpdate.bind(bot)`; stitchkit does not pass its
15909
+ attempt context into grammY's optional webhook-envelope parameter.
15910
+
15911
+ 3. A custom store used by `handleAttempt` implements `claimOwned`, `renewOwned`, `owns` and
15912
+ `settleOwned` over the full `{ updateId, attempt, claimId }` identity. If it also delivers
15913
+ `handleExhaustion`, implement `exhaust`, `dueExhaustions` and `acknowledgeExhaustion`. Run
15914
+ `checkTelegramUpdateStore` against a fresh database; it checks base, fenced and durable rules
15915
+ according to the methods the store exposes.
15916
+
15917
+ 4. SQLite stores add `claim_id` automatically. PostgreSQL stores with the default
15918
+ `createTable: true` do the same. When migrations own a PostgreSQL table, apply the returned
15919
+ schema before enabling `handleAttempt` or `handleExhaustion`:
15920
+
15921
+ ```ts
15922
+ await sql.unsafe(postgresTelegramUpdateStoreSchema('telegram_updates'))
15923
+ // Equivalent addition for an existing table:
15924
+ // ALTER TABLE telegram_updates ADD COLUMN IF NOT EXISTS claim_id TEXT;
15925
+ ```
15926
+
15927
+ Legacy `handle(update)` continues to use base operations that do not reference `claim_id`, so
15928
+ the migration is required only when the new capability or an explicit base
15929
+ `claim(..., { durableExhaustion: true })` is enabled.
15930
+
15801
15931
  ## Released migration: 0.108.0
15802
15932
 
15803
15933
  ### a request that never left is its own send outcome
@@ -22575,13 +22705,16 @@ injected grammY bot. → ADR 0143, ADR 0201 — [guide](../guide/telegram.md)
22575
22705
  | `telegramWebhookUrl` | function | the address with an `owner` tag derived from the secret: equal for one secret, different for another, the path untouched |
22576
22706
  | `checkTelegramWebhook` / `TelegramWebhookState` | function / _type_ | whether the webhook still points here: `owned`, `ownerHost`, `pendingUpdates`, Telegram's `lastError` |
22577
22707
  | `receiveTelegramWebhook` / `ReceiveTelegramWebhookOptions` / `TelegramUpdateAcceptance` | function / _type_ | one webhook `Request`: 403 without the secret (compared in constant time), 405 for another method, 400 for no update, 200 once `accept` recorded it |
22578
- | `createTelegramUpdateIntake` | function | webhook updates recorded before Telegram is answered and handled after: chat order kept, other chats alongside up to `maxConcurrent`, a renewed lease per attempt, a sweep that takes over what a restart or a dead process left, retries, `maxAttempts`, finished updates remembered `retainMs` to refuse repeats; at least once |
22579
- | `TelegramUpdateIntakeConfig` / `TelegramUpdateIntake` / `TelegramUpdateEnvelope` / `TelegramUpdateFailure` / `TelegramUpdateStoreStep` | _type_ | `store`, `handle` (a grammY `BotError` is unwrapped: `retry`, `onFailure` and the stored error see what the middleware threw), `retry`, `maxAttempts` (5), `leaseMs` (120 000), `pendingGraceMs` (60 000), `sweepEveryMs` (30 000), `retainMs` (24 h), `maxConcurrent` (32), `onFailure`, `onStoreError`, `now`; `accept(body)`, `start()`, `sweep()`, `idle()`, `close()` |
22580
- | `TelegramUpdateStore` / `StoredTelegramUpdate` / `TelegramUpdateState` / `TelegramUpdateSettlement` / `TelegramUpdateClaimOptions` / `TelegramUpdateDueQuery` | _type_ | the store an intake runs on: `add`, `claim`, `renew`, `settle`, `due`, `prune`, each atomic on one record — a claim takes `pending`, a due `failed` or a lapsed `processing`; renew and settle only by the attempt holding it |
22708
+ | `createTelegramUpdateIntake` | function | webhook updates recorded before Telegram is answered and handled after: chat order kept, other chats alongside up to `maxConcurrent`, a renewed lease and immutable fence per attempt, a sweep that takes over what a restart or a dead process left, retries, `maxAttempts`, optional recoverable exhaustion delivery, finished updates remembered `retainMs` to refuse repeats; at least once |
22709
+ | `TelegramUpdateIntakeConfig` / `TelegramUpdateAttemptIntakeConfig` / `TelegramUpdateIntakeOptions` / `TelegramUpdateIntake` / `TelegramUpdateEnvelope` / `TelegramUpdateFailure` / `TelegramUpdateStoreStep` | _type_ | `store`, unchanged `handle(update)` or attempt-aware `handleAttempt(update, context)` (a grammY `BotError` is unwrapped), shared `retry`, `maxAttempts` (5), `leaseMs` (120 000), `pendingGraceMs` (60 000), `sweepEveryMs` (30 000), `retainMs` (24 h), `maxConcurrent` (32), `onFailure`, durable `handleExhaustion`, `onExhaustionFailure`, `onStoreError`, `now`; `accept(body)`, `start()`, `sweep()`, `idle()`, `close()` |
22710
+ | `TelegramUpdateAttemptContext` / `TelegramUpdateAttemptIdentity` / `TelegramUpdateOwnershipLostError` | _type_ / class | immutable `{ updateId, attempt, claimId }` fence plus `ownerLost`; the persisted opaque claim token prevents a stale capability from matching after prune/re-add, while a store check in the consumer's DB transaction fences a domain write |
22711
+ | `TelegramUpdateExhaustion` / `TelegramUpdateExhaustionFailure` / `StoredTelegramUpdateExhaustion` / `TelegramUpdateExhaustionQuery` | _type_ | a terminal update/attempt/error retained in the update store until `handleExhaustion` resolves; ordered `{ limit, afterUpdateId? }` pages prevent a failing first batch from starving later rows; delivery failures are observational and leave it due |
22712
+ | `TelegramUpdateStore` / `StoredTelegramUpdate` / `TelegramUpdateState` / `TelegramUpdateSettlement` / `TelegramUpdateClaimOptions` / `TelegramUpdateDueQuery` | _type_ | the base store an intake runs on: `add`, `claim`, `renew`, `settle`, `due`, `prune`, each atomic on one record — a claim takes `pending`, a due `failed` or a lapsed `processing`; renew and settle only by the attempt holding it |
22713
+ | `TelegramUpdateFencedStore` / `TelegramUpdateDurableStore` | _type_ | reference-store capabilities: `claimOwned` creates and returns the persisted identity, `renewOwned`, `owns(identity, at)` and `settleOwned(identity, settlement)` act only on that exact unexpired claim; `exhaust`, `dueExhaustions`, `acknowledgeExhaustion` keep a final consumer obligation in the same row until exact acknowledgement |
22581
22714
  | `memoryTelegramUpdateStore` | function | the store in this process's memory — tests, or a bot that accepts losing unhandled updates to a restart |
22582
22715
  | `sqliteTelegramUpdateStore` / `SqliteTelegramUpdateStoreConfig` / `TelegramSqliteDatabase` | function / _type_ | the store in SQLite over the handle the application opened — `bun:sqlite` `Database` or `node:sqlite` `DatabaseSync`; `table` (default `telegram_updates`) created when missing |
22583
22716
  | `postgresTelegramUpdateStore` / `PostgresTelegramUpdateStoreConfig` / `TelegramPostgresQuery` | function / _type_ | the store in Postgres over the client the application holds, as one `query(text, parameters)` returning rows — Bun `sql.unsafe`, Prisma `$queryRawUnsafe`, `pg` `pool.query`; each rule one conditional statement; `table`, `createTable` (default `true`) |
22584
- | `postgresTelegramUpdateStoreSchema` | function | the table and its index as a statement for a migration, safe to run twice |
22717
+ | `postgresTelegramUpdateStoreSchema` | function | the table, idempotent `claim_id` upgrade and index as a statement for a migration, safe to run twice; required before fenced methods when `createTable: false`, while legacy base methods remain compatible with the prior table |
22585
22718
  | `checkTelegramUpdateStore` | function | put any store through every rule, each on a fresh store from `make`, concurrent claims included; resolves with the violations, empty when it keeps them |
22586
22719
 
22587
22720
  ---
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) 46.7 KB → [llms/stitchkit.2.txt](llms/stitchkit.2.txt) 36.5 KB
12
+ - **stitchkit**: [llms/stitchkit.txt](llms/stitchkit.txt) 47.2 KB → [llms/stitchkit.2.txt](llms/stitchkit.2.txt) 36.5 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,7 +18,7 @@ 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.7 KB
21
- - **stitchkit/cli**: [llms/cli.txt](llms/cli.txt) 43.1 KB → [llms/cli.2.txt](llms/cli.2.txt) 20.2 KB
21
+ - **stitchkit/cli**: [llms/cli.txt](llms/cli.txt) 43.8 KB → [llms/cli.2.txt](llms/cli.2.txt) 20.2 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
@@ -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.5 KB
45
- - **stitchkit/telegram**: [llms/telegram.txt](llms/telegram.txt) 32.9 KB
45
+ - **stitchkit/telegram**: [llms/telegram.txt](llms/telegram.txt) 36.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) 16.8 KB
@@ -61,11 +61,12 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
61
61
  - **stitchkit/files/packaging**: [llms/files-packaging.txt](llms/files-packaging.txt) 3.5 KB
62
62
 
63
63
  ## Upgrading slices
64
- - **Upgrading — how to move across versions**: [llms/upgrading.txt](llms/upgrading.txt) 12.1 KB
65
- - **Upgrading 0.100.0 → 0.108.0**: [llms/upgrading-0.100.0-0.108.0.txt](llms/upgrading-0.100.0-0.108.0.txt) 46.1 KB
66
- - **Upgrading 0.72.0 → 0.99.0**: [llms/upgrading-0.72.0-0.99.0.txt](llms/upgrading-0.72.0-0.99.0.txt) 46.4 KB
67
- - **Upgrading 0.59.0 → 0.71.0**: [llms/upgrading-0.59.0-0.71.0.txt](llms/upgrading-0.59.0-0.71.0.txt) 45.6 KB
68
- - **Upgrading 0.37.0 → 0.58.0**: [llms/upgrading-0.37.0-0.58.0.txt](llms/upgrading-0.37.0-0.58.0.txt) 40.0 KB
64
+ - **Upgrading — how to move across versions**: [llms/upgrading.txt](llms/upgrading.txt) 12.2 KB
65
+ - **Upgrading 0.101.0 → 0.109.0**: [llms/upgrading-0.101.0-0.109.0.txt](llms/upgrading-0.101.0-0.109.0.txt) 45.0 KB
66
+ - **Upgrading 0.74.0 → 0.100.0**: [llms/upgrading-0.74.0-0.100.0.txt](llms/upgrading-0.74.0-0.100.0.txt) 45.1 KB
67
+ - **Upgrading 0.61.0 → 0.73.0**: [llms/upgrading-0.61.0-0.73.0.txt](llms/upgrading-0.61.0-0.73.0.txt) 41.2 KB
68
+ - **Upgrading 0.44.0 → 0.60.0**: [llms/upgrading-0.44.0-0.60.0.txt](llms/upgrading-0.44.0-0.60.0.txt) 43.9 KB
69
+ - **Upgrading 0.37.0 → 0.37.0**: [llms/upgrading-0.37.0.txt](llms/upgrading-0.37.0.txt) 6.2 KB
69
70
 
70
71
  ## Guide (web)
71
72
  - [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,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.108.5",
3
+ "version": "0.109.1",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",