@langchain/langgraph-sdk 1.10.3-rc.0 → 1.10.3-rc.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.
|
@@ -149,11 +149,9 @@ var StreamController = class {
|
|
|
149
149
|
* Interrupt ids this controller has locally marked resolved via
|
|
150
150
|
* {@link respond} / {@link respondAll}. Used only to suppress
|
|
151
151
|
* *historical* SSE replay of those `input.requested` events (there
|
|
152
|
-
* is no `input.responded` protocol event).
|
|
153
|
-
* resume barrier
|
|
154
|
-
*
|
|
155
|
-
* still-pending server interrupt can reappear on
|
|
156
|
-
* `rootStore.interrupts`.
|
|
152
|
+
* is no `input.responded` protocol event). A live event after the
|
|
153
|
+
* resume barrier clears an id from this set so an interrupt raised
|
|
154
|
+
* again by a later run can reappear on `rootStore.interrupts`.
|
|
157
155
|
*/
|
|
158
156
|
#resolvedInterrupts = /* @__PURE__ */ new Set();
|
|
159
157
|
/**
|
|
@@ -169,13 +167,17 @@ var StreamController = class {
|
|
|
169
167
|
* than {@link #interruptReplayThroughSeq} bypass the allowlist.
|
|
170
168
|
*/
|
|
171
169
|
#hydratedActiveInterruptIds = null;
|
|
170
|
+
/** Checkpoint whose replay establishes the hydrate-time interrupt cutoff. */
|
|
171
|
+
#hydratedInterruptCheckpointId;
|
|
172
172
|
/**
|
|
173
|
-
* Highest event sequence
|
|
174
|
-
* was accepted. Interrupts outside the hydrate-time
|
|
175
|
-
* filtered through this sequence, while newer events are
|
|
176
|
-
*
|
|
173
|
+
* Highest event sequence represented by hydration or already applied when
|
|
174
|
+
* the latest run command was accepted. Interrupts outside the hydrate-time
|
|
175
|
+
* allowlist remain filtered through this sequence, while newer events are
|
|
176
|
+
* live output and must be accepted.
|
|
177
177
|
*/
|
|
178
178
|
#interruptReplayThroughSeq;
|
|
179
|
+
/** Unknown inputs waiting for replay to reach the hydrated checkpoint. */
|
|
180
|
+
#pendingHydrationInterruptEvents = [];
|
|
179
181
|
/**
|
|
180
182
|
* Unknown interrupt events received between local command dispatch and its
|
|
181
183
|
* response. The response supplies the sequence barrier needed to classify
|
|
@@ -327,7 +329,9 @@ var StreamController = class {
|
|
|
327
329
|
onSubmitStart: () => {
|
|
328
330
|
this.#submitGeneration += 1;
|
|
329
331
|
this.#interruptCommandPending = this.#hydratedActiveInterruptIds != null;
|
|
330
|
-
this.#pendingInterruptEvents =
|
|
332
|
+
this.#pendingInterruptEvents = this.#pendingHydrationInterruptEvents;
|
|
333
|
+
this.#pendingHydrationInterruptEvents = [];
|
|
334
|
+
this.#hydratedInterruptCheckpointId = void 0;
|
|
331
335
|
},
|
|
332
336
|
onRunStart: () => this.#markLocalRunStart(),
|
|
333
337
|
onRunCreated: (runId) => {
|
|
@@ -578,6 +582,7 @@ var StreamController = class {
|
|
|
578
582
|
}));
|
|
579
583
|
if (this.#submitGeneration === generationAtFetch) {
|
|
580
584
|
this.#hydratedActiveInterruptIds = activeIds;
|
|
585
|
+
this.#hydratedInterruptCheckpointId = state.checkpoint?.checkpoint_id ?? void 0;
|
|
581
586
|
this.#interruptReplayThroughSeq = void 0;
|
|
582
587
|
}
|
|
583
588
|
}
|
|
@@ -1309,7 +1314,9 @@ var StreamController = class {
|
|
|
1309
1314
|
this.#localRunDepth = 0;
|
|
1310
1315
|
this.#messageMetadata.reset();
|
|
1311
1316
|
this.#hydratedActiveInterruptIds = null;
|
|
1317
|
+
this.#hydratedInterruptCheckpointId = void 0;
|
|
1312
1318
|
this.#interruptReplayThroughSeq = void 0;
|
|
1319
|
+
this.#pendingHydrationInterruptEvents = [];
|
|
1313
1320
|
this.#discardPendingInterruptEvents();
|
|
1314
1321
|
this.queueStore.setState(() => require_submit_coordinator.EMPTY_QUEUE);
|
|
1315
1322
|
try {
|
|
@@ -1485,6 +1492,7 @@ var StreamController = class {
|
|
|
1485
1492
|
} catch {}
|
|
1486
1493
|
this.#subgraphs.push(event);
|
|
1487
1494
|
this.#lifecycleLoading.handle(event);
|
|
1495
|
+
this.#advanceInterruptReplayBarrierFromCheckpoint(event);
|
|
1488
1496
|
/**
|
|
1489
1497
|
* `input.requested` events (including HITL inside a subagent /
|
|
1490
1498
|
* subgraph) are not always observable via the narrow content pump.
|
|
@@ -1734,6 +1742,10 @@ var StreamController = class {
|
|
|
1734
1742
|
this.#pendingInterruptEvents.push(event);
|
|
1735
1743
|
return;
|
|
1736
1744
|
}
|
|
1745
|
+
if (isUnknownInterrupt && this.#interruptReplayThroughSeq == null && this.#hydratedInterruptCheckpointId != null) {
|
|
1746
|
+
this.#pendingHydrationInterruptEvents.push(event);
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1737
1749
|
if (isUnknownInterrupt && (this.#interruptReplayThroughSeq == null || eventSeq != null && eventSeq <= this.#interruptReplayThroughSeq)) return;
|
|
1738
1750
|
const namespace = Array.isArray(event.params.namespace) ? [...event.params.namespace] : [...ROOT_NAMESPACE];
|
|
1739
1751
|
const interrupt = require_interrupts.normalizeInterruptForClient({
|
|
@@ -1751,6 +1763,16 @@ var StreamController = class {
|
|
|
1751
1763
|
};
|
|
1752
1764
|
});
|
|
1753
1765
|
}
|
|
1766
|
+
/** Establish the hydration cutoff when ordered replay reaches its checkpoint. */
|
|
1767
|
+
#advanceInterruptReplayBarrierFromCheckpoint(event) {
|
|
1768
|
+
if (event.method !== "checkpoints" || this.#hydratedInterruptCheckpointId == null || !require_namespace.isRootNamespace(event.params.namespace)) return;
|
|
1769
|
+
if (event.params.data?.id !== this.#hydratedInterruptCheckpointId || typeof event.seq !== "number") return;
|
|
1770
|
+
this.#interruptReplayThroughSeq = event.seq;
|
|
1771
|
+
this.#hydratedInterruptCheckpointId = void 0;
|
|
1772
|
+
const pendingEvents = this.#pendingHydrationInterruptEvents.sort((a, b) => (a.seq ?? 0) - (b.seq ?? 0));
|
|
1773
|
+
this.#pendingHydrationInterruptEvents = [];
|
|
1774
|
+
for (const pendingEvent of pendingEvents) this.#recordInterrupt(pendingEvent);
|
|
1775
|
+
}
|
|
1754
1776
|
/**
|
|
1755
1777
|
* Convert the hydrate-time allowlist into a replay barrier after a command
|
|
1756
1778
|
* is accepted. Built-in transports update `lastAppliedThroughSeq` from the
|
|
@@ -1796,8 +1818,7 @@ var StreamController = class {
|
|
|
1796
1818
|
* mirror the removal into the root snapshot the framework hooks read.
|
|
1797
1819
|
*
|
|
1798
1820
|
* Tombstones are not permanent: a live `input.requested` after the
|
|
1799
|
-
* resume barrier
|
|
1800
|
-
* clears the id when the server still reports it as pending.
|
|
1821
|
+
* resume barrier clears the id when the same interrupt is raised again.
|
|
1801
1822
|
*/
|
|
1802
1823
|
#markInterruptResolvedInRootStore(interruptId) {
|
|
1803
1824
|
this.#resolvedInterrupts.add(interruptId);
|
|
@@ -1816,10 +1837,11 @@ var StreamController = class {
|
|
|
1816
1837
|
* `state.tasks[].interrupts` after a resumed run settles.
|
|
1817
1838
|
*
|
|
1818
1839
|
* Sequential `respond()` of parallel interrupts optimistically clears
|
|
1819
|
-
* each id client-side.
|
|
1820
|
-
*
|
|
1821
|
-
*
|
|
1822
|
-
*
|
|
1840
|
+
* each targeted id client-side. The server checkpoint can continue to
|
|
1841
|
+
* list the original interrupt batch after accepting a partial response,
|
|
1842
|
+
* so locally-resolved ids remain filtered while untouched siblings are
|
|
1843
|
+
* restored. This keeps `stream.interrupts` truthful without re-exposing
|
|
1844
|
+
* an already-consumed interrupt.
|
|
1823
1845
|
*
|
|
1824
1846
|
* Uses the same transport-aware state fetch as {@link hydrate}, and
|
|
1825
1847
|
* drops the result if the thread swapped or a new submit/respond
|
|
@@ -1834,11 +1856,11 @@ var StreamController = class {
|
|
|
1834
1856
|
if (this.#disposed || this.#currentThreadId !== threadId || this.#submitGeneration !== generationAtFetch) return;
|
|
1835
1857
|
if (!Array.isArray(state?.tasks)) return;
|
|
1836
1858
|
const { activeInterrupts, activeIds } = collectActiveInterruptsFromTasks(state.tasks);
|
|
1837
|
-
|
|
1859
|
+
const pendingInterrupts = activeInterrupts.filter((interrupt) => interrupt.id == null || !this.#resolvedInterrupts.has(interrupt.id));
|
|
1838
1860
|
this.rootStore.setState((s) => ({
|
|
1839
1861
|
...s,
|
|
1840
|
-
interrupts:
|
|
1841
|
-
interrupt:
|
|
1862
|
+
interrupts: pendingInterrupts,
|
|
1863
|
+
interrupt: pendingInterrupts[0]
|
|
1842
1864
|
}));
|
|
1843
1865
|
this.#hydratedActiveInterruptIds = activeIds;
|
|
1844
1866
|
} catch {}
|