@langchain/langgraph-sdk 1.9.29 → 1.9.31

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.
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.cts","names":[],"sources":["../../src/stream/controller.ts"],"mappings":";;;;;;;;;;;;;;AA6KA;;cAAa,kBAAA,WAA6B,OAAA;;AAkC1C;;;;;;;;;;;;cAAa,gBAAA,4BACgB,MAAA,8EAEO,MAAA;EAAA;WAEzB,SAAA,EAAW,WAAA,CAAY,YAAA,CAAa,SAAA,EAAW,aAAA;EAAA,SAC/C,aAAA,EAAe,WAAA,CAAY,WAAA;EAAA,SAC3B,aAAA,EAAe,WAAA,CAAY,WAAA;EAAA,SAC3B,mBAAA,EAAqB,WAAA,CAAY,iBAAA;EAAA,SACjC,oBAAA,EAAsB,WAAA,CAAY,kBAAA;EAAA,SAClC,UAAA,EAAY,WAAA,CAAY,uBAAA,CAAwB,SAAA;EAAA,SAChD,QAAA,EAAU,eAAA;EAgI0B;;;;;EAA7C,WAAA,CAAY,OAAA,EAAS,uBAAA,CAAwB,SAAA;EAsyBF;;;;;;;EAAA,IAvrBvC,gBAAA,CAAA,GAAoB,OAAA;EA41BS;;;;;;;;EAnyB3B,OAAA,CAAQ,QAAA,mBAA2B,OAAA;EAihCpB;;;;;;;;;;;;;;EAzpBf,wBAAA,CAAyB,UAAA,WAAqB,OAAA;EArqB5B;;;;;;;;EAy6BlB,MAAA,CACJ,KAAA,WACA,OAAA,GAAU,mBAAA,CAAoB,SAAA,EAAW,gBAAA,IACxC,OAAA;EAz6B4B;;;;;;EAm7BzB,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EAj7BtB;;;;EAq8Bb,UAAA,CAAA,GAAc,OAAA;EAttBhB;;;;;;;;;;;EAsxBE,YAAA,CAAa,EAAA,WAAa,OAAA;EA/FW;;;EAsGrC,UAAA,CAAA,GAAc,OAAA;EA3FC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwJf,OAAA,CACJ,QAAA,WACA,OAAA,GAAU,oBAAA,CAAqB,gBAAA,IAC9B,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+GG,UAAA,CACJ,aAAA,EAAe,MAAA,mBACf,OAAA,GAAU,uBAAA,CAAwB,gBAAA,IACjC,OAAA;;;;EA0DG,OAAA,CAAA,GAAW,OAAA;;;;;;;;;;;;;;;;EAyBjB,QAAA,CAAA;;;;;;EA4BA,SAAA,CAAA,GAAa,YAAA;;;;;;;;EAWb,eAAA,CACE,QAAA,GAAW,MAAA,EAAQ,YAAA;AAAA"}
1
+ {"version":3,"file":"controller.d.cts","names":[],"sources":["../../src/stream/controller.ts"],"mappings":";;;;;;;;;;;;;;AA6KA;;cAAa,kBAAA,WAA6B,OAAA;;AAkC1C;;;;;;;;;;;;cAAa,gBAAA,4BACgB,MAAA,8EAEO,MAAA;EAAA;WAEzB,SAAA,EAAW,WAAA,CAAY,YAAA,CAAa,SAAA,EAAW,aAAA;EAAA,SAC/C,aAAA,EAAe,WAAA,CAAY,WAAA;EAAA,SAC3B,aAAA,EAAe,WAAA,CAAY,WAAA;EAAA,SAC3B,mBAAA,EAAqB,WAAA,CAAY,iBAAA;EAAA,SACjC,oBAAA,EAAsB,WAAA,CAAY,kBAAA;EAAA,SAClC,UAAA,EAAY,WAAA,CAAY,uBAAA,CAAwB,SAAA;EAAA,SAChD,QAAA,EAAU,eAAA;EAqJ0B;;;;;EAA7C,WAAA,CAAY,OAAA,EAAS,uBAAA,CAAwB,SAAA;EAszBF;;;;;;;EAAA,IA5rBvC,gBAAA,CAAA,GAAoB,OAAA;EAi2BS;;;;;;;;EAxyB3B,OAAA,CAAQ,QAAA,mBAA2B,OAAA;EA0hCpB;;;;;;;;;;;;;;EA7pBf,wBAAA,CAAyB,UAAA,WAAqB,OAAA;EA1sB5B;;;;;;;;EA88BlB,MAAA,CACJ,KAAA,WACA,OAAA,GAAU,mBAAA,CAAoB,SAAA,EAAW,gBAAA,IACxC,OAAA;EA98B4B;;;;;;EAw9BzB,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EAt9BtB;;;;EA0+Bb,UAAA,CAAA,GAAc,OAAA;EA3tBhB;;;;;;;;;;;EA2xBE,YAAA,CAAa,EAAA,WAAa,OAAA;EA/FW;;;EAsGrC,UAAA,CAAA,GAAc,OAAA;EA3FC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwJf,OAAA,CACJ,QAAA,WACA,OAAA,GAAU,oBAAA,CAAqB,gBAAA,IAC9B,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiHG,UAAA,CACJ,aAAA,EAAe,MAAA,mBACf,OAAA,GAAU,uBAAA,CAAwB,gBAAA,IACjC,OAAA;;;;EA4DG,OAAA,CAAA,GAAW,OAAA;;;;;;;;;;;;;;;;EAyBjB,QAAA,CAAA;;;;;;EA4BA,SAAA,CAAA,GAAa,YAAA;;;;;;;;EAWb,eAAA,CACE,QAAA,GAAW,MAAA,EAAQ,YAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","names":[],"sources":["../../src/stream/controller.ts"],"mappings":";;;;;;;;;;;;;;;AA6KA;cAAa,kBAAA,WAA6B,OAAA;;;AAkC1C;;;;;;;;;;;cAAa,gBAAA,4BACgB,MAAA,8EAEO,MAAA;EAAA;WAEzB,SAAA,EAAW,WAAA,CAAY,YAAA,CAAa,SAAA,EAAW,aAAA;EAAA,SAC/C,aAAA,EAAe,WAAA,CAAY,WAAA;EAAA,SAC3B,aAAA,EAAe,WAAA,CAAY,WAAA;EAAA,SAC3B,mBAAA,EAAqB,WAAA,CAAY,iBAAA;EAAA,SACjC,oBAAA,EAAsB,WAAA,CAAY,kBAAA;EAAA,SAClC,UAAA,EAAY,WAAA,CAAY,uBAAA,CAAwB,SAAA;EAAA,SAChD,QAAA,EAAU,eAAA;EAAA;;;;;EAgInB,WAAA,CAAY,OAAA,EAAS,uBAAA,CAAwB,SAAA;EAsyBb;;;;;;;EAAA,IAvrB5B,gBAAA,CAAA,GAAoB,OAAA;EA6xBJ;;;;;;;;EApuBd,OAAA,CAAQ,QAAA,mBAA2B,OAAA;EAqgC5B;;;;;;;;;;;;;;EA7oBP,wBAAA,CAAyB,UAAA,WAAqB,OAAA;EArqB3C;;;;;;;;EAy6BH,MAAA,CACJ,KAAA,WACA,OAAA,GAAU,mBAAA,CAAoB,SAAA,EAAW,gBAAA,IACxC,OAAA;EAz6BM;;;;;;EAm7BH,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EAj7BhC;;;;EAq8BH,UAAA,CAAA,GAAc,OAAA;EAr0BR;;;;;;;;;;;EAq4BN,YAAA,CAAa,EAAA,WAAa,OAAA;EA/FA;;;EAsG1B,UAAA,CAAA,GAAc,OAAA;EA3Fd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwJA,OAAA,CACJ,QAAA,WACA,OAAA,GAAU,oBAAA,CAAqB,gBAAA,IAC9B,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+GG,UAAA,CACJ,aAAA,EAAe,MAAA,mBACf,OAAA,GAAU,uBAAA,CAAwB,gBAAA,IACjC,OAAA;;;;EA0DG,OAAA,CAAA,GAAW,OAAA;;;;;;;;;;;;;;;;EAyBjB,QAAA,CAAA;;;;;;EA4BA,SAAA,CAAA,GAAa,YAAA;;;;;;;;EAWb,eAAA,CACE,QAAA,GAAW,MAAA,EAAQ,YAAA;AAAA"}
1
+ {"version":3,"file":"controller.d.ts","names":[],"sources":["../../src/stream/controller.ts"],"mappings":";;;;;;;;;;;;;;;AA6KA;cAAa,kBAAA,WAA6B,OAAA;;;AAkC1C;;;;;;;;;;;cAAa,gBAAA,4BACgB,MAAA,8EAEO,MAAA;EAAA;WAEzB,SAAA,EAAW,WAAA,CAAY,YAAA,CAAa,SAAA,EAAW,aAAA;EAAA,SAC/C,aAAA,EAAe,WAAA,CAAY,WAAA;EAAA,SAC3B,aAAA,EAAe,WAAA,CAAY,WAAA;EAAA,SAC3B,mBAAA,EAAqB,WAAA,CAAY,iBAAA;EAAA,SACjC,oBAAA,EAAsB,WAAA,CAAY,kBAAA;EAAA,SAClC,UAAA,EAAY,WAAA,CAAY,uBAAA,CAAwB,SAAA;EAAA,SAChD,QAAA,EAAU,eAAA;EAAA;;;;;EAqJnB,WAAA,CAAY,OAAA,EAAS,uBAAA,CAAwB,SAAA;EAszBb;;;;;;;EAAA,IA5rB5B,gBAAA,CAAA,GAAoB,OAAA;EAkyBJ;;;;;;;;EAzuBd,OAAA,CAAQ,QAAA,mBAA2B,OAAA;EA8gC5B;;;;;;;;;;;;;;EAjpBP,wBAAA,CAAyB,UAAA,WAAqB,OAAA;EA1sB3C;;;;;;;;EA88BH,MAAA,CACJ,KAAA,WACA,OAAA,GAAU,mBAAA,CAAoB,SAAA,EAAW,gBAAA,IACxC,OAAA;EA98BM;;;;;;EAw9BH,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EAt9BhC;;;;EA0+BH,UAAA,CAAA,GAAc,OAAA;EAr1BR;;;;;;;;;;;EAq5BN,YAAA,CAAa,EAAA,WAAa,OAAA;EA/FA;;;EAsG1B,UAAA,CAAA,GAAc,OAAA;EA3Fd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwJA,OAAA,CACJ,QAAA,WACA,OAAA,GAAU,oBAAA,CAAqB,gBAAA,IAC9B,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiHG,UAAA,CACJ,aAAA,EAAe,MAAA,mBACf,OAAA,GAAU,uBAAA,CAAwB,gBAAA,IACjC,OAAA;;;;EA4DG,OAAA,CAAA,GAAW,OAAA;;;;;;;;;;;;;;;;EAyBjB,QAAA,CAAA;;;;;;EA4BA,SAAA,CAAA,GAAa,YAAA;;;;;;;;EAWb,eAAA,CACE,QAAA,GAAW,MAAA,EAAQ,YAAA;AAAA"}
@@ -154,12 +154,25 @@ var StreamController = class {
154
154
  * SSE replay re-adds historically-requested interrupts that have
155
155
  * since been resolved (no `input.responded` event exists in the
156
156
  * protocol, so the SDK has no other way to tell replay from live
157
- * for an idle thread). `null` outside the hydrate-window so
158
- * genuinely new live interrupts on an active run aren't filtered;
159
- * cleared at the start of `submit()` for the same reason.
157
+ * for an idle thread). After a command is accepted, events newer
158
+ * than {@link #interruptReplayThroughSeq} bypass the allowlist.
160
159
  */
161
160
  #hydratedActiveInterruptIds = null;
162
161
  /**
162
+ * Highest event sequence already applied when the latest run command
163
+ * was accepted. Interrupts outside the hydrate-time allowlist remain
164
+ * filtered through this sequence, while newer events are live output
165
+ * from the newly-started run and must be accepted.
166
+ */
167
+ #interruptReplayThroughSeq;
168
+ /**
169
+ * Unknown interrupt events received between local command dispatch and its
170
+ * response. The response supplies the sequence barrier needed to classify
171
+ * each event as historical replay or live output from the new run.
172
+ */
173
+ #pendingInterruptEvents = [];
174
+ #interruptCommandPending = false;
175
+ /**
163
176
  * Monotonic counter bumped at the start of each `submit()` and used
164
177
  * by {@link hydrate} to skip its post-fetch allowlist write when a
165
178
  * submit started while the state fetch was in flight. Without this
@@ -169,6 +182,14 @@ var StreamController = class {
169
182
  */
170
183
  #submitGeneration = 0;
171
184
  /**
185
+ * Monotonic counter bumped at the start of each `#teardownThread`.
186
+ * The root pump captures the generation when it starts and drops
187
+ * any event whose generation no longer matches — including queued
188
+ * events that `SubscriptionHandle.close()` still drains after the
189
+ * snapshot has already been cleared by `hydrate()`.
190
+ */
191
+ #rootPumpGeneration = 0;
192
+ /**
172
193
  * Thread ids this controller minted client-side on first `submit()`.
173
194
  * `hydrate()` skips `threads.getState()` for these — we know there
174
195
  * is nothing checkpointed yet. Cleared once dispatch commits the
@@ -293,13 +314,20 @@ var StreamController = class {
293
314
  awaitNextTerminal: (signal) => this.#awaitNextTerminal(signal),
294
315
  awaitResumedRunTerminal: (signal) => this.#awaitResumedRunTerminal(signal),
295
316
  onSubmitStart: () => {
296
- this.#hydratedActiveInterruptIds = null;
297
317
  this.#submitGeneration += 1;
318
+ this.#interruptCommandPending = this.#hydratedActiveInterruptIds != null;
319
+ this.#pendingInterruptEvents = [];
298
320
  },
299
321
  onRunStart: () => this.#markLocalRunStart(),
300
- onRunCreated: (runId) => this.#notifyCreated(runId),
322
+ onRunCreated: (runId) => {
323
+ this.#advanceInterruptReplayBarrier();
324
+ this.#notifyCreated(runId);
325
+ },
301
326
  onRunCompleted: (reason, runId) => this.#notifyCompleted(reason, runId),
302
- onRunEnd: () => this.#markLocalRunEnd(),
327
+ onRunEnd: () => {
328
+ this.#interruptCommandPending = false;
329
+ this.#markLocalRunEnd();
330
+ },
303
331
  beginOptimistic: (input) => this.#beginOptimistic(input),
304
332
  settleOptimistic: (handle, event) => this.#settleOptimistic(handle, event)
305
333
  });
@@ -391,13 +419,16 @@ var StreamController = class {
391
419
  * Suspense boundary remounted against the new id suspends again.
392
420
  */
393
421
  this.#resetHydrationPromise();
394
- await this.#teardownThread();
395
422
  /**
396
- * Reset UI-facing snapshot so stale messages/values/tool-calls
397
- * from the previous thread don't bleed into the new one. The
398
- * new thread's state (if any) is then populated below via
399
- * `#applyValues`.
423
+ * Kick teardown so the synchronous abort (unbind, drop onEvent,
424
+ * close the root subscription, reset assemblers) runs before we
425
+ * touch the snapshot. Then reset immediately so the UI does not
426
+ * wait on pump/close. An interrupted thread parks the root pump
427
+ * on `waitForResume()`; awaiting teardown *before* this reset
428
+ * left `threadId` null while `messages` still showed the previous
429
+ * conversation (`useStream` fire-and-forgets `hydrate()`).
400
430
  */
431
+ const teardown = this.#teardownThread();
401
432
  this.rootStore.setState(() => ({
402
433
  ...this.#createInitialSnapshot(),
403
434
  threadId: this.#currentThreadId
@@ -408,6 +439,7 @@ var StreamController = class {
408
439
  * surprising. Mirrors the legacy `StreamOrchestrator` behaviour.
409
440
  */
410
441
  this.queueStore.setState(() => EMPTY_QUEUE);
442
+ await teardown;
411
443
  }
412
444
  if (this.#currentThreadId == null) {
413
445
  this.rootStore.setState((s) => ({
@@ -549,7 +581,10 @@ var StreamController = class {
549
581
  interrupts: activeInterrupts,
550
582
  interrupt: activeInterrupts[0]
551
583
  }));
552
- if (this.#submitGeneration === generationAtFetch) this.#hydratedActiveInterruptIds = activeIds;
584
+ if (this.#submitGeneration === generationAtFetch) {
585
+ this.#hydratedActiveInterruptIds = activeIds;
586
+ this.#interruptReplayThroughSeq = void 0;
587
+ }
553
588
  }
554
589
  } catch (error) {
555
590
  if (error?.status !== 404) {
@@ -996,9 +1031,11 @@ var StreamController = class {
996
1031
  config: options?.config,
997
1032
  metadata: options?.metadata
998
1033
  });
1034
+ this.#advanceInterruptReplayBarrier();
999
1035
  this.#markInterruptResolvedInRootStore(resolved.interruptId);
1000
1036
  }, prepared?.handle);
1001
1037
  } catch (error) {
1038
+ this.#discardPendingInterruptEvents();
1002
1039
  if (this.#disposed && isAbortLikeError(error)) return;
1003
1040
  throw error;
1004
1041
  }
@@ -1065,9 +1102,11 @@ var StreamController = class {
1065
1102
  config: options?.config,
1066
1103
  metadata: options?.metadata
1067
1104
  });
1105
+ this.#advanceInterruptReplayBarrier();
1068
1106
  for (const { interrupt_id: interruptId } of responses) this.#markInterruptResolvedInRootStore(interruptId);
1069
1107
  }, prepared?.handle);
1070
1108
  } catch (error) {
1109
+ this.#discardPendingInterruptEvents();
1071
1110
  if (this.#disposed && isAbortLikeError(error)) return;
1072
1111
  throw error;
1073
1112
  }
@@ -1235,6 +1274,14 @@ var StreamController = class {
1235
1274
  * Close the current thread stream and reset per-thread assembly state.
1236
1275
  */
1237
1276
  async #teardownThread() {
1277
+ /**
1278
+ * Invalidate the in-flight root pump before `close()` unparks it.
1279
+ * `SubscriptionHandle.close()` leaves queued events intact and the
1280
+ * iterator drains them before observing `closed`, so without this
1281
+ * bump a parked interrupted pump would still dispatch stale
1282
+ * `values` / `messages` into a snapshot `hydrate()` already cleared.
1283
+ */
1284
+ this.#rootPumpGeneration += 1;
1238
1285
  const thread = this.#thread;
1239
1286
  this.#thread = void 0;
1240
1287
  this.registry.bind(void 0);
@@ -1247,16 +1294,16 @@ var StreamController = class {
1247
1294
  */
1248
1295
  this.#rootEventListeners.delete(this.#lifecycleLoading.listener);
1249
1296
  this.#rootEventListeners.delete(this.#runLifecycleListener);
1250
- try {
1251
- await this.#rootSubscription?.unsubscribe();
1252
- } catch {}
1297
+ /**
1298
+ * Close first so a pump parked on `waitForResume()` (interrupted
1299
+ * run) unparks even if the unsubscribe RPC is slow. `close()` is
1300
+ * idempotent; `unsubscribe()` is then a no-op once closed.
1301
+ */
1302
+ const subscription = this.#rootSubscription;
1253
1303
  this.#rootSubscription = void 0;
1304
+ subscription?.close();
1254
1305
  this.#rootPumpReady = void 0;
1255
1306
  this.#rootPumpDeferred = false;
1256
- try {
1257
- await this.#rootPump;
1258
- } catch {}
1259
- this.#rootPump = void 0;
1260
1307
  this.#rootMessages.reset();
1261
1308
  this.#rootToolAssembler = new ToolCallAssembler();
1262
1309
  this.#lifecycleLoading.reset();
@@ -1267,7 +1314,16 @@ var StreamController = class {
1267
1314
  this.#localRunDepth = 0;
1268
1315
  this.#messageMetadata.reset();
1269
1316
  this.#hydratedActiveInterruptIds = null;
1317
+ this.#interruptReplayThroughSeq = void 0;
1318
+ this.#discardPendingInterruptEvents();
1270
1319
  this.queueStore.setState(() => EMPTY_QUEUE);
1320
+ try {
1321
+ await subscription?.unsubscribe();
1322
+ } catch {}
1323
+ try {
1324
+ await this.#rootPump;
1325
+ } catch {}
1326
+ this.#rootPump = void 0;
1271
1327
  if (thread != null) {
1272
1328
  try {
1273
1329
  await thread.close();
@@ -1291,6 +1347,7 @@ var StreamController = class {
1291
1347
  */
1292
1348
  #startRootPump(thread) {
1293
1349
  if (this.#rootPump != null) return;
1350
+ const pumpGeneration = this.#rootPumpGeneration;
1294
1351
  let resolveReady;
1295
1352
  this.#rootPumpReady = new Promise((resolve) => {
1296
1353
  resolveReady = resolve;
@@ -1349,6 +1406,14 @@ var StreamController = class {
1349
1406
  resolveReady = void 0;
1350
1407
  });
1351
1408
  const subscription = await subscriptionPromise;
1409
+ if (pumpGeneration !== this.#rootPumpGeneration) {
1410
+ resolveReady?.();
1411
+ resolveReady = void 0;
1412
+ try {
1413
+ subscription.close();
1414
+ } catch {}
1415
+ return;
1416
+ }
1352
1417
  resolveReady?.();
1353
1418
  resolveReady = void 0;
1354
1419
  this.#rootSubscription = subscription;
@@ -1362,9 +1427,9 @@ var StreamController = class {
1362
1427
  * for every resumed iteration until the subscription is
1363
1428
  * permanently closed or the controller is disposed.
1364
1429
  */
1365
- while (!this.#disposed) {
1430
+ while (!this.#disposed && pumpGeneration === this.#rootPumpGeneration) {
1366
1431
  for await (const event of subscription) {
1367
- if (this.#disposed) break;
1432
+ if (this.#disposed || pumpGeneration !== this.#rootPumpGeneration) break;
1368
1433
  /**
1369
1434
  * Resilience: isolate per-event dispatch from the pump loop.
1370
1435
  *
@@ -1396,7 +1461,7 @@ var StreamController = class {
1396
1461
  this.#onRootEvent(event);
1397
1462
  } catch {}
1398
1463
  }
1399
- if (this.#disposed) break;
1464
+ if (this.#disposed || pumpGeneration !== this.#rootPumpGeneration) break;
1400
1465
  if (!subscription.isPaused) break;
1401
1466
  await subscription.waitForResume();
1402
1467
  }
@@ -1664,7 +1729,13 @@ var StreamController = class {
1664
1729
  const data = event.params.data;
1665
1730
  const interruptId = data?.interrupt_id;
1666
1731
  if (typeof interruptId !== "string" || this.#resolvedInterrupts.has(interruptId)) return;
1667
- if (this.#hydratedActiveInterruptIds != null && !this.#hydratedActiveInterruptIds.has(interruptId)) return;
1732
+ const eventSeq = typeof event.seq === "number" ? event.seq : void 0;
1733
+ const isUnknownInterrupt = this.#hydratedActiveInterruptIds != null && !this.#hydratedActiveInterruptIds.has(interruptId);
1734
+ if (isUnknownInterrupt && this.#interruptCommandPending) {
1735
+ this.#pendingInterruptEvents.push(event);
1736
+ return;
1737
+ }
1738
+ if (isUnknownInterrupt && (this.#interruptReplayThroughSeq == null || eventSeq != null && eventSeq <= this.#interruptReplayThroughSeq)) return;
1668
1739
  const namespace = Array.isArray(event.params.namespace) ? [...event.params.namespace] : [...ROOT_NAMESPACE];
1669
1740
  const interrupt = normalizeInterruptForClient({
1670
1741
  id: interruptId,
@@ -1682,6 +1753,31 @@ var StreamController = class {
1682
1753
  });
1683
1754
  }
1684
1755
  /**
1756
+ * Convert the hydrate-time allowlist into a replay barrier after a command
1757
+ * is accepted. Built-in transports update `lastAppliedThroughSeq` from the
1758
+ * command response before resolving `submitRun` / `respondInput`.
1759
+ */
1760
+ #advanceInterruptReplayBarrier() {
1761
+ if (this.#hydratedActiveInterruptIds == null) {
1762
+ this.#discardPendingInterruptEvents();
1763
+ return;
1764
+ }
1765
+ const throughSeq = this.#thread?.ordering?.lastAppliedThroughSeq;
1766
+ if (typeof throughSeq === "number") this.#interruptReplayThroughSeq = throughSeq;
1767
+ else {
1768
+ this.#hydratedActiveInterruptIds = null;
1769
+ this.#interruptReplayThroughSeq = void 0;
1770
+ }
1771
+ this.#interruptCommandPending = false;
1772
+ const pendingEvents = this.#pendingInterruptEvents;
1773
+ this.#pendingInterruptEvents = [];
1774
+ for (const event of pendingEvents) this.#recordInterrupt(event);
1775
+ }
1776
+ #discardPendingInterruptEvents() {
1777
+ this.#interruptCommandPending = false;
1778
+ this.#pendingInterruptEvents = [];
1779
+ }
1780
+ /**
1685
1781
  * Resolve the protocol namespace for a targeted resume.
1686
1782
  *
1687
1783
  * Prefer an explicit caller-supplied namespace, then the matching