@langchain/langgraph-sdk 1.10.3-rc.1 → 1.10.3-rc.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/index.cjs +23 -1
- package/dist/client/stream/index.cjs.map +1 -1
- package/dist/client/stream/index.d.cts +6 -0
- package/dist/client/stream/index.d.cts.map +1 -1
- package/dist/client/stream/index.d.ts +6 -0
- package/dist/client/stream/index.d.ts.map +1 -1
- package/dist/client/stream/index.js +23 -1
- package/dist/client/stream/index.js.map +1 -1
- package/dist/client/stream/transport/http.cjs +14 -3
- 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 +14 -3
- package/dist/client/stream/transport/http.js.map +1 -1
- package/dist/stream/controller.cjs +79 -27
- 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 +79 -27
- package/dist/stream/controller.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.cts","names":[],"sources":["../../src/stream/controller.ts"],"mappings":";;;;;;;;;;;;;;AA6KA;;cAAa,kBAAA,WAA6B,OAAA;;
|
|
1
|
+
{"version":3,"file":"controller.d.cts","names":[],"sources":["../../src/stream/controller.ts"],"mappings":";;;;;;;;;;;;;;AA6KA;;cAAa,kBAAA,WAA6B,OAAA;;AAwC1C;;;;;;;;;;;;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;EAiK0B;;;;;EAA7C,WAAA,CAAY,OAAA,EAAS,uBAAA,CAAwB,SAAA;EAiyBF;;;;;;;EAAA,IAtqBvC,gBAAA,CAAA,GAAoB,OAAA;EA20BS;;;;;;;;EAlxB3B,OAAA,CAAQ,QAAA,mBAA2B,OAAA;EAogCpB;;;;;;;;;;;;;;EA7pBf,wBAAA,CAAyB,UAAA,WAAqB,OAAA;EAjsB5B;;;;;;;;EAq8BlB,MAAA,CACJ,KAAA,WACA,OAAA,GAAU,mBAAA,CAAoB,SAAA,EAAW,gBAAA,IACxC,OAAA;EAr8B4B;;;;;;EA+8BzB,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EA78BtB;;;;EAi+Bb,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;;;
|
|
1
|
+
{"version":3,"file":"controller.d.ts","names":[],"sources":["../../src/stream/controller.ts"],"mappings":";;;;;;;;;;;;;;;AA6KA;cAAa,kBAAA,WAA6B,OAAA;;;AAwC1C;;;;;;;;;;;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;;;;;EAiKnB,WAAA,CAAY,OAAA,EAAS,uBAAA,CAAwB,SAAA;EAiyBb;;;;;;;EAAA,IAtqB5B,gBAAA,CAAA,GAAoB,OAAA;EA4wBJ;;;;;;;;EAntBd,OAAA,CAAQ,QAAA,mBAA2B,OAAA;EAw/B5B;;;;;;;;;;;;;;EAjpBP,wBAAA,CAAyB,UAAA,WAAqB,OAAA;EAjsB3C;;;;;;;;EAq8BH,MAAA,CACJ,KAAA,WACA,OAAA,GAAU,mBAAA,CAAoB,SAAA,EAAW,gBAAA,IACxC,OAAA;EAr8BM;;;;;;EA+8BH,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EA78BhC;;;;EAi+BH,UAAA,CAAA,GAAc,OAAA;EAh0BR;;;;;;;;;;;EAg4BN,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"}
|
|
@@ -104,6 +104,8 @@ const ROOT_PUMP_CHANNELS = [
|
|
|
104
104
|
"messages",
|
|
105
105
|
"tools"
|
|
106
106
|
];
|
|
107
|
+
const PARKED_INTERRUPT_SETTLE_MS = 5e3;
|
|
108
|
+
const PARKED_INTERRUPT_SETTLE_POLL_MS = 500;
|
|
107
109
|
/**
|
|
108
110
|
* Coordinates one thread's protocol-v2 stream and exposes stable
|
|
109
111
|
* observable projections for framework bindings.
|
|
@@ -142,6 +144,7 @@ var StreamController = class {
|
|
|
142
144
|
*/
|
|
143
145
|
#rootPumpDeferred = false;
|
|
144
146
|
#threadEventUnsubscribe;
|
|
147
|
+
#threadErrorUnsubscribe;
|
|
145
148
|
#disposed = false;
|
|
146
149
|
#pendingDisposeTimer = null;
|
|
147
150
|
/**
|
|
@@ -166,17 +169,16 @@ var StreamController = class {
|
|
|
166
169
|
* than {@link #interruptReplayThroughSeq} bypass the allowlist.
|
|
167
170
|
*/
|
|
168
171
|
#hydratedActiveInterruptIds = null;
|
|
169
|
-
/** Checkpoint whose replay establishes the hydrate-time interrupt cutoff. */
|
|
170
|
-
#hydratedInterruptCheckpointId;
|
|
171
172
|
/**
|
|
172
|
-
* Highest event sequence
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
173
|
+
* Highest event sequence already applied when the latest run command
|
|
174
|
+
* was accepted. Interrupts outside the hydrate-time allowlist remain
|
|
175
|
+
* filtered through this sequence, while newer events are live output
|
|
176
|
+
* from the newly-started run and must be accepted.
|
|
176
177
|
*/
|
|
177
178
|
#interruptReplayThroughSeq;
|
|
178
|
-
/** Unknown inputs waiting
|
|
179
|
+
/** Unknown inputs waiting to be classified as live or replayed history. */
|
|
179
180
|
#pendingHydrationInterruptEvents = [];
|
|
181
|
+
#settleParkedInterruptsPromise;
|
|
180
182
|
/**
|
|
181
183
|
* Unknown interrupt events received between local command dispatch and its
|
|
182
184
|
* response. The response supplies the sequence barrier needed to classify
|
|
@@ -330,7 +332,6 @@ var StreamController = class {
|
|
|
330
332
|
this.#interruptCommandPending = this.#hydratedActiveInterruptIds != null;
|
|
331
333
|
this.#pendingInterruptEvents = this.#pendingHydrationInterruptEvents;
|
|
332
334
|
this.#pendingHydrationInterruptEvents = [];
|
|
333
|
-
this.#hydratedInterruptCheckpointId = void 0;
|
|
334
335
|
},
|
|
335
336
|
onRunStart: () => this.#markLocalRunStart(),
|
|
336
337
|
onRunCreated: (runId) => {
|
|
@@ -581,7 +582,6 @@ var StreamController = class {
|
|
|
581
582
|
}));
|
|
582
583
|
if (this.#submitGeneration === generationAtFetch) {
|
|
583
584
|
this.#hydratedActiveInterruptIds = activeIds;
|
|
584
|
-
this.#hydratedInterruptCheckpointId = state.checkpoint?.checkpoint_id ?? void 0;
|
|
585
585
|
this.#interruptReplayThroughSeq = void 0;
|
|
586
586
|
}
|
|
587
587
|
}
|
|
@@ -1286,6 +1286,8 @@ var StreamController = class {
|
|
|
1286
1286
|
this.registry.bind(void 0);
|
|
1287
1287
|
this.#threadEventUnsubscribe?.();
|
|
1288
1288
|
this.#threadEventUnsubscribe = void 0;
|
|
1289
|
+
this.#threadErrorUnsubscribe?.();
|
|
1290
|
+
this.#threadErrorUnsubscribe = void 0;
|
|
1289
1291
|
/**
|
|
1290
1292
|
* Persistent lifecycle driver is scoped to the current thread
|
|
1291
1293
|
* stream. Remove it so a swap to a new thread starts with a clean
|
|
@@ -1313,7 +1315,6 @@ var StreamController = class {
|
|
|
1313
1315
|
this.#localRunDepth = 0;
|
|
1314
1316
|
this.#messageMetadata.reset();
|
|
1315
1317
|
this.#hydratedActiveInterruptIds = null;
|
|
1316
|
-
this.#hydratedInterruptCheckpointId = void 0;
|
|
1317
1318
|
this.#interruptReplayThroughSeq = void 0;
|
|
1318
1319
|
this.#pendingHydrationInterruptEvents = [];
|
|
1319
1320
|
this.#discardPendingInterruptEvents();
|
|
@@ -1362,6 +1363,13 @@ var StreamController = class {
|
|
|
1362
1363
|
* pump's narrow filter.
|
|
1363
1364
|
*/
|
|
1364
1365
|
this.#threadEventUnsubscribe = thread.onEvent((event) => this.#onWildcardEvent(event));
|
|
1366
|
+
this.#threadErrorUnsubscribe = thread.onError((error) => {
|
|
1367
|
+
this.rootStore.setState((s) => ({
|
|
1368
|
+
...s,
|
|
1369
|
+
error,
|
|
1370
|
+
isLoading: false
|
|
1371
|
+
}));
|
|
1372
|
+
});
|
|
1365
1373
|
/**
|
|
1366
1374
|
* Persistent isLoading driver. Drives `isLoading` from
|
|
1367
1375
|
* root-namespace lifecycle events so that in-flight runs observed
|
|
@@ -1491,7 +1499,6 @@ var StreamController = class {
|
|
|
1491
1499
|
} catch {}
|
|
1492
1500
|
this.#subgraphs.push(event);
|
|
1493
1501
|
this.#lifecycleLoading.handle(event);
|
|
1494
|
-
this.#advanceInterruptReplayBarrierFromCheckpoint(event);
|
|
1495
1502
|
/**
|
|
1496
1503
|
* `input.requested` events (including HITL inside a subagent /
|
|
1497
1504
|
* subgraph) are not always observable via the narrow content pump.
|
|
@@ -1501,6 +1508,7 @@ var StreamController = class {
|
|
|
1501
1508
|
* resume targeting.
|
|
1502
1509
|
*/
|
|
1503
1510
|
this.#recordInterrupt(event);
|
|
1511
|
+
this.#settleParkedInterruptsOnTerminal(event);
|
|
1504
1512
|
}
|
|
1505
1513
|
/**
|
|
1506
1514
|
* Process one root-pump event and update all root projections.
|
|
@@ -1741,11 +1749,12 @@ var StreamController = class {
|
|
|
1741
1749
|
this.#pendingInterruptEvents.push(event);
|
|
1742
1750
|
return;
|
|
1743
1751
|
}
|
|
1744
|
-
|
|
1752
|
+
const barrier = this.#interruptReplayThroughSeq;
|
|
1753
|
+
if (isUnknownInterrupt && barrier == null) {
|
|
1745
1754
|
this.#pendingHydrationInterruptEvents.push(event);
|
|
1746
1755
|
return;
|
|
1747
1756
|
}
|
|
1748
|
-
if (isUnknownInterrupt &&
|
|
1757
|
+
if (isUnknownInterrupt && barrier != null && eventSeq != null && eventSeq <= barrier) return;
|
|
1749
1758
|
const namespace = Array.isArray(event.params.namespace) ? [...event.params.namespace] : [...ROOT_NAMESPACE];
|
|
1750
1759
|
const interrupt = normalizeInterruptForClient({
|
|
1751
1760
|
id: interruptId,
|
|
@@ -1762,16 +1771,6 @@ var StreamController = class {
|
|
|
1762
1771
|
};
|
|
1763
1772
|
});
|
|
1764
1773
|
}
|
|
1765
|
-
/** Establish the hydration cutoff when ordered replay reaches its checkpoint. */
|
|
1766
|
-
#advanceInterruptReplayBarrierFromCheckpoint(event) {
|
|
1767
|
-
if (event.method !== "checkpoints" || this.#hydratedInterruptCheckpointId == null || !isRootNamespace(event.params.namespace)) return;
|
|
1768
|
-
if (event.params.data?.id !== this.#hydratedInterruptCheckpointId || typeof event.seq !== "number") return;
|
|
1769
|
-
this.#interruptReplayThroughSeq = event.seq;
|
|
1770
|
-
this.#hydratedInterruptCheckpointId = void 0;
|
|
1771
|
-
const pendingEvents = this.#pendingHydrationInterruptEvents.sort((a, b) => (a.seq ?? 0) - (b.seq ?? 0));
|
|
1772
|
-
this.#pendingHydrationInterruptEvents = [];
|
|
1773
|
-
for (const pendingEvent of pendingEvents) this.#recordInterrupt(pendingEvent);
|
|
1774
|
-
}
|
|
1775
1774
|
/**
|
|
1776
1775
|
* Convert the hydrate-time allowlist into a replay barrier after a command
|
|
1777
1776
|
* is accepted. Built-in transports update `lastAppliedThroughSeq` from the
|
|
@@ -1848,12 +1847,12 @@ var StreamController = class {
|
|
|
1848
1847
|
*/
|
|
1849
1848
|
async #reconcilePendingInterruptsFromServer() {
|
|
1850
1849
|
const threadId = this.#currentThreadId;
|
|
1851
|
-
if (threadId == null || this.#disposed) return;
|
|
1850
|
+
if (threadId == null || this.#disposed) return null;
|
|
1852
1851
|
const generationAtFetch = this.#submitGeneration;
|
|
1853
1852
|
try {
|
|
1854
1853
|
const state = await this.#fetchHydrationState();
|
|
1855
|
-
if (this.#disposed || this.#currentThreadId !== threadId || this.#submitGeneration !== generationAtFetch) return;
|
|
1856
|
-
if (!Array.isArray(state?.tasks)) return;
|
|
1854
|
+
if (this.#disposed || this.#currentThreadId !== threadId || this.#submitGeneration !== generationAtFetch) return null;
|
|
1855
|
+
if (!Array.isArray(state?.tasks)) return null;
|
|
1857
1856
|
const { activeInterrupts, activeIds } = collectActiveInterruptsFromTasks(state.tasks);
|
|
1858
1857
|
const pendingInterrupts = activeInterrupts.filter((interrupt) => interrupt.id == null || !this.#resolvedInterrupts.has(interrupt.id));
|
|
1859
1858
|
this.rootStore.setState((s) => ({
|
|
@@ -1862,7 +1861,55 @@ var StreamController = class {
|
|
|
1862
1861
|
interrupt: pendingInterrupts[0]
|
|
1863
1862
|
}));
|
|
1864
1863
|
this.#hydratedActiveInterruptIds = activeIds;
|
|
1865
|
-
|
|
1864
|
+
return state;
|
|
1865
|
+
} catch {
|
|
1866
|
+
return null;
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
#settleParkedInterruptsOnTerminal(event) {
|
|
1870
|
+
if (this.#pendingHydrationInterruptEvents.length === 0) return;
|
|
1871
|
+
if (event.method !== "lifecycle") return;
|
|
1872
|
+
if (!isRootNamespace(event.params.namespace)) return;
|
|
1873
|
+
const status = event.params.data?.event;
|
|
1874
|
+
if (status !== "interrupted" && status !== "completed" && status !== "failed") return;
|
|
1875
|
+
this.#settleParkedInterrupts();
|
|
1876
|
+
}
|
|
1877
|
+
/**
|
|
1878
|
+
* Decide parked interrupts with server state instead of a stream marker.
|
|
1879
|
+
*
|
|
1880
|
+
* After a passive rejoin the stream cannot tell a replayed, already
|
|
1881
|
+
* resolved `input.requested` from one the current run just raised: the
|
|
1882
|
+
* SSE replays the thread buffer on connect with no marker for where the
|
|
1883
|
+
* replay ends. `state.tasks[].interrupts` is authoritative: parked ids it
|
|
1884
|
+
* lists are live, the rest are history.
|
|
1885
|
+
*/
|
|
1886
|
+
async #settleParkedInterrupts() {
|
|
1887
|
+
const makePromise = async () => {
|
|
1888
|
+
try {
|
|
1889
|
+
const threadId = this.#currentThreadId;
|
|
1890
|
+
const generation = this.#submitGeneration;
|
|
1891
|
+
const deadline = Date.now() + PARKED_INTERRUPT_SETTLE_MS;
|
|
1892
|
+
for (;;) {
|
|
1893
|
+
if (this.#disposed || this.#currentThreadId !== threadId || this.#submitGeneration !== generation || this.#pendingHydrationInterruptEvents.length === 0) return;
|
|
1894
|
+
const parkedIds = new Set(this.#pendingHydrationInterruptEvents.map((event) => event.params.data.interrupt_id));
|
|
1895
|
+
const state = await this.#reconcilePendingInterruptsFromServer();
|
|
1896
|
+
if (state != null) {
|
|
1897
|
+
if ([...this.#hydratedActiveInterruptIds ?? []].some((id) => parkedIds.has(id)) || !isThreadStateActive(state)) {
|
|
1898
|
+
this.#pendingHydrationInterruptEvents = [];
|
|
1899
|
+
return;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
if (Date.now() >= deadline) return;
|
|
1903
|
+
await new Promise((resolve) => {
|
|
1904
|
+
setTimeout(resolve, PARKED_INTERRUPT_SETTLE_POLL_MS);
|
|
1905
|
+
});
|
|
1906
|
+
}
|
|
1907
|
+
} finally {
|
|
1908
|
+
this.#settleParkedInterruptsPromise = void 0;
|
|
1909
|
+
}
|
|
1910
|
+
};
|
|
1911
|
+
this.#settleParkedInterruptsPromise ??= makePromise();
|
|
1912
|
+
return this.#settleParkedInterruptsPromise;
|
|
1866
1913
|
}
|
|
1867
1914
|
/**
|
|
1868
1915
|
* Resolve on the next root-namespace terminal lifecycle event
|
|
@@ -1908,6 +1955,7 @@ var StreamController = class {
|
|
|
1908
1955
|
settled = true;
|
|
1909
1956
|
unsubscribeRoot?.();
|
|
1910
1957
|
unsubscribeThread?.();
|
|
1958
|
+
unsubscribeError?.();
|
|
1911
1959
|
signal.removeEventListener("abort", finishAborted);
|
|
1912
1960
|
resolve(result);
|
|
1913
1961
|
}
|
|
@@ -1933,6 +1981,10 @@ var StreamController = class {
|
|
|
1933
1981
|
};
|
|
1934
1982
|
const unsubscribeRoot = this.#rootBus.subscribe(onEvent);
|
|
1935
1983
|
const unsubscribeThread = this.#thread?.onEvent(onEvent);
|
|
1984
|
+
const unsubscribeError = this.#thread?.onError((error) => finish({
|
|
1985
|
+
event: "failed",
|
|
1986
|
+
error: error.message
|
|
1987
|
+
}));
|
|
1936
1988
|
if (signal.aborted) finishAborted();
|
|
1937
1989
|
else signal.addEventListener("abort", finishAborted, { once: true });
|
|
1938
1990
|
});
|