stitchkit 0.115.0 → 0.116.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/agent-runtime/coding-tool-paths.d.ts.map +1 -1
  3. package/dist/entrypoints/agent-runtime/coding-tools.js +4 -4
  4. package/dist/entrypoints/agent-runtime/harness.js +2 -2
  5. package/dist/entrypoints/agent-runtime/sandbox.js +4 -4
  6. package/dist/entrypoints/agent-runtime/sqlite/bun.js +6 -6
  7. package/dist/entrypoints/agent-runtime/sqlite/node.js +6 -6
  8. package/dist/entrypoints/agent-runtime/testing.js +6 -6
  9. package/dist/entrypoints/agent-runtime.js +6 -6
  10. package/dist/entrypoints/cli.js +3 -3
  11. package/dist/entrypoints/telegram/grammy.js +2 -2
  12. package/dist/entrypoints/telegram.d.ts +1 -1
  13. package/dist/entrypoints/telegram.d.ts.map +1 -1
  14. package/dist/entrypoints/telegram.js +22 -9
  15. package/dist/entrypoints/tools.js +3 -3
  16. package/dist/{index-dx5cm9pc.js → index-4g6qmgdx.js} +1 -1
  17. package/dist/{index-nregbbsc.js → index-6f49krb5.js} +1 -1
  18. package/dist/{index-x0ddbj85.js → index-arjmb6de.js} +36 -1
  19. package/dist/{index-crmswbrt.js → index-fa435yq2.js} +1 -1
  20. package/dist/{index-944x38nv.js → index-jq2ky8fw.js} +1 -1
  21. package/dist/{index-7yx8j6ay.js → index-n5sv4z0w.js} +12 -3
  22. package/dist/{index-j8kf56wx.js → index-q968hy6y.js} +1 -1
  23. package/dist/{index-3qqdqwxe.js → index-w7jq3fz9.js} +25 -5
  24. package/dist/internal/contained-files.d.ts +10 -0
  25. package/dist/internal/contained-files.d.ts.map +1 -1
  26. package/dist/telegram/budget-transformer.d.ts +5 -2
  27. package/dist/telegram/budget-transformer.d.ts.map +1 -1
  28. package/dist/telegram/outbound-budget.d.ts +26 -11
  29. package/dist/telegram/outbound-budget.d.ts.map +1 -1
  30. package/dist/tools/cli/view.d.ts +7 -1
  31. package/dist/tools/cli/view.d.ts.map +1 -1
  32. package/llms/agent-runtime.txt +2 -2
  33. package/llms/cli.txt +3 -1
  34. package/llms/stitchkit.txt +3 -3
  35. package/llms/telegram.txt +10 -3
  36. package/llms/{upgrading-0.104.0-0.115.0.txt → upgrading-0.105.0-0.116.0.txt} +26 -124
  37. package/llms/{upgrading-0.44.0-0.61.0.txt → upgrading-0.44.0-0.62.0.txt} +120 -3
  38. package/llms/{upgrading-0.62.0-0.78.0.txt → upgrading-0.63.0-0.83.0.txt} +181 -120
  39. package/llms/{upgrading-0.79.0-0.103.13.txt → upgrading-0.84.0-0.104.0.txt} +124 -181
  40. package/llms/upgrading.txt +4 -4
  41. package/llms-full.txt +41 -9
  42. package/llms.txt +6 -6
  43. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"contained-files.d.ts","sourceRoot":"","sources":["../../src/internal/contained-files.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contained-files.d.ts","sourceRoot":"","sources":["../../src/internal/contained-files.ts"],"names":[],"mappings":"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"}
@@ -16,7 +16,7 @@
16
16
  * grammY is named in the declarations and never imported at run time.
17
17
  */
18
18
  import type { Transformer } from 'grammy';
19
- import type { TelegramOutboundBudget } from './outbound-budget.js';
19
+ import type { TelegramOutboundBudget, TelegramOutboundCallOptions } from './outbound-budget.js';
20
20
  /**
21
21
  * A grammY client transformer that runs every Bot API call under `budget`.
22
22
  *
@@ -30,6 +30,9 @@ import type { TelegramOutboundBudget } from './outbound-budget.js';
30
30
  * `TelegramNotDispatchedError`: nothing was sent. A cancellation after the
31
31
  * request was handed on is the client's ordinary error and the outcome is
32
32
  * unknown, not a definite failure.
33
+ *
34
+ * `options.lane` applies to every call through this client: a campaign installs
35
+ * `{ lane: 'bulk' }` on its own `Api`, and replies stay ahead of it.
33
36
  */
34
- export declare function telegramBudgetTransformer(budget: TelegramOutboundBudget): Transformer;
37
+ export declare function telegramBudgetTransformer(budget: TelegramOutboundBudget, options?: TelegramOutboundCallOptions): Transformer;
35
38
  //# sourceMappingURL=budget-transformer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"budget-transformer.d.ts","sourceRoot":"","sources":["../../src/telegram/budget-transformer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAE1C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AA4BhE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,sBAAsB,GAAG,WAAW,CAsBrF"}
1
+ {"version":3,"file":"budget-transformer.d.ts","sourceRoot":"","sources":["../../src/telegram/budget-transformer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAE1C,OAAO,KAAK,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AA4B7F;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,CAAC,EAAE,2BAA2B,GACpC,WAAW,CA4Bb"}
@@ -13,9 +13,15 @@
13
13
  * `forwardMessages` cost their message ids, and the follow-up call to action
14
14
  * after an album is one more message.
15
15
  *
16
- * **It paces; it does not retry.** A 429 pauses every sender of the token for
17
- * the wait Telegram stated (or a declared fallback when it stated none). A
18
- * network failure or a 5xx is returned to the caller unchanged: repeating a
16
+ * Two lanes share that one rate. An `interactive` call is granted before any
17
+ * `bulk` call that is waiting, so a person's reply never queues behind a
18
+ * campaign; a campaign runs at whatever rate replies leave it.
19
+ *
20
+ * **It paces; it does not retry.** A 429 on a method that spends the budget
21
+ * pauses every sender of the token for the wait Telegram stated (or a declared
22
+ * fallback when it stated none). A 429 on an edit or a read concerns that call
23
+ * and pauses nothing. A network failure or a 5xx is returned to the caller
24
+ * unchanged: repeating a
19
25
  * send whose external outcome is unknown is the caller's decision, and a
20
26
  * primitive that retried it would turn one unknown message into two.
21
27
  *
@@ -25,6 +31,8 @@
25
31
  * saved burst at start and again after a 429 pause, which is exactly the
26
32
  * stampede a shared budget exists to prevent.
27
33
  */
34
+ /** Whose turn comes first. `interactive` answers a person; `bulk` is a campaign. */
35
+ export type TelegramOutboundLane = 'interactive' | 'bulk';
28
36
  export interface TelegramOutboundBudgetConfig {
29
37
  /** The bot token whose sends share this budget. It is never returned or logged. */
30
38
  readonly token: string;
@@ -52,31 +60,38 @@ export interface TelegramOutboundBudgetStats {
52
60
  readonly granted: number;
53
61
  /** Weighted messages admitted: an album of three counts as three. */
54
62
  readonly messages: number;
55
- /** Calls waiting for their turn. */
63
+ /** Calls waiting for their turn, in both lanes. */
56
64
  readonly queued: number;
65
+ /** How many of them are in the `bulk` lane. */
66
+ readonly queuedBulk: number;
57
67
  readonly messagesPerSecond: number;
58
68
  /** How much of the current 429 pause is still ahead, in milliseconds. */
59
69
  readonly pausedForMs: number;
60
70
  }
71
+ export interface TelegramOutboundCallOptions {
72
+ /** Default `interactive`. */
73
+ readonly lane?: TelegramOutboundLane;
74
+ }
61
75
  /**
62
76
  * A token's outbound budget. `run` is the narrow adapter a client transformer
63
77
  * calls around its own send; it gates, pauses on 429 and never retries.
64
78
  */
65
79
  export interface TelegramOutboundBudget {
66
80
  /**
67
- * Run one Bot API call under the budget. A non-send method passes through
68
- * without spending a message. A 429 pauses every sender of the token, whether
69
- * `send` throws it or resolves with the Bot API's `{ ok: false, … }` body, as
70
- * a client transformer's `send` does. The error is rethrown, or the response
71
- * returned, unchanged and the call is not repeated.
81
+ * Run one Bot API call under the budget, in the `interactive` lane by default.
82
+ * A non-send method passes through without spending a message. A 429 on a send
83
+ * pauses every sender of the token, whether `send` throws it or resolves with
84
+ * the Bot API's `{ ok: false, … }` body, as a client transformer's `send` does;
85
+ * a 429 on a non-send method pauses nothing. The error is rethrown, or the
86
+ * response returned, unchanged and the call is not repeated.
72
87
  */
73
- run<T>(method: string, payload: unknown, signal: AbortSignal | undefined, send: () => Promise<T>): Promise<T>;
88
+ run<T>(method: string, payload: unknown, signal: AbortSignal | undefined, send: () => Promise<T>, options?: TelegramOutboundCallOptions): Promise<T>;
74
89
  /**
75
90
  * Wait until `cost` messages fit. The wait rejects with `signal.reason`
76
91
  * without spending a token; a granted call owns its slots even if its later
77
92
  * send is aborted, which the caller must not repeat as a definite failure.
78
93
  */
79
- acquire(cost: number, signal?: AbortSignal): Promise<void>;
94
+ acquire(cost: number, signal?: AbortSignal, options?: TelegramOutboundCallOptions): Promise<void>;
80
95
  /** Pause every sender of this token for at least `milliseconds`. Never shortens an existing pause. */
81
96
  pause(milliseconds: number): void;
82
97
  /** Pause the token after a rate-limited refusal; another failure does nothing. */
@@ -1 +1 @@
1
- {"version":3,"file":"outbound-budget.d.ts","sourceRoot":"","sources":["../../src/telegram/outbound-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAwEH,MAAM,WAAW,4BAA4B;IAC3C,mFAAmF;IACnF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAED,kEAAkE;AAClE,MAAM,WAAW,2BAA2B;IAC1C,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,yEAAyE;IACzE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,GAAG,CAAC,CAAC,EACH,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,CAAC,CAAC,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,sGAAsG;IACtG,KAAK,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,kFAAkF;IAClF,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC;;;OAGG;IACH,gBAAgB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,sDAAsD;IACtD,KAAK,IAAI,2BAA2B,CAAC;CACtC;AAyMD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,4BAA4B,GACnC,sBAAsB,CAsCxB"}
1
+ {"version":3,"file":"outbound-budget.d.ts","sourceRoot":"","sources":["../../src/telegram/outbound-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAwEH,oFAAoF;AACpF,MAAM,MAAM,oBAAoB,GAAG,aAAa,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,4BAA4B;IAC3C,mFAAmF;IACnF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAED,kEAAkE;AAClE,MAAM,WAAW,2BAA2B;IAC1C,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,yEAAyE;IACzE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAC1C,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;;OAOG;IACH,GAAG,CAAC,CAAC,EACH,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAAC,CAAC,CAAC,CAAC;IACd;;;;OAIG;IACH,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,sGAAsG;IACtG,KAAK,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,kFAAkF;IAClF,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC;;;OAGG;IACH,gBAAgB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,sDAAsD;IACtD,KAAK,IAAI,2BAA2B,CAAC;CACtC;AA6ND;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,4BAA4B,GACnC,sBAAsB,CAsCxB"}
@@ -1,12 +1,18 @@
1
1
  import type { CliResultView } from './args-view.js';
2
- /** What a view produces: a JSON value, or the one human-facing shape. */
2
+ /**
3
+ * What a view produces: a JSON value, or the one human-facing shape. `order` is the order of
4
+ * a grouped object's keys, which an object cannot hold once a key looks like an integer.
5
+ */
3
6
  export type CliViewOutput = {
4
7
  kind: 'json';
5
8
  data: unknown;
9
+ order?: readonly string[];
6
10
  } | {
7
11
  kind: 'text';
8
12
  text: string;
9
13
  };
14
+ /** One grouped view in its own order, spaced as the CLI spaces any JSON it prints. */
15
+ export declare function stringifyGroups(data: unknown, order: readonly string[], compact: boolean): string;
10
16
  /** Compute the requested view, or refuse it with a message naming the field. */
11
17
  export declare function renderCliView(data: unknown, view: CliResultView): CliViewOutput;
12
18
  //# sourceMappingURL=view.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/view.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,yEAAyE;AACzE,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AA4M7F,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,GAAG,aAAa,CAgC/E"}
1
+ {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/view.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAuGnC,sFAAsF;AACtF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,EAAE,OAAO,GACf,MAAM,CAMR;AA6GD,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,GAAG,aAAa,CAgC/E"}
@@ -314,8 +314,8 @@ stay pinned through authorization; `write_file` plans before it and opens the pa
314
314
  the parent it creates does not exist yet. Reads revalidate the pinned file identity;
315
315
  writes and patches revalidate the pinned parent identity; search and resource discovery descend
316
316
  only through opened directories. A path that changed during authorization refuses with `CONFLICT`.
317
- Policies compare path strings, so on a case-insensitive filesystem such as default macOS volumes a
318
- rule on `credentials` does not match `CREDENTIALS`; such a host must normalize in its own policy.
317
+ A path spelled differently from the name stored on disk refuses before any policy reads it, so on a
318
+ case-insensitive volume a rule on `credentials` cannot be passed by asking for `CREDENTIALS`.
319
319
  NUL bytes are refused before either host policy sees a path.
320
320
  Reads and edits open file candidates without blocking on special files, then require a regular
321
321
  file. A writerless FIFO therefore refuses instead of occupying a filesystem worker. `write_file`
package/llms/cli.txt CHANGED
@@ -670,7 +670,9 @@ myapp item_list --sort messages --top 5 --json # the same five, a
670
670
  myapp item_list --sort name --ascending # ordered the other way
671
671
  ```
672
672
 
673
- Groups come back largest first for the same reason. A record that carries no
673
+ Groups come back largest first for the same reason, in the printed bytes even when a key looks
674
+ like a number; a reader that parses them into a JavaScript object reorders such keys itself.
675
+ A string equal to `null` or `(absent)` is quoted, so it stays apart from the missing value. A record that carries no
674
676
  value for the sort field sorts **last in both directions**: it is not the
675
677
  smallest, it is not on the scale at all, and letting it lead an ascending list
676
678
  would answer a question nobody asked.
@@ -86,13 +86,13 @@ own, recorded as an ADR.
86
86
  | `stitchkit/geo` | server (Bun or Node) | evolving | managed GeoIP reader generations, last-known-good reload and the optional MaxMind adapter |
87
87
  | `stitchkit/oauth` | browser **and** server | evolving | provider-neutral Authorization Code + PKCE request and one-shot callback transaction mechanics |
88
88
  | `stitchkit/google` | server (Bun or Node) | evolving | optional Google code exchange and verified OIDC identity adapter |
89
- | `stitchkit/observability` | server | stable<br>_redefined in 2 of the 60 minors since 0.56.2, most recently 0.92.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
89
+ | `stitchkit/observability` | server | stable<br>_redefined in 2 of the 61 minors since 0.56.2, most recently 0.92.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
90
90
  | `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 |
91
91
  | `stitchkit/declaration` | browser + build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
92
92
  | `stitchkit/react` | browser + server rendering | stable | `createCursorQuery`, `createCacheBridge`, QueryClient and `ApiError` retry policy |
93
93
  | `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) |
94
94
  | `stitchkit/react/keyboard/testing` | server (Bun or Node) | evolving | the keyboard layers and zones without a DOM — fakes for the window, elements and key events beside the two engines, to test the order of layers, `scope`/`inert` and the edges of a zone in milliseconds |
95
- | `stitchkit/agent-runtime` | server | evolving<br>_redefined in 25 of the 60 minors since 0.56.2, most recently 0.115.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
95
+ | `stitchkit/agent-runtime` | server | evolving<br>_redefined in 25 of the 61 minors since 0.56.2, most recently 0.115.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
96
96
  | `stitchkit/agent-runtime/sandbox` | server | evolving | optional Linux Bubblewrap sessions, durable workspaces and a host HTTP credential gateway; see [sandbox guide](sandbox.md) |
97
97
  | `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 |
98
98
  | `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
@@ -104,7 +104,7 @@ own, recorded as an ADR.
104
104
  | `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
105
105
  | `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
106
106
  | `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
107
- | `stitchkit/application` | browser + server | evolving<br>_redefined in 14 of the 60 minors since 0.56.2, most recently 0.110.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
107
+ | `stitchkit/application` | browser + server | evolving<br>_redefined in 14 of the 61 minors since 0.56.2, most recently 0.110.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
108
108
  | `stitchkit/application/grammy` | server | evolving | a grammY bot as application resources — configuration, then polling with updates admitted by batch — and the webhook adapter |
109
109
  | `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
110
110
  | `stitchkit/application/schemas` | browser + server | evolving | the application's snapshot, health and shutdown schemas alone, without the kernel |
package/llms/telegram.txt CHANGED
@@ -122,6 +122,13 @@ cast, and a send cancelled in the queue then waits for its slot and fails as
122
122
  a follow-up call to action after an album costs one more. Reads and edits
123
123
  (`getMe`, `getFile`, `editMessage*`, `deleteMessage`, `sendChatAction`) do not
124
124
  spend the budget.
125
+ - **Two lanes share one rate.** A call is `interactive` by default; a campaign passes
126
+ `{ lane: 'bulk' }` to `run` or `acquire`, or installs
127
+ `telegramBudgetTransformer(budget, { lane: 'bulk' })` on its own `Api`. A waiting
128
+ interactive call is granted first, so a reply never queues behind recipients;
129
+ the wait it can still see is the interval of the grant before it, up to one
130
+ album. Bulk runs at whatever rate replies leave, and the sum never exceeds
131
+ `messagesPerSecond`.
125
132
  - **The first send after idle is immediate; the rest are spaced.** This is a
126
133
  strict budget, not a bucket that saves a burst: at 24/s the next send is due
127
134
  one interval later. A 429 pauses the whole token; when it resumes, one send
@@ -133,8 +140,8 @@ cast, and a send cancelled in the queue then waits for its slot and fails as
133
140
  The refusal may be thrown or returned: a client transformer sits below the
134
141
  place where grammY turns Telegram's `{ ok: false, error_code: 429, … }` body into
135
142
  a `GrammyError`, so `run` reads that body too and hands it back unchanged.
136
- A 429 from an edit or a read is still a fact about the token and pauses later
137
- sends too. A network failure is rethrown unchanged and stays `unknown`; a 5xx
143
+ A 429 from an edit or a read concerns that call and pauses nothing; `budget.pauseAfter`
144
+ remains for a caller who decides otherwise. A network failure is rethrown unchanged and stays `unknown`; a 5xx
138
145
  is rethrown unchanged and stays `server-error`. Neither is retried by the
139
146
  budget or pauses the token — repeating a send whose outcome is unknown is a
140
147
  decision, not a primitive's silent guess.
@@ -608,7 +615,7 @@ injected grammY bot. → ADR 0143, ADR 0201, ADR 0274 — [guide](../guide/teleg
608
615
  | `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) |
609
616
  | `TelegramNotDispatchedError` / `TelegramNotDispatchedStage` | class / _type_ | a request that provably never left (`lookup`, `connect` or `request`), so repeating it cannot duplicate a message |
610
617
  | `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 |
611
- | `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 (a 429 pauses the token whether `send` throws it or resolves with the Bot API's `{ ok: false, … }` body), `pause`/`pauseAfter` for 429, `waitUntilResumed` for non-send retries and `stats`; it paces and never retries, and no public value carries the token |
618
+ | `telegramOutboundBudget` / `TelegramOutboundBudget` / `TelegramOutboundBudgetConfig` / `TelegramOutboundBudgetStats` / `TelegramOutboundCallOptions` / `TelegramOutboundLane` | 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, an `interactive` lane granted before `bulk`, `run(method, payload, signal, send, { lane })` as the transformer adapter (a 429 on a send pauses the token whether `send` throws it or resolves with the Bot API's `{ ok: false, … }` body), `pause`/`pauseAfter` for 429, `waitUntilResumed` for non-send retries and `stats`; it paces and never retries, and no public value carries the token |
612
619
  | `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 |
613
620
  | `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` |
614
621
  | `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 |
@@ -1,14 +1,37 @@
1
- # Upgrading 0.104.0 → 0.115.0 — stitchkit docs slice
1
+ # Upgrading 0.105.0 → 0.116.0 — stitchkit docs slice
2
2
 
3
3
  > Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
4
4
  > `llms.txt` in this package.
5
5
 
6
- Contains: Guide: Upgrading, 0.104.0 → 0.115.0 (docs/guide/upgrading.md)
6
+ Contains: Guide: Upgrading, 0.105.0 → 0.116.0 (docs/guide/upgrading.md)
7
7
 
8
8
  ==============================================================================
9
- # Guide: Upgrading, 0.104.0 → 0.115.0 (docs/guide/upgrading.md)
9
+ # Guide: Upgrading, 0.105.0 → 0.116.0 (docs/guide/upgrading.md)
10
10
  ==============================================================================
11
11
 
12
+ ## Released migration: 0.116.0
13
+
14
+ ### send-only-telegram-pause
15
+
16
+ **Who must act:** code that relied on a 429 from `editMessage*`, `deleteMessage` or a read to stop a
17
+ token's sends. Code that only sends needs no change.
18
+
19
+ `run` pauses the token only on a method that spends the budget
20
+ ([ADR 0277](../decisions/0277-a-telegram-budget-serves-replies-first.md)). Where an edit must still stop
21
+ the sends, say so:
22
+
23
+ ```ts
24
+ // before
25
+ await budget.run('editMessageText', payload, signal, send)
26
+ // after
27
+ await budget.run('editMessageText', payload, signal, send).catch((error) => {
28
+ budget.pauseAfter(error)
29
+ throw error
30
+ })
31
+ ```
32
+
33
+ Search pattern: `budget.run` next to edit and read methods.
34
+
12
35
  ## Released migration: 0.115.0
13
36
 
14
37
  ### contained-cli-downloads
@@ -794,124 +817,3 @@ in the second position is a type error.
794
817
 
795
818
  4. Both classes accept the standard `cause`, which `error.cause` returns; omit the option to
796
819
  leave the property absent.
797
-
798
- ## Released migration: 0.104.0
799
-
800
- JS bundles carrying Darwin native capabilities also need the
801
- [delivery migration first affected in 0.103.13](#released-migration-010313).
802
- Consumers upgrading from 0.103.12 or earlier must apply it even if their TypeScript API is unchanged.
803
-
804
- ### CLI runtime-tool construction
805
-
806
- **Who must act:** callers writing a schema-dependent handler or MCP/AI `present` directly
807
- inside an annotated `CliConfig.runtimeTools` or `CliInvokerConfig.runtimeTools` object.
808
- Native `commands` and values returned by `defineRuntimeTool` / `createRuntimeToolFactory`
809
- remain valid. Execution, auth, validation and the invocation result envelope keep their behavior.
810
-
811
- Construct a CLI-only managed definition with the neutral schema-aware type before registration:
812
-
813
- ```ts
814
- import type { CliInvokerConfig, RuntimeToolExecutionWithOutput } from 'stitchkit/cli'
815
- import { z } from 'zod'
816
-
817
- const input = z.object({ text: z.string() })
818
- const output = z.object({ size: z.number() })
819
- // Before: handler receives the heterogeneous registry context.
820
- const config: CliInvokerConfig = {
821
- name: 'app',
822
- runtimeTools: [{
823
- name: 'measure', description: 'Measure text',
824
- identity: { serviceName: 'text', action: 'measure', method: 'POST' },
825
- transports: ['CLI'], input, output,
826
- handler: ({ input }) => ({ size: String(input.text).length }),
827
- }],
828
- }
829
- // After: handler input and output derive from the construction schemas.
830
- const measure = {
831
- name: 'measure', description: 'Measure text',
832
- identity: { serviceName: 'text', action: 'measure', method: 'POST' },
833
- transports: ['CLI'], input, output,
834
- handler: ({ input }) => ({ size: input.text.length }),
835
- } satisfies RuntimeToolExecutionWithOutput<typeof input, typeof output>
836
- const nextConfig: CliInvokerConfig = { name: 'app', runtimeTools: [measure] }
837
- ```
838
-
839
- For a shared MCP/AI tool, construct the definition with `defineRuntimeTool` from
840
- `stitchkit/tools`, including its typed SDK `present` callbacks, then pass the returned value
841
- to `runtimeTools`. Install the corresponding SDK peers for that integration. A CLI-only
842
- consumer needs `stitchkit`, `zod` and its ordinary Node type tooling.
843
-
844
- `RuntimeToolExecution` names the heterogeneous registration contract. Call a registered
845
- operation through `createCli` or `createCliInvoker`; its erased handler input is `never`
846
- because the managed runner owns schema validation before execution. For a managed void
847
- definition, use `RuntimeToolDefinitionWithoutOutput<typeof input>`.
848
-
849
- ### MCP construction, state stores and delivery
850
-
851
- **Who must act:** schema-dependent runtime tool literals written directly inside MCP mount
852
- configuration, MCP presenters returning malformed content or metadata, custom `StateStore`
853
- implementations, file-store consumers using retired lock
854
- options, broadcast consumers reading `halt` or retrying unknown send outcomes, and consumers
855
- that validate HTTP error envelopes with a closed schema. Applications collecting raw tool
856
- causes from `console.error` must configure an internal tool hook sink.
857
-
858
- MCP-only code can import the existing server factories from `stitchkit/tools/mcp` and
859
- construct its schema-aware tool before heterogeneous registration:
860
-
861
- ```ts
862
- import { buildMcpServer, type RuntimeMcpToolDefinitionWithOutput } from 'stitchkit/tools/mcp'
863
- import { z } from 'zod'
864
- const input = z.object({ value: z.number() })
865
- const output = z.object({ doubled: z.number() })
866
- // Before: runtimeTools: [{ input, output, handler, present }]
867
- const double = {
868
- name: 'double', description: 'Double a number',
869
- identity: { serviceName: 'numbers', action: 'double', method: 'POST' },
870
- input, output,
871
- handler: ({ input }) => ({ doubled: input.value * 2 }),
872
- present: { mcp: ({ doubled }) => ({ content: [{ type: 'text', text: String(doubled) }] }) },
873
- } satisfies RuntimeMcpToolDefinitionWithOutput<typeof input, typeof output>
874
- const server = buildMcpServer({ serverInfo: { name: 'numbers', version: '1' }, services: [], runtimeTools: [double] })
875
- ```
876
-
877
- Full MCP/AI integrations keep `defineRuntimeTool` from `stitchkit/tools`; those typed values
878
- remain accepted by the MCP leaf and CLI. The leaf requires the MCP SDK and Zod, with no AI peer.
879
-
880
- `RuntimeMcpPresentation` preserves the official SDK's required `content` and typed `_meta`
881
- fields. A presenter returning `{}` must return `{ content: [] }`; text blocks require string
882
- text, and metadata must be an object. `structuredContent` and `isError` remain framework-owned.
883
- This restores SDK checks that an indexed mapped type previously erased.
884
-
885
- Unexpected tool causes remain in `hooks.onToolError` and the `error` field of
886
- `hooks.afterToolCall`. Protocol stderr carries safe errors. MCP resolver failures use those
887
- same observers without executing the handler or its lifecycle again. HTTP's default
888
- unexpected-error logging retains its behavior.
889
-
890
- A custom state adapter's `update` must invoke `transition(current, context)` while it still
891
- owns the serialized transaction. `context.assertHeld()` checks the actual transaction or lock
892
- generation and refuses after completion, rollback or ownership loss. A no-op guard cannot
893
- satisfy this contract. Existing transition callbacks may keep one parameter. For the owning
894
- file adapter, replace `{ staleLockMs, retryMs, lockTimeoutMs }` with `{ lockTimeoutMs }`:
895
- the remaining budget controls acquisition waiting, never expiry of a live transaction.
896
- Unknown legacy PID locks and historical temporary files are preserved; recover them only
897
- after independently proving their owner is gone.
898
-
899
- Broadcast consumers change `report.halt.reason` checks to the closed `halt.kind` union:
900
- `retry-after`, `transient`, `permanent` or `ambiguous`. A custom MTProto adapter can classify
901
- an acknowledged flood refusal as `{ kind: 'retry-after', retryAfterMs: wait }`; the exact
902
- provider wait is respected. A wait over `maxRetryDelayMs` halts with the recipient pending.
903
- Unknown write outcome becomes `uncertain`; restarting the same broadcast does not send it
904
- again. A retry classification must certify that the attempt did not apply the external effect.
905
-
906
- HTTP errors gain optional boolean `error.retryable`; framed contract streams use the same
907
- field. Update closed consumer schemas before producers declaring it. `false` on 502 and
908
- `true` on 409 remain explicit recommendations through the remote tool path. An absent field
909
- retains prior status-derived defaults; the field does not change the HTTP client's retry policy.
910
- The existing seventh `ApiError` constructor argument remains `ErrorOptions`; retryability is
911
- the new eighth argument.
912
-
913
- Caller cancellation now reaches `implementRemote`'s existing HTTP call. Applications bind
914
- signals to `createCli` / `createCliInvoker` and cooperative handlers observe `ctx.signal`.
915
- `REQUEST_ABORTED` is nonretryable and exits 130. A disconnected caller does not prove that
916
- an origin ignoring cancellation or an external provider stopped; keep resource leases until
917
- that work actually completes.
@@ -1,14 +1,131 @@
1
- # Upgrading 0.44.0 → 0.61.0 — stitchkit docs slice
1
+ # Upgrading 0.44.0 → 0.62.0 — stitchkit docs slice
2
2
 
3
3
  > Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
4
4
  > `llms.txt` in this package.
5
5
 
6
- Contains: Guide: Upgrading, 0.44.0 → 0.61.0 (docs/guide/upgrading.md)
6
+ Contains: Guide: Upgrading, 0.44.0 → 0.62.0 (docs/guide/upgrading.md)
7
7
 
8
8
  ==============================================================================
9
- # Guide: Upgrading, 0.44.0 → 0.61.0 (docs/guide/upgrading.md)
9
+ # Guide: Upgrading, 0.44.0 → 0.62.0 (docs/guide/upgrading.md)
10
10
  ==============================================================================
11
11
 
12
+ ## Released migration: 0.62.0
13
+
14
+ Two groups of behaviour changes. Nothing moves an export — the surface is
15
+ strictly additive — and every item changes what a running system reports or
16
+ sends, which is what this heading is for. One of them changes a number you may
17
+ already be billing against.
18
+
19
+ ### A run reports what it spent
20
+
21
+ Three changes to what the runtime says about cost and tokens. Nothing moves an
22
+ export; all three change numbers a running system reports, and one of them
23
+ changes a number you may already be billing against.
24
+
25
+ #### Multi-step cost was under-reported and is now summed
26
+
27
+ No code change is needed to get the fix — but check any predicate that reads
28
+ `provenance`:
29
+
30
+ ```ts
31
+ // before — accepted a number that was one step's cost, not the run's
32
+ if (usage.cost?.provenance === 'provider-reported') bill(usage.cost.value)
33
+
34
+ // after — a sum stitchkit performed says so
35
+ if (usage.cost && usage.cost.provenance !== 'unavailable') bill(usage.cost.value)
36
+ ```
37
+
38
+ `'computed'` means stitchkit added up provider-reported parts. It is not a guess
39
+ — `'estimated'` is the word for that — but it is deliberately not
40
+ `'provider-reported'`, because that label is what a caller filters on when it
41
+ wants a figure it can bill against unchanged, and a sum is not one.
42
+
43
+ Token totals moved with it. The AI SDK's `totalUsage` is a sum *it* performed
44
+ over per-step provider figures — not a run total any provider handed over — so
45
+ labelling it `provider-reported` was the same overstatement. **A run total on a
46
+ terminal event is always `computed`.** If you want a figure with the provider's
47
+ own word on it, read `step-finished`: each step carries what that call reported.
48
+
49
+ #### `usage` is always present on a terminal event
50
+
51
+ ```ts
52
+ // before — absent when the run ended before the provider's `finish`
53
+ const spent = event.usage?.cost?.value ?? 0 // silently 0 for a real spend
54
+
55
+ // after — present, and it says what it does not know
56
+ event.usage?.cost?.provenance === 'unavailable' // we spent, and cannot say how much
57
+ ```
58
+
59
+ Keep the optional chaining: one `AgentRunEvent` shape covers `run-started`,
60
+ `step-finished` and `run-terminal`, so `usage` stays optional on the type. The
61
+ guarantee is about terminal events, and a schema shared with `run-started`
62
+ cannot express it.
63
+
64
+ **Do not read `unavailable` as zero.** A run aborted mid-stream has spent real
65
+ money that nobody has counted; a run that never reached the provider has not.
66
+ Both used to look the same and now do not.
67
+
68
+ #### A losing executor reports its own spend
69
+
70
+ An execution that loses the terminal compare-and-swap now emits an operator
71
+ `run-terminal` event, because it ran and it spent. If a sink treated those events
72
+ as "runs this process committed", that is no longer true — `AgentRuntimeResult.metrics`
73
+ is still `undefined` for a losing executor and remains the way to tell.
74
+
75
+ The *delivery* `terminal` event is unchanged and still fires only for the winner,
76
+ so nothing delivers a turn twice.
77
+
78
+ ### An interrupted answer stops passing as a finished one
79
+
80
+ Two behaviour changes, one shared cause: a run ended by a newer input used to
81
+ leave its half-written answer in the conversation with no sign that it was cut
82
+ off, and the next request to the provider carried it as an ordinary assistant
83
+ turn.
84
+
85
+ #### The projection marks an interrupted turn
86
+
87
+ Nothing to change to adopt the fix — the default is the fixed behaviour. What to
88
+ check is whether the marker is the *right* form for your surface, and the
89
+ question that decides it is not "was the run interrupted" but **"did anyone see
90
+ what it produced"**.
91
+
92
+ ```ts
93
+ // after — pick the form; the default is 'assistant-marked'
94
+ createAgentRuntime({ history: { interruptedAssistant: 'system-note' } })
95
+ ```
96
+
97
+ - **The user pressed stop and the text was on their screen** — keep
98
+ `'assistant-marked'`. The assistant turn is the truthful record of what the
99
+ human read, and the model should stay consistent with it.
100
+ - **The partial never reached anyone** — a surface that sends nothing until the
101
+ run is done — prefer `'system-note'`. An assistant turn in provider history is
102
+ a commitment the model stays consistent with; a system line is context.
103
+
104
+ If you pass `history.project` you own the projection outright and none of this
105
+ applies — but the same question does.
106
+
107
+ #### A run ended by a newer input can now say so
108
+
109
+ ```ts
110
+ // before
111
+ runs: { inputPolicy: 'interrupt' } // ends the run, keeps its partial answer
112
+
113
+ // after — for a surface where a follow-up message invalidates the answer
114
+ // in flight rather than merely stopping it
115
+ runs: { inputPolicy: 'supersede' } // ends the run, discards its partial answer
116
+ ```
117
+
118
+ `inputPolicy` also accepts `(input) => policy`, which is how one application
119
+ gives two conversation surfaces different rules without the runtime learning
120
+ which is which.
121
+
122
+ A superseded run terminates with `terminalReason: 'superseded'`, state
123
+ `'superseded'` and an assistant message of status `'superseded'`. **If you switch
124
+ exhaustively on any of those enums, add the arm** — that is the part of this
125
+ release that can break a build rather than a behaviour. The record itself is
126
+ kept: it is excluded from the projection, not deleted, so an operator can still
127
+ see what was thrown away.
128
+
12
129
  ## Released migration: 0.61.0
13
130
 
14
131
  Three behaviour changes between versions. None moves an export — the surface is