@langchain/langgraph-sdk 1.9.30 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/stream/controller.cjs +68 -8
- package/dist/stream/controller.cjs.map +1 -1
- package/dist/stream/controller.d.cts.map +1 -1
- package/dist/stream/controller.d.ts.map +1 -1
- package/dist/stream/controller.js +68 -8
- package/dist/stream/controller.js.map +1 -1
- package/dist/stream/submit-coordinator.cjs +1 -1
- package/dist/stream/submit-coordinator.cjs.map +1 -1
- package/dist/stream/submit-coordinator.js +1 -1
- package/dist/stream/submit-coordinator.js.map +1 -1
- package/package.json +3 -13
|
@@ -155,12 +155,25 @@ var StreamController = class {
|
|
|
155
155
|
* SSE replay re-adds historically-requested interrupts that have
|
|
156
156
|
* since been resolved (no `input.responded` event exists in the
|
|
157
157
|
* protocol, so the SDK has no other way to tell replay from live
|
|
158
|
-
* for an idle thread).
|
|
159
|
-
*
|
|
160
|
-
* cleared at the start of `submit()` for the same reason.
|
|
158
|
+
* for an idle thread). After a command is accepted, events newer
|
|
159
|
+
* than {@link #interruptReplayThroughSeq} bypass the allowlist.
|
|
161
160
|
*/
|
|
162
161
|
#hydratedActiveInterruptIds = null;
|
|
163
162
|
/**
|
|
163
|
+
* Highest event sequence already applied when the latest run command
|
|
164
|
+
* was accepted. Interrupts outside the hydrate-time allowlist remain
|
|
165
|
+
* filtered through this sequence, while newer events are live output
|
|
166
|
+
* from the newly-started run and must be accepted.
|
|
167
|
+
*/
|
|
168
|
+
#interruptReplayThroughSeq;
|
|
169
|
+
/**
|
|
170
|
+
* Unknown interrupt events received between local command dispatch and its
|
|
171
|
+
* response. The response supplies the sequence barrier needed to classify
|
|
172
|
+
* each event as historical replay or live output from the new run.
|
|
173
|
+
*/
|
|
174
|
+
#pendingInterruptEvents = [];
|
|
175
|
+
#interruptCommandPending = false;
|
|
176
|
+
/**
|
|
164
177
|
* Monotonic counter bumped at the start of each `submit()` and used
|
|
165
178
|
* by {@link hydrate} to skip its post-fetch allowlist write when a
|
|
166
179
|
* submit started while the state fetch was in flight. Without this
|
|
@@ -302,13 +315,20 @@ var StreamController = class {
|
|
|
302
315
|
awaitNextTerminal: (signal) => this.#awaitNextTerminal(signal),
|
|
303
316
|
awaitResumedRunTerminal: (signal) => this.#awaitResumedRunTerminal(signal),
|
|
304
317
|
onSubmitStart: () => {
|
|
305
|
-
this.#hydratedActiveInterruptIds = null;
|
|
306
318
|
this.#submitGeneration += 1;
|
|
319
|
+
this.#interruptCommandPending = this.#hydratedActiveInterruptIds != null;
|
|
320
|
+
this.#pendingInterruptEvents = [];
|
|
307
321
|
},
|
|
308
322
|
onRunStart: () => this.#markLocalRunStart(),
|
|
309
|
-
onRunCreated: (runId) =>
|
|
323
|
+
onRunCreated: (runId) => {
|
|
324
|
+
this.#advanceInterruptReplayBarrier();
|
|
325
|
+
this.#notifyCreated(runId);
|
|
326
|
+
},
|
|
310
327
|
onRunCompleted: (reason, runId) => this.#notifyCompleted(reason, runId),
|
|
311
|
-
onRunEnd: () =>
|
|
328
|
+
onRunEnd: () => {
|
|
329
|
+
this.#interruptCommandPending = false;
|
|
330
|
+
this.#markLocalRunEnd();
|
|
331
|
+
},
|
|
312
332
|
beginOptimistic: (input) => this.#beginOptimistic(input),
|
|
313
333
|
settleOptimistic: (handle, event) => this.#settleOptimistic(handle, event)
|
|
314
334
|
});
|
|
@@ -562,7 +582,10 @@ var StreamController = class {
|
|
|
562
582
|
interrupts: activeInterrupts,
|
|
563
583
|
interrupt: activeInterrupts[0]
|
|
564
584
|
}));
|
|
565
|
-
if (this.#submitGeneration === generationAtFetch)
|
|
585
|
+
if (this.#submitGeneration === generationAtFetch) {
|
|
586
|
+
this.#hydratedActiveInterruptIds = activeIds;
|
|
587
|
+
this.#interruptReplayThroughSeq = void 0;
|
|
588
|
+
}
|
|
566
589
|
}
|
|
567
590
|
} catch (error) {
|
|
568
591
|
if (error?.status !== 404) {
|
|
@@ -1009,9 +1032,11 @@ var StreamController = class {
|
|
|
1009
1032
|
config: options?.config,
|
|
1010
1033
|
metadata: options?.metadata
|
|
1011
1034
|
});
|
|
1035
|
+
this.#advanceInterruptReplayBarrier();
|
|
1012
1036
|
this.#markInterruptResolvedInRootStore(resolved.interruptId);
|
|
1013
1037
|
}, prepared?.handle);
|
|
1014
1038
|
} catch (error) {
|
|
1039
|
+
this.#discardPendingInterruptEvents();
|
|
1015
1040
|
if (this.#disposed && isAbortLikeError(error)) return;
|
|
1016
1041
|
throw error;
|
|
1017
1042
|
}
|
|
@@ -1078,9 +1103,11 @@ var StreamController = class {
|
|
|
1078
1103
|
config: options?.config,
|
|
1079
1104
|
metadata: options?.metadata
|
|
1080
1105
|
});
|
|
1106
|
+
this.#advanceInterruptReplayBarrier();
|
|
1081
1107
|
for (const { interrupt_id: interruptId } of responses) this.#markInterruptResolvedInRootStore(interruptId);
|
|
1082
1108
|
}, prepared?.handle);
|
|
1083
1109
|
} catch (error) {
|
|
1110
|
+
this.#discardPendingInterruptEvents();
|
|
1084
1111
|
if (this.#disposed && isAbortLikeError(error)) return;
|
|
1085
1112
|
throw error;
|
|
1086
1113
|
}
|
|
@@ -1288,6 +1315,8 @@ var StreamController = class {
|
|
|
1288
1315
|
this.#localRunDepth = 0;
|
|
1289
1316
|
this.#messageMetadata.reset();
|
|
1290
1317
|
this.#hydratedActiveInterruptIds = null;
|
|
1318
|
+
this.#interruptReplayThroughSeq = void 0;
|
|
1319
|
+
this.#discardPendingInterruptEvents();
|
|
1291
1320
|
this.queueStore.setState(() => require_submit_coordinator.EMPTY_QUEUE);
|
|
1292
1321
|
try {
|
|
1293
1322
|
await subscription?.unsubscribe();
|
|
@@ -1701,7 +1730,13 @@ var StreamController = class {
|
|
|
1701
1730
|
const data = event.params.data;
|
|
1702
1731
|
const interruptId = data?.interrupt_id;
|
|
1703
1732
|
if (typeof interruptId !== "string" || this.#resolvedInterrupts.has(interruptId)) return;
|
|
1704
|
-
|
|
1733
|
+
const eventSeq = typeof event.seq === "number" ? event.seq : void 0;
|
|
1734
|
+
const isUnknownInterrupt = this.#hydratedActiveInterruptIds != null && !this.#hydratedActiveInterruptIds.has(interruptId);
|
|
1735
|
+
if (isUnknownInterrupt && this.#interruptCommandPending) {
|
|
1736
|
+
this.#pendingInterruptEvents.push(event);
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
if (isUnknownInterrupt && (this.#interruptReplayThroughSeq == null || eventSeq != null && eventSeq <= this.#interruptReplayThroughSeq)) return;
|
|
1705
1740
|
const namespace = Array.isArray(event.params.namespace) ? [...event.params.namespace] : [...ROOT_NAMESPACE];
|
|
1706
1741
|
const interrupt = require_interrupts.normalizeInterruptForClient({
|
|
1707
1742
|
id: interruptId,
|
|
@@ -1719,6 +1754,31 @@ var StreamController = class {
|
|
|
1719
1754
|
});
|
|
1720
1755
|
}
|
|
1721
1756
|
/**
|
|
1757
|
+
* Convert the hydrate-time allowlist into a replay barrier after a command
|
|
1758
|
+
* is accepted. Built-in transports update `lastAppliedThroughSeq` from the
|
|
1759
|
+
* command response before resolving `submitRun` / `respondInput`.
|
|
1760
|
+
*/
|
|
1761
|
+
#advanceInterruptReplayBarrier() {
|
|
1762
|
+
if (this.#hydratedActiveInterruptIds == null) {
|
|
1763
|
+
this.#discardPendingInterruptEvents();
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
const throughSeq = this.#thread?.ordering?.lastAppliedThroughSeq;
|
|
1767
|
+
if (typeof throughSeq === "number") this.#interruptReplayThroughSeq = throughSeq;
|
|
1768
|
+
else {
|
|
1769
|
+
this.#hydratedActiveInterruptIds = null;
|
|
1770
|
+
this.#interruptReplayThroughSeq = void 0;
|
|
1771
|
+
}
|
|
1772
|
+
this.#interruptCommandPending = false;
|
|
1773
|
+
const pendingEvents = this.#pendingInterruptEvents;
|
|
1774
|
+
this.#pendingInterruptEvents = [];
|
|
1775
|
+
for (const event of pendingEvents) this.#recordInterrupt(event);
|
|
1776
|
+
}
|
|
1777
|
+
#discardPendingInterruptEvents() {
|
|
1778
|
+
this.#interruptCommandPending = false;
|
|
1779
|
+
this.#pendingInterruptEvents = [];
|
|
1780
|
+
}
|
|
1781
|
+
/**
|
|
1722
1782
|
* Resolve the protocol namespace for a targeted resume.
|
|
1723
1783
|
*
|
|
1724
1784
|
* Prefer an explicit caller-supplied namespace, then the matching
|