@langchain/langgraph-sdk 1.10.0 → 1.10.2
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/client/stream/transport/http.cjs +2 -0
- package/dist/client/stream/transport/http.cjs.map +1 -1
- package/dist/client/stream/transport/http.d.cts.map +1 -1
- package/dist/client/stream/transport/http.d.ts.map +1 -1
- package/dist/client/stream/transport/http.js +2 -0
- package/dist/client/stream/transport/http.js.map +1 -1
- package/dist/stream/controller.cjs +95 -23
- 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 +95 -23
- package/dist/stream/controller.js.map +1 -1
- package/dist/stream/message-reconciliation.cjs +47 -22
- package/dist/stream/message-reconciliation.cjs.map +1 -1
- package/dist/stream/message-reconciliation.js +47 -22
- package/dist/stream/message-reconciliation.js.map +1 -1
- package/dist/stream/root-message-projection.cjs +7 -5
- package/dist/stream/root-message-projection.cjs.map +1 -1
- package/dist/stream/root-message-projection.js +7 -5
- package/dist/stream/root-message-projection.js.map +1 -1
- package/package.json +4 -4
|
@@ -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;
|
|
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;EA+J0B;;;;;EAA7C,WAAA,CAAY,OAAA,EAAS,uBAAA,CAAwB,SAAA;EAgyBF;;;;;;;EAAA,IAtqBvC,gBAAA,CAAA,GAAoB,OAAA;EA20BS;;;;;;;;EAlxB3B,OAAA,CAAQ,QAAA,mBAA2B,OAAA;EAogCpB;;;;;;;;;;;;;;EA7pBf,wBAAA,CAAyB,UAAA,WAAqB,OAAA;EA9rB5B;;;;;;;;EAk8BlB,MAAA,CACJ,KAAA,WACA,OAAA,GAAU,mBAAA,CAAoB,SAAA,EAAW,gBAAA,IACxC,OAAA;EAl8B4B;;;;;;EA48BzB,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EA18BtB;;;;EA89Bb,UAAA,CAAA,GAAc,OAAA;EArsBhB;;;;;;;;;;;EAqwBE,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;;;;;
|
|
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;;;;;EA+JnB,WAAA,CAAY,OAAA,EAAS,uBAAA,CAAwB,SAAA;EAgyBb;;;;;;;EAAA,IAtqB5B,gBAAA,CAAA,GAAoB,OAAA;EA4wBJ;;;;;;;;EAntBd,OAAA,CAAQ,QAAA,mBAA2B,OAAA;EAw/B5B;;;;;;;;;;;;;;EAjpBP,wBAAA,CAAyB,UAAA,WAAqB,OAAA;EA9rB3C;;;;;;;;EAk8BH,MAAA,CACJ,KAAA,WACA,OAAA,GAAU,mBAAA,CAAoB,SAAA,EAAW,gBAAA,IACxC,OAAA;EAl8BM;;;;;;EA48BH,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EA18BhC;;;;EA89BH,UAAA,CAAA,GAAc,OAAA;EA/zBR;;;;;;;;;;;EA+3BN,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"}
|
|
@@ -144,6 +144,16 @@ var StreamController = class {
|
|
|
144
144
|
#threadEventUnsubscribe;
|
|
145
145
|
#disposed = false;
|
|
146
146
|
#pendingDisposeTimer = null;
|
|
147
|
+
/**
|
|
148
|
+
* Interrupt ids this controller has locally marked resolved via
|
|
149
|
+
* {@link respond} / {@link respondAll}. Used only to suppress
|
|
150
|
+
* *historical* SSE replay of those `input.requested` events (there
|
|
151
|
+
* is no `input.responded` protocol event). Live events after the
|
|
152
|
+
* resume barrier — or a post-resume reconcile against
|
|
153
|
+
* `state.tasks[].interrupts` — clear an id from this set so a
|
|
154
|
+
* still-pending server interrupt can reappear on
|
|
155
|
+
* `rootStore.interrupts`.
|
|
156
|
+
*/
|
|
147
157
|
#resolvedInterrupts = /* @__PURE__ */ new Set();
|
|
148
158
|
/**
|
|
149
159
|
* Set of interrupt IDs the server reports as currently *active* on
|
|
@@ -558,24 +568,8 @@ var StreamController = class {
|
|
|
558
568
|
*/
|
|
559
569
|
if (Array.isArray(state?.tasks)) {
|
|
560
570
|
const generationAtFetch = this.#submitGeneration;
|
|
561
|
-
const activeInterrupts =
|
|
562
|
-
const
|
|
563
|
-
for (const task of state.tasks) {
|
|
564
|
-
if (!Array.isArray(task?.interrupts)) continue;
|
|
565
|
-
const checkpointNs = task?.checkpoint?.checkpoint_ns;
|
|
566
|
-
const namespace = typeof checkpointNs === "string" && checkpointNs.length > 0 ? checkpointNs.split("|").filter((segment) => segment.length > 0) : [...ROOT_NAMESPACE];
|
|
567
|
-
for (const interrupt of task.interrupts) {
|
|
568
|
-
const typed = interrupt;
|
|
569
|
-
const id = typed?.id;
|
|
570
|
-
if (typeof id !== "string" || activeIds.has(id)) continue;
|
|
571
|
-
activeIds.add(id);
|
|
572
|
-
activeInterrupts.push(normalizeInterruptForClient({
|
|
573
|
-
id,
|
|
574
|
-
value: typed?.value,
|
|
575
|
-
namespace: Array.isArray(typed?.namespace) ? [...typed.namespace] : namespace
|
|
576
|
-
}));
|
|
577
|
-
}
|
|
578
|
-
}
|
|
571
|
+
const { activeInterrupts, activeIds } = collectActiveInterruptsFromTasks(state.tasks);
|
|
572
|
+
for (const id of activeIds) this.#resolvedInterrupts.delete(id);
|
|
579
573
|
this.rootStore.setState((s) => ({
|
|
580
574
|
...s,
|
|
581
575
|
interrupts: activeInterrupts,
|
|
@@ -1728,8 +1722,12 @@ var StreamController = class {
|
|
|
1728
1722
|
if (event.method !== "input.requested") return;
|
|
1729
1723
|
const data = event.params.data;
|
|
1730
1724
|
const interruptId = data?.interrupt_id;
|
|
1731
|
-
if (typeof interruptId !== "string"
|
|
1725
|
+
if (typeof interruptId !== "string") return;
|
|
1732
1726
|
const eventSeq = typeof event.seq === "number" ? event.seq : void 0;
|
|
1727
|
+
if (this.#resolvedInterrupts.has(interruptId)) {
|
|
1728
|
+
if (!(this.#hydratedActiveInterruptIds == null || typeof this.#interruptReplayThroughSeq === "number" && eventSeq != null && eventSeq > this.#interruptReplayThroughSeq)) return;
|
|
1729
|
+
this.#resolvedInterrupts.delete(interruptId);
|
|
1730
|
+
}
|
|
1733
1731
|
const isUnknownInterrupt = this.#hydratedActiveInterruptIds != null && !this.#hydratedActiveInterruptIds.has(interruptId);
|
|
1734
1732
|
if (isUnknownInterrupt && this.#interruptCommandPending) {
|
|
1735
1733
|
this.#pendingInterruptEvents.push(event);
|
|
@@ -1793,8 +1791,12 @@ var StreamController = class {
|
|
|
1793
1791
|
return [...ROOT_NAMESPACE];
|
|
1794
1792
|
}
|
|
1795
1793
|
/**
|
|
1796
|
-
* Mark an interrupt resolved for replay filtering and
|
|
1797
|
-
* removal into the root snapshot the framework hooks read.
|
|
1794
|
+
* Mark an interrupt resolved for historical-replay filtering and
|
|
1795
|
+
* mirror the removal into the root snapshot the framework hooks read.
|
|
1796
|
+
*
|
|
1797
|
+
* Tombstones are not permanent: a live `input.requested` after the
|
|
1798
|
+
* resume barrier, or {@link #reconcilePendingInterruptsFromServer},
|
|
1799
|
+
* clears the id when the server still reports it as pending.
|
|
1798
1800
|
*/
|
|
1799
1801
|
#markInterruptResolvedInRootStore(interruptId) {
|
|
1800
1802
|
this.#resolvedInterrupts.add(interruptId);
|
|
@@ -1809,6 +1811,38 @@ var StreamController = class {
|
|
|
1809
1811
|
});
|
|
1810
1812
|
}
|
|
1811
1813
|
/**
|
|
1814
|
+
* Re-sync `rootStore.interrupts` from the server's authoritative
|
|
1815
|
+
* `state.tasks[].interrupts` after a resumed run settles.
|
|
1816
|
+
*
|
|
1817
|
+
* Sequential `respond()` of parallel interrupts optimistically clears
|
|
1818
|
+
* each id client-side. When the server still has siblings pending and
|
|
1819
|
+
* does not re-emit `input.requested` for them (session map already
|
|
1820
|
+
* holds the id), this restore keeps `stream.interrupts` truthful so
|
|
1821
|
+
* callers do not free-text `submit()` into an ambiguous resume.
|
|
1822
|
+
*
|
|
1823
|
+
* Uses the same transport-aware state fetch as {@link hydrate}, and
|
|
1824
|
+
* drops the result if the thread swapped or a new submit/respond
|
|
1825
|
+
* started while the fetch was in flight.
|
|
1826
|
+
*/
|
|
1827
|
+
async #reconcilePendingInterruptsFromServer() {
|
|
1828
|
+
const threadId = this.#currentThreadId;
|
|
1829
|
+
if (threadId == null || this.#disposed) return;
|
|
1830
|
+
const generationAtFetch = this.#submitGeneration;
|
|
1831
|
+
try {
|
|
1832
|
+
const state = await this.#fetchHydrationState();
|
|
1833
|
+
if (this.#disposed || this.#currentThreadId !== threadId || this.#submitGeneration !== generationAtFetch) return;
|
|
1834
|
+
if (!Array.isArray(state?.tasks)) return;
|
|
1835
|
+
const { activeInterrupts, activeIds } = collectActiveInterruptsFromTasks(state.tasks);
|
|
1836
|
+
for (const id of activeIds) this.#resolvedInterrupts.delete(id);
|
|
1837
|
+
this.rootStore.setState((s) => ({
|
|
1838
|
+
...s,
|
|
1839
|
+
interrupts: activeInterrupts,
|
|
1840
|
+
interrupt: activeInterrupts[0]
|
|
1841
|
+
}));
|
|
1842
|
+
this.#hydratedActiveInterruptIds = activeIds;
|
|
1843
|
+
} catch {}
|
|
1844
|
+
}
|
|
1845
|
+
/**
|
|
1812
1846
|
* Resolve on the next root-namespace terminal lifecycle event
|
|
1813
1847
|
* (`completed` / `failed` / `interrupted`) or on abort.
|
|
1814
1848
|
*
|
|
@@ -1833,9 +1867,15 @@ var StreamController = class {
|
|
|
1833
1867
|
* but before `respondInput` calls `#prepareForNextRun`; accepting that
|
|
1834
1868
|
* terminal would unsubscribe the watcher before the resumed run's `failed`
|
|
1835
1869
|
* terminal arrives.
|
|
1870
|
+
*
|
|
1871
|
+
* On `interrupted` / `completed`, reconciles pending interrupts from
|
|
1872
|
+
* server state so optimistic clears from {@link respond} cannot leave
|
|
1873
|
+
* `stream.interrupts` empty while the checkpoint still has siblings.
|
|
1836
1874
|
*/
|
|
1837
|
-
#awaitResumedRunTerminal(signal) {
|
|
1838
|
-
|
|
1875
|
+
async #awaitResumedRunTerminal(signal) {
|
|
1876
|
+
const terminal = await this.#awaitRootTerminal(signal, { skipInterruptedUntilRunning: true });
|
|
1877
|
+
if (!signal.aborted && !this.#disposed && (terminal.event === "interrupted" || terminal.event === "completed")) await this.#reconcilePendingInterruptsFromServer();
|
|
1878
|
+
return terminal;
|
|
1839
1879
|
}
|
|
1840
1880
|
#awaitRootTerminal(signal, options) {
|
|
1841
1881
|
return new Promise((resolve) => {
|
|
@@ -1927,6 +1967,38 @@ function extractAndCoerceMessagesWithFallback(values, messagesKey) {
|
|
|
1927
1967
|
if (!Array.isArray(raw)) return null;
|
|
1928
1968
|
return ensureMessageInstances(raw);
|
|
1929
1969
|
}
|
|
1970
|
+
/**
|
|
1971
|
+
* Collect pending interrupts from a `threads.getState()` `tasks` array.
|
|
1972
|
+
*
|
|
1973
|
+
* Shared by {@link StreamController.hydrate} and the post-resume
|
|
1974
|
+
* reconcile path so both stay aligned on namespace derivation and
|
|
1975
|
+
* id dedupe.
|
|
1976
|
+
*/
|
|
1977
|
+
function collectActiveInterruptsFromTasks(tasks) {
|
|
1978
|
+
const activeInterrupts = [];
|
|
1979
|
+
const activeIds = /* @__PURE__ */ new Set();
|
|
1980
|
+
for (const task of tasks) {
|
|
1981
|
+
if (!Array.isArray(task?.interrupts)) continue;
|
|
1982
|
+
const typedTask = task;
|
|
1983
|
+
const checkpointNs = typedTask.checkpoint?.checkpoint_ns;
|
|
1984
|
+
const namespace = typeof checkpointNs === "string" && checkpointNs.length > 0 ? checkpointNs.split("|").filter((segment) => segment.length > 0) : [...ROOT_NAMESPACE];
|
|
1985
|
+
for (const interrupt of typedTask.interrupts) {
|
|
1986
|
+
const typed = interrupt;
|
|
1987
|
+
const id = typed?.id;
|
|
1988
|
+
if (typeof id !== "string" || activeIds.has(id)) continue;
|
|
1989
|
+
activeIds.add(id);
|
|
1990
|
+
activeInterrupts.push(normalizeInterruptForClient({
|
|
1991
|
+
id,
|
|
1992
|
+
value: typed?.value,
|
|
1993
|
+
namespace: Array.isArray(typed?.namespace) ? [...typed.namespace] : namespace
|
|
1994
|
+
}));
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
return {
|
|
1998
|
+
activeInterrupts,
|
|
1999
|
+
activeIds
|
|
2000
|
+
};
|
|
2001
|
+
}
|
|
1930
2002
|
//#endregion
|
|
1931
2003
|
export { ROOT_PUMP_CHANNELS, StreamController };
|
|
1932
2004
|
|