stitchkit 0.111.0 → 0.111.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.
package/CHANGELOG.md CHANGED
@@ -15,6 +15,19 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
15
15
 
16
16
  ## [Unreleased]
17
17
 
18
+ ## [0.111.1] - 2026-10-17
19
+
20
+ ### Fixed
21
+
22
+ - `stitchkit/server` — **an open contract stream keeps a constant number of objects however many frames it sends.** Each frame raced the source against a promise that lived as long as the stream, so every frame left a reaction and the frame itself retained until the stream ended; a subscription sending a frame a second grew by about 1.6 MB a minute. The stream now waits for each frame through a listener it removes itself. A source that never has to wait is also stopped at the stream's `lifetimeMs`, which it used to outlive. → ADR 0264
23
+ **Affects:** `stitchkit/server` createServer, createHandler, implement
24
+ - `stitchkit/voice` — **`SpeechQueue` no longer keeps a reaction and the spoken clip for every sentence it has said.** → ADR 0264
25
+ **Affects:** `stitchkit/voice` SpeechQueue
26
+ - `stitchkit/tools/mcp` — **`createMcpHandler` no longer keeps the authenticated principal of every request it has answered until it is closed.** → ADR 0264
27
+ **Affects:** `stitchkit/tools/mcp` createMcpHandler
28
+ - `stitchkit/application/grammy` — **the update gate follows grammY's polling signal once instead of adding a listener on every `getUpdates`.** → ADR 0264
29
+ **Affects:** `stitchkit/application/grammy` behaviour
30
+
18
31
  ## [0.111.0] - 2026-10-17
19
32
 
20
33
  ### ⚠️ Breaking changes
@@ -1 +1 @@
1
- {"version":3,"file":"grammy-update-admission.d.ts","sourceRoot":"","sources":["../../src/application/grammy-update-admission.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAE3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,mBAAmB;IAClC,gGAAgG;IAChG,IAAI,CAAC,SAAS,EAAE,wBAAwB,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5D,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,6EAA6E;IAC7E,OAAO,IAAI,IAAI,CAAC;CACjB;AAsDD,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAmDvF"}
1
+ {"version":3,"file":"grammy-update-admission.d.ts","sourceRoot":"","sources":["../../src/application/grammy-update-admission.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAE3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,mBAAmB;IAClC,gGAAgG;IAChG,IAAI,CAAC,SAAS,EAAE,wBAAwB,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5D,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,6EAA6E;IAC7E,OAAO,IAAI,IAAI,CAAC;CACjB;AAiED,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAmDvF"}
@@ -21,7 +21,7 @@ import {
21
21
  import"../../index-zrtrjkbf.js";
22
22
  import {
23
23
  readBoundedBody2
24
- } from "../../index-qndsr7f0.js";
24
+ } from "../../index-5efrpfmj.js";
25
25
  import {
26
26
  MAX_TIMER_MS
27
27
  } from "../../index-eemvahkc.js";
@@ -15,7 +15,7 @@ function batchSize(result) {
15
15
  function abortError() {
16
16
  return new DOMException("Telegram polling stopped", "AbortError");
17
17
  }
18
- function untilAborted(signal) {
18
+ function untilNoLongerAdmitted(signal) {
19
19
  return new Promise((_, reject) => {
20
20
  if (signal.aborted)
21
21
  reject(abortError());
@@ -29,10 +29,19 @@ async function admitted(admission, signal) {
29
29
  } catch {
30
30
  if (signal.aborted)
31
31
  throw abortError();
32
- return untilAborted(signal);
32
+ return untilNoLongerAdmitted(signal);
33
33
  }
34
34
  }
35
+ var followers = new WeakMap;
35
36
  function followed(signal) {
37
+ const known = followers.get(signal);
38
+ if (known)
39
+ return known;
40
+ const follower = follow(signal);
41
+ followers.set(signal, follower);
42
+ return follower;
43
+ }
44
+ function follow(signal) {
36
45
  const controller = new AbortController;
37
46
  if (signal.aborted)
38
47
  controller.abort(abortError());
@@ -15,7 +15,7 @@ import {
15
15
  gzipCliAsset,
16
16
  decodeCliAsset,
17
17
  compareCliVersions2
18
- } from "../../index-kdnfe0sr.js";
18
+ } from "../../index-erv5shjq.js";
19
19
  import {
20
20
  withExclusiveLock2
21
21
  } from "../../index-w9mqgnz9.js";
@@ -16,7 +16,7 @@ import {
16
16
  renderCliView2,
17
17
  pollUntilDone2,
18
18
  createCli2
19
- } from "../index-syzngt7v.js";
19
+ } from "../index-v2eyj2ws.js";
20
20
  import"../index-fynr93w4.js";
21
21
  import"../index-ct75c3at.js";
22
22
  import"../index-q6crhe1n.js";
@@ -40,7 +40,7 @@ import {
40
40
  checkCliUpdate2,
41
41
  applyCliUpdate2,
42
42
  rollbackCliUpdate2
43
- } from "../index-kdnfe0sr.js";
43
+ } from "../index-erv5shjq.js";
44
44
  import {
45
45
  writeFileAtomicSync2
46
46
  } from "../index-07dcf2yn.js";
@@ -14,13 +14,13 @@ import {
14
14
  createUrlBuilder2,
15
15
  createUrlBuilders2,
16
16
  createScopedUrlBuilders2
17
- } from "../index-1y0arq4z.js";
17
+ } from "../index-c5at3ykd.js";
18
18
  import {
19
19
  ApiError2
20
20
  } from "../index-kfjkb396.js";
21
21
  import {
22
22
  readBoundedBody2
23
- } from "../index-qndsr7f0.js";
23
+ } from "../index-5efrpfmj.js";
24
24
  export {
25
25
  ApiError2 as ApiError,
26
26
  contractEndpointMatchers2 as contractEndpointMatchers,
@@ -71,7 +71,7 @@ import {
71
71
  createUrlBuilder2,
72
72
  createUrlBuilders2,
73
73
  createScopedUrlBuilders2
74
- } from "../index-1y0arq4z.js";
74
+ } from "../index-c5at3ykd.js";
75
75
  import {
76
76
  createRetainedTopics2,
77
77
  createRealtimeClientWithPeer,
@@ -85,7 +85,7 @@ import {
85
85
  } from "../index-kfjkb396.js";
86
86
  import {
87
87
  readBoundedBody2
88
- } from "../index-qndsr7f0.js";
88
+ } from "../index-5efrpfmj.js";
89
89
  import {
90
90
  sleep
91
91
  } from "../index-eemvahkc.js";
@@ -23,7 +23,7 @@ import {
23
23
  createSocketIOServer2,
24
24
  UnixClientTransportError2,
25
25
  createUnixClientTransport2
26
- } from "../index-krng2a5j.js";
26
+ } from "../index-2qymcsq2.js";
27
27
  import {
28
28
  bindRealtimeServer2
29
29
  } from "../index-xmgjtkvr.js";
@@ -4,7 +4,7 @@ import"../index-p6apg0jg.js";
4
4
  import {
5
5
  endpointHasArguments,
6
6
  createClient2
7
- } from "../index-1y0arq4z.js";
7
+ } from "../index-c5at3ykd.js";
8
8
  import {
9
9
  ApiError2
10
10
  } from "../index-kfjkb396.js";
@@ -49,7 +49,7 @@ import {
49
49
  socketIoLane2,
50
50
  UnixClientTransportError2,
51
51
  createUnixClientTransport2
52
- } from "../index-krng2a5j.js";
52
+ } from "../index-2qymcsq2.js";
53
53
  import {
54
54
  createFileStateStore2
55
55
  } from "../index-nx49x0tw.js";
@@ -86,7 +86,7 @@ import"../index-1bx1xv1k.js";
86
86
  import {
87
87
  readBoundedChunks,
88
88
  concatChunks
89
- } from "../index-qndsr7f0.js";
89
+ } from "../index-5efrpfmj.js";
90
90
  import {
91
91
  assertPositiveSafeInteger
92
92
  } from "../index-0s4xebbg.js";
@@ -26,15 +26,15 @@ import {
26
26
  MAX_TIMER_MS,
27
27
  sleep
28
28
  } from "../index-eemvahkc.js";
29
- import {
30
- untilAborted
31
- } from "../index-a5qr2rj6.js";
32
29
  import {
33
30
  assertPositiveSafeInteger
34
31
  } from "../index-0s4xebbg.js";
35
32
  import {
36
33
  BOT_TOKEN_SECRET
37
34
  } from "../index-sznqf8fx.js";
35
+ import {
36
+ untilAborted
37
+ } from "../index-a5qr2rj6.js";
38
38
  import {
39
39
  isRecord,
40
40
  transportResult
@@ -35,7 +35,7 @@ import"../index-fynr93w4.js";
35
35
  import {
36
36
  createClient2,
37
37
  createClients2
38
- } from "../index-1y0arq4z.js";
38
+ } from "../index-c5at3ykd.js";
39
39
  import {
40
40
  assertPositiveSafeInteger
41
41
  } from "../index-0s4xebbg.js";
@@ -16,7 +16,7 @@ import {
16
16
  import {
17
17
  readBoundedChunks,
18
18
  concatChunks
19
- } from "../../index-qndsr7f0.js";
19
+ } from "../../index-5efrpfmj.js";
20
20
  import {
21
21
  MAX_TIMER_MS
22
22
  } from "../../index-eemvahkc.js";
@@ -20,7 +20,7 @@ import {
20
20
  createMcpHttpRoute2,
21
21
  createStdioMcpServer2,
22
22
  bindStdioProcessSignals2
23
- } from "../../index-s2eybn7b.js";
23
+ } from "../../index-c5374vpt.js";
24
24
  import"../../index-0d8m0kee.js";
25
25
  import"../../index-636mggad.js";
26
26
  export {
@@ -60,7 +60,7 @@ import {
60
60
  createMcpHttpRoute2,
61
61
  createStdioMcpServer2,
62
62
  bindStdioProcessSignals2
63
- } from "../index-s2eybn7b.js";
63
+ } from "../index-c5374vpt.js";
64
64
  import {
65
65
  AsyncOperationCancelResultSchema2,
66
66
  createAsyncOperationSnapshotSchema2,
@@ -74,7 +74,7 @@ import {
74
74
  WaitTimeoutError,
75
75
  runWaitOperation,
76
76
  createCli2
77
- } from "../index-syzngt7v.js";
77
+ } from "../index-v2eyj2ws.js";
78
78
  import {
79
79
  ManagedFilePathSchema2,
80
80
  ManagedFileRefSchema2
@@ -97,12 +97,12 @@ import {
97
97
  fetchGuarded,
98
98
  fetchPinnedDocument,
99
99
  readCapped
100
- } from "../index-t65erk4z.js";
100
+ } from "../index-cxpcdswt.js";
101
101
  import"../index-1bx1xv1k.js";
102
102
  import {
103
103
  readBoundedChunks,
104
104
  concatChunks
105
- } from "../index-qndsr7f0.js";
105
+ } from "../index-5efrpfmj.js";
106
106
  import {
107
107
  assertPositiveSafeInteger
108
108
  } from "../index-0s4xebbg.js";
@@ -1,3 +1,7 @@
1
+ import {
2
+ untilAborted
3
+ } from "../index-a5qr2rj6.js";
4
+
1
5
  // src/voice/phases.ts
2
6
  var LIVE_VOICE_PHASES = [
3
7
  "opening",
@@ -99,10 +103,7 @@ class SpeechQueue {
99
103
  closed = false;
100
104
  cancelled = false;
101
105
  wake = null;
102
- stop;
103
- stopped = new Promise((resolve) => {
104
- this.stop = resolve;
105
- });
106
+ stopped = new AbortController;
106
107
  constructor(options) {
107
108
  this.options = options;
108
109
  const lookahead = options.lookahead ?? 1;
@@ -146,9 +147,16 @@ class SpeechQueue {
146
147
  this.release(outcome.value);
147
148
  });
148
149
  }
149
- this.stop(CANCELLED);
150
+ this.stopped.abort();
150
151
  this.notify();
151
152
  }
153
+ async unlessStopped(pending) {
154
+ try {
155
+ return await untilAborted(pending, this.stopped.signal);
156
+ } catch {
157
+ return CANCELLED;
158
+ }
159
+ }
152
160
  notify() {
153
161
  this.wake?.();
154
162
  }
@@ -179,19 +187,18 @@ class SpeechQueue {
179
187
  }
180
188
  this.current = slot;
181
189
  try {
182
- const prepared = await Promise.race([slot.result, this.stopped]);
190
+ const prepared = await this.unlessStopped(slot.result);
183
191
  if (prepared === CANCELLED)
184
192
  return;
185
193
  if (!prepared.ok) {
186
194
  this.report(prepared.error, slot.text);
187
195
  continue;
188
196
  }
197
+ if (this.cancelled)
198
+ return;
189
199
  this.playing = true;
190
200
  this.fill();
191
- const played = await Promise.race([
192
- settle(() => this.options.play(prepared.value, slot.controller.signal)),
193
- this.stopped
194
- ]);
201
+ const played = await this.unlessStopped(settle(() => this.options.play(prepared.value, slot.controller.signal)));
195
202
  if (played === CANCELLED)
196
203
  return;
197
204
  if (!played.ok)
@@ -31,10 +31,7 @@ import {
31
31
  readBoundedChunks,
32
32
  concatChunks,
33
33
  readBoundedBody2
34
- } from "./index-qndsr7f0.js";
35
- import {
36
- abortReason
37
- } from "./index-a5qr2rj6.js";
34
+ } from "./index-5efrpfmj.js";
38
35
  import {
39
36
  assertPositiveSafeInteger
40
37
  } from "./index-0s4xebbg.js";
@@ -62,6 +59,10 @@ import {
62
59
  getClientInfo2,
63
60
  parseQueryParams
64
61
  } from "./index-kw1ws0cs.js";
62
+ import {
63
+ abortReason,
64
+ untilAborted
65
+ } from "./index-a5qr2rj6.js";
65
66
  import {
66
67
  isUnsafeKey,
67
68
  safeJsonParse
@@ -1001,15 +1002,6 @@ function encodedBytes(value, format) {
1001
1002
  `;
1002
1003
  return new TextEncoder().encode(framing).byteLength;
1003
1004
  }
1004
- function waitForAbort(signal) {
1005
- return new Promise((_resolve, reject) => {
1006
- const rejectAborted = () => reject(signal.reason ?? new Error("Stream aborted"));
1007
- if (signal.aborted)
1008
- rejectAborted();
1009
- else
1010
- signal.addEventListener("abort", rejectAborted, { once: true });
1011
- });
1012
- }
1013
1005
  function contractStreamResponse(request, context, source, descriptor, operationAbort) {
1014
1006
  const format = descriptor.format ?? "ndjson";
1015
1007
  const maxFrameBytes = descriptor.maxFrameBytes ?? DEFAULT_CONTRACT_STREAM_FRAME_BYTES2;
@@ -1048,12 +1040,11 @@ function contractStreamResponse(request, context, source, descriptor, operationA
1048
1040
  const frames = async function* () {
1049
1041
  if (closing)
1050
1042
  return;
1051
- const aborted = waitForAbort(operationAbort.signal);
1052
1043
  let terminalSeen = descriptor.terminal === undefined;
1053
1044
  try {
1054
1045
  for (;; ) {
1055
1046
  pendingNext = Promise.resolve(iterator.next());
1056
- const next = await Promise.race([pendingNext, aborted]);
1047
+ const next = await untilAborted(pendingNext, operationAbort.signal);
1057
1048
  if (next.done)
1058
1049
  break;
1059
1050
  const parsed = descriptor.item.safeParse(next.value);
@@ -36,6 +36,9 @@ import {
36
36
  runWithRequestContext2,
37
37
  getRequestContext2
38
38
  } from "./index-r6v4mc67.js";
39
+ import {
40
+ untilAborted
41
+ } from "./index-a5qr2rj6.js";
39
42
  import {
40
43
  AppError2
41
44
  } from "./index-j9gxbztg.js";
@@ -971,10 +974,7 @@ function createMcpHandler2(config) {
971
974
  const buildPrepared = prepareStaticSurface(config);
972
975
  const authByCarrier = new WeakMap;
973
976
  let closed = false;
974
- let resolveClosed;
975
- const closedSignal = new Promise((resolve) => {
976
- resolveClosed = resolve;
977
- });
977
+ const closing = new AbortController;
978
978
  const sdkHandler = createSdkMcpHandler(({ authInfo }) => {
979
979
  const resolved = authInfo ? authByCarrier.get(authInfo) : undefined;
980
980
  if (!resolved) {
@@ -1011,10 +1011,11 @@ function createMcpHandler2(config) {
1011
1011
  const originRejection = originValidationResponse(request, [...allowedOrigins]);
1012
1012
  if (originRejection)
1013
1013
  return observeRejection(request, originRejection);
1014
- const auth = await Promise.race([
1015
- Promise.resolve(config.auth(request)),
1016
- closedSignal.then(() => null)
1017
- ]);
1014
+ const auth = await untilAborted(Promise.resolve(config.auth(request)), closing.signal).catch((error) => {
1015
+ if (closing.signal.aborted)
1016
+ return null;
1017
+ throw error;
1018
+ });
1018
1019
  if (closed) {
1019
1020
  return observeRejection(request, jsonRpcError(-32000, "MCP handler is closed", 503));
1020
1021
  }
@@ -1036,7 +1037,7 @@ function createMcpHandler2(config) {
1036
1037
  if (closed)
1037
1038
  return;
1038
1039
  closed = true;
1039
- resolveClosed?.();
1040
+ closing.abort();
1040
1041
  await sdkHandler.close();
1041
1042
  }
1042
1043
  };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./index-b0kddvzw.js";
4
4
  import {
5
5
  readBoundedChunks
6
- } from "./index-qndsr7f0.js";
6
+ } from "./index-5efrpfmj.js";
7
7
 
8
8
  // src/internal/secure-fetch.ts
9
9
  import { lookup } from "node:dns/promises";
@@ -5,7 +5,7 @@ import {
5
5
  fetchGuarded,
6
6
  PrivateAddressRefusal,
7
7
  readCapped
8
- } from "./index-t65erk4z.js";
8
+ } from "./index-cxpcdswt.js";
9
9
  import {
10
10
  writeFileAtomicSync2
11
11
  } from "./index-07dcf2yn.js";
@@ -26,7 +26,7 @@ import {
26
26
  import {
27
27
  fetchGuarded,
28
28
  readCapped
29
- } from "./index-t65erk4z.js";
29
+ } from "./index-cxpcdswt.js";
30
30
  import {
31
31
  isWithinDir2
32
32
  } from "./index-5cc6r990.js";
@@ -1 +1 @@
1
- {"version":3,"file":"contract-stream.d.ts","sourceRoot":"","sources":["../../src/server/contract-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAUnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAiB/C,gEAAgE;AAChE,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,EAC9B,UAAU,EAAE,wBAAwB,EACpC,cAAc,EAAE,eAAe,GAC9B,OAAO,CAAC,QAAQ,CAAC,CAgHnB"}
1
+ {"version":3,"file":"contract-stream.d.ts","sourceRoot":"","sources":["../../src/server/contract-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAWnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAS/C,gEAAgE;AAChE,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,EAC9B,UAAU,EAAE,wBAAwB,EACpC,cAAc,EAAE,eAAe,GAC9B,OAAO,CAAC,QAAQ,CAAC,CA+GnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/tools/mcp/handler.ts"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,uBAAuB,EAE7B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,WAAW,CAAC;AAEnB,yEAAyE;AACzE,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEjD,2EAA2E;AAC3E,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,+EAA+E;IAC/E,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa,CAAC,KAAK;IAClC,uEAAuE;IACvE,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC7D,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;IAC5C,wEAAwE;IACxE,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,sFAAsF;IACtF,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAC5B,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,QAAQ,CAAC;KACpB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAC1B,KAAK,EACL,SAAS,SAAS,kBAAkB,GAAG,kBAAkB,IACvD,oBAAoB,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;AAElE,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAgFD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EACL,KAAK,CAAC,SAAS,SAAS,kBAAkB,GAAG,kBAAkB,EAC/D,MAAM,EAAE,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,cAAc,CAkF5D;AAED,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,cAAc,CAAC;CACzB,GAAG,QAAQ,CAMX"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/tools/mcp/handler.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,KAAK,uBAAuB,EAE7B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,WAAW,CAAC;AAEnB,yEAAyE;AACzE,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEjD,2EAA2E;AAC3E,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,+EAA+E;IAC/E,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa,CAAC,KAAK;IAClC,uEAAuE;IACvE,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC7D,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;IAC5C,wEAAwE;IACxE,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,sFAAsF;IACtF,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAC5B,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,QAAQ,CAAC;KACpB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAC1B,KAAK,EACL,SAAS,SAAS,kBAAkB,GAAG,kBAAkB,IACvD,oBAAoB,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;AAElE,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAgFD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EACL,KAAK,CAAC,SAAS,SAAS,kBAAkB,GAAG,kBAAkB,EAC/D,MAAM,EAAE,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,cAAc,CAoF5D;AAED,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,cAAc,CAAC;CACzB,GAAG,QAAQ,CAMX"}
@@ -21,7 +21,6 @@ export declare class SpeechQueue<Prepared> {
21
21
  private closed;
22
22
  private cancelled;
23
23
  private wake;
24
- private stop;
25
24
  private readonly stopped;
26
25
  constructor(options: SpeechQueueOptions<Prepared>);
27
26
  get isCancelled(): boolean;
@@ -32,6 +31,12 @@ export declare class SpeechQueue<Prepared> {
32
31
  close(): void;
33
32
  /** Interrupted: abort the sentence playing and every synthesis, drop the rest. */
34
33
  cancel(): void;
34
+ /**
35
+ * `pending`, or `CANCELLED` once the queue is cancelled. The wait owns its listener and
36
+ * releases it when `pending` settles: a promise shared by every sentence would keep one
37
+ * reaction per sentence for as long as the queue lives. `pending` never rejects.
38
+ */
39
+ private unlessStopped;
35
40
  private notify;
36
41
  /** Start synthesis up to the lookahead: the sentence playing or next, plus `lookahead`. */
37
42
  private fill;
@@ -1 +1 @@
1
- {"version":3,"file":"speech-queue.d.ts","sourceRoot":"","sources":["../../src/voice/speech-queue.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,kBAAkB,CAAC,QAAQ;IAC1C,oEAAoE;IACpE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE,kFAAkF;IAClF,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,6FAA6F;IAC7F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,uFAAuF;IACvF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;CACxC;AAqBD,qBAAa,WAAW,CAAC,QAAQ;IAenB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAdpC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAC9C,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,IAAI,CAAqC;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAErB;IAEH,YAA6B,OAAO,EAAE,kBAAkB,CAAC,QAAQ,CAAC,EAOjE;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,sFAAsF;IACtF,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKvB;IAED,yDAAyD;IACzD,KAAK,IAAI,IAAI,CAGZ;IAED,kFAAkF;IAClF,MAAM,IAAI,IAAI,CAgBb;IAED,OAAO,CAAC,MAAM;IAId,2FAA2F;IAC3F,OAAO,CAAC,IAAI;YAaE,GAAG;IAmCjB,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,OAAO;CAOhB"}
1
+ {"version":3,"file":"speech-queue.d.ts","sourceRoot":"","sources":["../../src/voice/speech-queue.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,kBAAkB,CAAC,QAAQ;IAC1C,oEAAoE;IACpE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE,kFAAkF;IAClF,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,6FAA6F;IAC7F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,uFAAuF;IACvF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;CACxC;AAqBD,qBAAa,WAAW,CAAC,QAAQ;IAYnB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAXpC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAC9C,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IAEjD,YAA6B,OAAO,EAAE,kBAAkB,CAAC,QAAQ,CAAC,EAOjE;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,sFAAsF;IACtF,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKvB;IAED,yDAAyD;IACzD,KAAK,IAAI,IAAI,CAGZ;IAED,kFAAkF;IAClF,MAAM,IAAI,IAAI,CAgBb;IAED;;;;OAIG;YACW,aAAa;IAQ3B,OAAO,CAAC,MAAM;IAId,2FAA2F;IAC3F,OAAO,CAAC,IAAI;YAaE,GAAG;IAoCjB,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,OAAO;CAOhB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.111.0",
3
+ "version": "0.111.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",
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  chunksOf
3
3
  } from "./index-cjbn98zt.js";
4
- import {
5
- abortReason
6
- } from "./index-a5qr2rj6.js";
7
4
  import {
8
5
  assertPositiveSafeInteger
9
6
  } from "./index-0s4xebbg.js";
7
+ import {
8
+ abortReason
9
+ } from "./index-a5qr2rj6.js";
10
10
 
11
11
  // src/internal/bounded-body.ts
12
12
  async function readBoundedChunks(source, options) {
File without changes