@langchain/langgraph 0.2.18 → 0.2.20-rc.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.
@@ -1,7 +1,6 @@
1
1
  /* eslint-disable no-param-reassign */
2
2
  import { Runnable, RunnableSequence, getCallbackManagerForConfig, mergeConfigs, patchConfig, _coerceToRunnable, } from "@langchain/core/runnables";
3
3
  import { compareChannelVersions, copyCheckpoint, emptyCheckpoint, uuid5, } from "@langchain/langgraph-checkpoint";
4
- import Deque from "double-ended-queue";
5
4
  import { createCheckpoint, emptyChannels, isBaseChannel, } from "../channels/base.js";
6
5
  import { PregelNode } from "./read.js";
7
6
  import { validateGraph, validateKeys } from "./validate.js";
@@ -13,7 +12,7 @@ import { GraphRecursionError, GraphValueError, InvalidUpdateError, isGraphInterr
13
12
  import { _prepareNextTasks, _localRead, _applyWrites, } from "./algo.js";
14
13
  import { _coerceToDict, getNewChannelVersions, patchCheckpointMap, } from "./utils/index.js";
15
14
  import { findSubgraphPregel } from "./utils/subgraph.js";
16
- import { PregelLoop, StreamProtocol } from "./loop.js";
15
+ import { PregelLoop, IterableReadableWritableStream } from "./loop.js";
17
16
  import { executeTasksWithRetry } from "./retry.js";
18
17
  import { ChannelKeyPlaceholder, isConfiguredManagedValue, ManagedValueMapping, NoopManagedValue, } from "../managed/base.js";
19
18
  import { gatherIterator, patchConfigurable } from "../utils.js";
@@ -88,6 +87,12 @@ export class Pregel extends Runnable {
88
87
  writable: true,
89
88
  value: ["langgraph", "pregel"]
90
89
  });
90
+ Object.defineProperty(this, "lg_is_pregel", {
91
+ enumerable: true,
92
+ configurable: true,
93
+ writable: true,
94
+ value: true
95
+ });
91
96
  Object.defineProperty(this, "nodes", {
92
97
  enumerable: true,
93
98
  configurable: true,
@@ -204,8 +209,9 @@ export class Pregel extends Runnable {
204
209
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
205
210
  // @ts-ignore Remove ignore when we remove support for 0.2 versions of core
206
211
  withConfig(config) {
212
+ const mergedConfig = mergeConfigs(this.config, config);
207
213
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
208
- return new this.constructor({ ...this, config });
214
+ return new this.constructor({ ...this, config: mergedConfig });
209
215
  }
210
216
  validate() {
211
217
  validateGraph({
@@ -238,6 +244,10 @@ export class Pregel extends Runnable {
238
244
  return Object.keys(this.channels);
239
245
  }
240
246
  }
247
+ async getGraphAsync(config) {
248
+ return this.getGraph(config);
249
+ }
250
+ /** @deprecated Use getSubgraphsAsync instead. The async method will become the default in the next minor release. */
241
251
  *getSubgraphs(namespace, recurse
242
252
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
243
253
  ) {
@@ -275,6 +285,11 @@ export class Pregel extends Runnable {
275
285
  }
276
286
  }
277
287
  }
288
+ async *getSubgraphsAsync(namespace, recurse
289
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
290
+ ) {
291
+ yield* this.getSubgraphs(namespace, recurse);
292
+ }
278
293
  async _prepareStateSnapshot({ config, saved, subgraphCheckpointer, }) {
279
294
  if (saved === undefined) {
280
295
  return {
@@ -288,7 +303,7 @@ export class Pregel extends Runnable {
288
303
  const { managed } = await this.prepareSpecs(config, { skipManaged: true });
289
304
  const channels = emptyChannels(this.channels, saved.checkpoint);
290
305
  const nextTasks = Object.values(_prepareNextTasks(saved.checkpoint, this.nodes, channels, managed, saved.config, false, { step: (saved.metadata?.step ?? -1) + 1 }));
291
- const subgraphs = await gatherIterator(this.getSubgraphs());
306
+ const subgraphs = await gatherIterator(this.getSubgraphsAsync());
292
307
  const parentNamespace = saved.config.configurable?.checkpoint_ns ?? "";
293
308
  const taskStates = {};
294
309
  for (const task of nextTasks) {
@@ -352,7 +367,7 @@ export class Pregel extends Runnable {
352
367
  .split(CHECKPOINT_NAMESPACE_SEPARATOR)
353
368
  .map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0])
354
369
  .join(CHECKPOINT_NAMESPACE_SEPARATOR);
355
- for (const [name, subgraph] of this.getSubgraphs(recastCheckpointNamespace, true)) {
370
+ for await (const [name, subgraph] of this.getSubgraphsAsync(recastCheckpointNamespace, true)) {
356
371
  if (name === recastCheckpointNamespace) {
357
372
  return await subgraph.getState(patchConfigurable(config, {
358
373
  [CONFIG_KEY_CHECKPOINTER]: checkpointer,
@@ -386,7 +401,7 @@ export class Pregel extends Runnable {
386
401
  .map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0])
387
402
  .join(CHECKPOINT_NAMESPACE_SEPARATOR);
388
403
  // find the subgraph with the matching name
389
- for (const [name, pregel] of this.getSubgraphs(recastCheckpointNamespace, true)) {
404
+ for await (const [name, pregel] of this.getSubgraphsAsync(recastCheckpointNamespace, true)) {
390
405
  if (name === recastCheckpointNamespace) {
391
406
  yield* pregel.getStateHistory(patchConfigurable(config, {
392
407
  [CONFIG_KEY_CHECKPOINTER]: checkpointer,
@@ -429,7 +444,7 @@ export class Pregel extends Runnable {
429
444
  .join(CHECKPOINT_NAMESPACE_SEPARATOR);
430
445
  // find the subgraph with the matching name
431
446
  // eslint-disable-next-line no-unreachable-loop
432
- for (const [, pregel] of this.getSubgraphs(recastCheckpointNamespace, true)) {
447
+ for await (const [, pregel] of this.getSubgraphsAsync(recastCheckpointNamespace, true)) {
433
448
  return await pregel.updateState(patchConfigurable(inputConfig, {
434
449
  [CONFIG_KEY_CHECKPOINTER]: checkpointer,
435
450
  }), values, asNode);
@@ -688,15 +703,125 @@ export class Pregel extends Runnable {
688
703
  // assign defaults
689
704
  const [debug, streamMode, , outputKeys, config, interruptBefore, interruptAfter, checkpointer, store,] = this._defaults(inputConfig);
690
705
  const { channelSpecs, managed } = await this.prepareSpecs(config);
706
+ const stream = new IterableReadableWritableStream({
707
+ modes: new Set(streamMode),
708
+ });
691
709
  let loop;
692
- const stream = new Deque();
693
- function* emitCurrentLoopOutputs() {
694
- while (loop !== undefined && stream.length > 0) {
695
- const nextItem = stream.shift();
696
- if (nextItem === undefined) {
710
+ let loopError;
711
+ const runLoop = async () => {
712
+ try {
713
+ loop = await PregelLoop.initialize({
714
+ input,
715
+ config,
716
+ checkpointer,
717
+ nodes: this.nodes,
718
+ channelSpecs,
719
+ managed,
720
+ outputKeys,
721
+ streamKeys: this.streamChannelsAsIs,
722
+ store,
723
+ stream,
724
+ });
725
+ if (options?.subgraphs) {
726
+ loop.config.configurable = {
727
+ ...loop.config.configurable,
728
+ [CONFIG_KEY_STREAM]: loop.stream,
729
+ };
730
+ }
731
+ while (await loop.tick({
732
+ inputKeys: this.inputChannels,
733
+ interruptAfter,
734
+ interruptBefore,
735
+ manager: runManager,
736
+ })) {
737
+ if (debug) {
738
+ printStepCheckpoint(loop.checkpointMetadata.step, loop.channels, this.streamChannelsList);
739
+ }
740
+ if (debug) {
741
+ printStepTasks(loop.step, Object.values(loop.tasks));
742
+ }
743
+ // execute tasks, and wait for one to fail or all to finish.
744
+ // each task is independent from all other concurrent tasks
745
+ // yield updates/debug output as each task finishes
746
+ const taskStream = executeTasksWithRetry(Object.values(loop.tasks).filter((task) => task.writes.length === 0), {
747
+ stepTimeout: this.stepTimeout,
748
+ signal: config.signal,
749
+ retryPolicy: this.retryPolicy,
750
+ });
751
+ // Timeouts will be thrown
752
+ for await (const { task, error } of taskStream) {
753
+ if (error !== undefined) {
754
+ if (isGraphInterrupt(error)) {
755
+ if (loop.isNested) {
756
+ throw error;
757
+ }
758
+ if (error.interrupts.length) {
759
+ loop.putWrites(task.id, error.interrupts.map((interrupt) => [INTERRUPT, interrupt]));
760
+ }
761
+ }
762
+ else {
763
+ loop.putWrites(task.id, [
764
+ [ERROR, { message: error.message, name: error.name }],
765
+ ]);
766
+ }
767
+ }
768
+ else {
769
+ loop.putWrites(task.id, task.writes);
770
+ }
771
+ if (error !== undefined && !isGraphInterrupt(error)) {
772
+ throw error;
773
+ }
774
+ }
775
+ if (debug) {
776
+ printStepWrites(loop.step, Object.values(loop.tasks)
777
+ .map((task) => task.writes)
778
+ .flat(), this.streamChannelsList);
779
+ }
780
+ }
781
+ if (loop.status === "out_of_steps") {
782
+ throw new GraphRecursionError([
783
+ `Recursion limit of ${config.recursionLimit} reached`,
784
+ "without hitting a stop condition. You can increase the",
785
+ `limit by setting the "recursionLimit" config key.`,
786
+ ].join(" "), {
787
+ lc_error_code: "GRAPH_RECURSION_LIMIT",
788
+ });
789
+ }
790
+ }
791
+ catch (e) {
792
+ loopError = e;
793
+ }
794
+ finally {
795
+ try {
796
+ // Call `.stop()` again incase it was not called in the loop, e.g due to an error.
797
+ if (loop) {
798
+ await loop.store?.stop();
799
+ }
800
+ await Promise.all([
801
+ ...(loop?.checkpointerPromises ?? []),
802
+ ...Array.from(managed.values()).map((mv) => mv.promises()),
803
+ ]);
804
+ }
805
+ catch (e) {
806
+ loopError = loopError ?? e;
807
+ }
808
+ if (loopError) {
809
+ // Will throw an error outside of this method
810
+ stream.error(loopError);
811
+ }
812
+ else {
813
+ // Will end the iterator outside of this method
814
+ stream.close();
815
+ }
816
+ }
817
+ };
818
+ const runLoopPromise = runLoop();
819
+ try {
820
+ for await (const chunk of stream) {
821
+ if (chunk === undefined) {
697
822
  throw new Error("Data structure error.");
698
823
  }
699
- const [namespace, mode, payload] = nextItem;
824
+ const [namespace, mode, payload] = chunk;
700
825
  if (streamMode.includes(mode)) {
701
826
  if (streamSubgraphs && streamMode.length > 1) {
702
827
  yield [namespace, mode, payload];
@@ -713,104 +838,14 @@ export class Pregel extends Runnable {
713
838
  }
714
839
  }
715
840
  }
716
- try {
717
- loop = await PregelLoop.initialize({
718
- input,
719
- config,
720
- checkpointer,
721
- nodes: this.nodes,
722
- channelSpecs,
723
- managed,
724
- outputKeys,
725
- streamKeys: this.streamChannelsAsIs,
726
- store,
727
- stream: new StreamProtocol((chunk) => stream.push(chunk), new Set(streamMode)),
728
- });
729
- if (options?.subgraphs) {
730
- loop.config.configurable = {
731
- ...loop.config.configurable,
732
- [CONFIG_KEY_STREAM]: loop.stream,
733
- };
734
- }
735
- while (await loop.tick({
736
- inputKeys: this.inputChannels,
737
- interruptAfter,
738
- interruptBefore,
739
- manager: runManager,
740
- })) {
741
- if (debug) {
742
- printStepCheckpoint(loop.checkpointMetadata.step, loop.channels, this.streamChannelsList);
743
- }
744
- yield* emitCurrentLoopOutputs();
745
- if (debug) {
746
- printStepTasks(loop.step, Object.values(loop.tasks));
747
- }
748
- // execute tasks, and wait for one to fail or all to finish.
749
- // each task is independent from all other concurrent tasks
750
- // yield updates/debug output as each task finishes
751
- const taskStream = executeTasksWithRetry(Object.values(loop.tasks).filter((task) => task.writes.length === 0), {
752
- stepTimeout: this.stepTimeout,
753
- signal: config.signal,
754
- retryPolicy: this.retryPolicy,
755
- });
756
- // Timeouts will be thrown
757
- for await (const { task, error } of taskStream) {
758
- if (error !== undefined) {
759
- if (isGraphInterrupt(error)) {
760
- if (loop.isNested) {
761
- throw error;
762
- }
763
- if (error.interrupts.length) {
764
- loop.putWrites(task.id, error.interrupts.map((interrupt) => [INTERRUPT, interrupt]));
765
- }
766
- }
767
- else {
768
- loop.putWrites(task.id, [
769
- [ERROR, { message: error.message, name: error.name }],
770
- ]);
771
- }
772
- }
773
- else {
774
- loop.putWrites(task.id, task.writes);
775
- }
776
- yield* emitCurrentLoopOutputs();
777
- if (error !== undefined && !isGraphInterrupt(error)) {
778
- throw error;
779
- }
780
- }
781
- if (debug) {
782
- printStepWrites(loop.step, Object.values(loop.tasks)
783
- .map((task) => task.writes)
784
- .flat(), this.streamChannelsList);
785
- }
786
- }
787
- yield* emitCurrentLoopOutputs();
788
- if (loop.status === "out_of_steps") {
789
- throw new GraphRecursionError([
790
- `Recursion limit of ${config.recursionLimit} reached`,
791
- "without hitting a stop condition. You can increase the",
792
- `limit by setting the "recursionLimit" config key.`,
793
- ].join(" "), {
794
- lc_error_code: "GRAPH_RECURSION_LIMIT",
795
- });
796
- }
797
- await Promise.all(loop?.checkpointerPromises ?? []);
798
- await runManager?.handleChainEnd(loop.output);
799
- }
800
841
  catch (e) {
801
- await runManager?.handleChainError(e);
842
+ await runManager?.handleChainError(loopError);
802
843
  throw e;
803
844
  }
804
845
  finally {
805
- // Call `.stop()` again incase it was not called in the loop, e.g due to an error.
806
- if (loop) {
807
- await loop.store?.stop();
808
- }
809
- await Promise.all([
810
- ...(loop?.checkpointerPromises ?? []),
811
- ...Array.from(managed.values()).map((mv) => mv.promises()),
812
- ]);
846
+ await runLoopPromise;
813
847
  }
848
+ await runManager?.handleChainEnd(loop?.output ?? {});
814
849
  }
815
850
  /**
816
851
  * Run the graph with a single input and config.
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PregelLoop = exports.StreamProtocol = void 0;
3
+ exports.PregelLoop = exports.IterableReadableWritableStream = void 0;
4
+ const stream_1 = require("@langchain/core/utils/stream");
4
5
  const langgraph_checkpoint_1 = require("@langchain/langgraph-checkpoint");
5
6
  const base_js_1 = require("../channels/base.cjs");
6
7
  const constants_js_1 = require("../constants.cjs");
@@ -14,33 +15,72 @@ const INPUT_DONE = Symbol.for("INPUT_DONE");
14
15
  const INPUT_RESUMING = Symbol.for("INPUT_RESUMING");
15
16
  const DEFAULT_LOOP_LIMIT = 25;
16
17
  const SPECIAL_CHANNELS = [constants_js_1.ERROR, constants_js_1.INTERRUPT];
17
- class StreamProtocol {
18
- constructor(pushFn, modes) {
19
- Object.defineProperty(this, "push", {
18
+ class IterableReadableWritableStream extends stream_1.IterableReadableStream {
19
+ constructor(params) {
20
+ let streamControllerPromiseResolver;
21
+ let streamControllerPromise = new Promise((resolve) => {
22
+ streamControllerPromiseResolver = resolve;
23
+ });
24
+ super({
25
+ start: (controller) => {
26
+ streamControllerPromiseResolver(controller);
27
+ },
28
+ });
29
+ Object.defineProperty(this, "modes", {
20
30
  enumerable: true,
21
31
  configurable: true,
22
32
  writable: true,
23
33
  value: void 0
24
34
  });
25
- Object.defineProperty(this, "modes", {
35
+ Object.defineProperty(this, "controller", {
36
+ enumerable: true,
37
+ configurable: true,
38
+ writable: true,
39
+ value: void 0
40
+ });
41
+ Object.defineProperty(this, "passthroughFn", {
26
42
  enumerable: true,
27
43
  configurable: true,
28
44
  writable: true,
29
45
  value: void 0
30
46
  });
31
- this.push = pushFn;
32
- this.modes = modes;
47
+ // .start() will always be called before the stream can be interacted
48
+ // with anyway
49
+ streamControllerPromise.then((controller) => {
50
+ this.controller = controller;
51
+ });
52
+ this.passthroughFn = params.passthroughFn;
53
+ this.modes = params.modes;
54
+ }
55
+ push(chunk) {
56
+ this.passthroughFn?.(chunk);
57
+ this.controller.enqueue(chunk);
58
+ }
59
+ close() {
60
+ try {
61
+ this.controller.close();
62
+ }
63
+ catch (e) {
64
+ // pass
65
+ }
66
+ }
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ error(e) {
69
+ this.controller.error(e);
33
70
  }
34
71
  }
35
- exports.StreamProtocol = StreamProtocol;
72
+ exports.IterableReadableWritableStream = IterableReadableWritableStream;
36
73
  function createDuplexStream(...streams) {
37
- return new StreamProtocol((value) => {
38
- for (const stream of streams) {
39
- if (stream.modes.has(value[1])) {
40
- stream.push(value);
74
+ return new IterableReadableWritableStream({
75
+ passthroughFn: (value) => {
76
+ for (const stream of streams) {
77
+ if (stream.modes.has(value[1])) {
78
+ stream.push(value);
79
+ }
41
80
  }
42
- }
43
- }, new Set(streams.flatMap((s) => Array.from(s.modes))));
81
+ },
82
+ modes: new Set(streams.flatMap((s) => Array.from(s.modes))),
83
+ });
44
84
  }
45
85
  class PregelLoop {
46
86
  constructor(params) {
@@ -1,5 +1,6 @@
1
1
  import type { RunnableConfig } from "@langchain/core/runnables";
2
2
  import type { CallbackManagerForChainRun } from "@langchain/core/callbacks/manager";
3
+ import { IterableReadableStream } from "@langchain/core/utils/stream";
3
4
  import { BaseCheckpointSaver, Checkpoint, PendingWrite, CheckpointPendingWrite, CheckpointMetadata, All, BaseStore, AsyncBatchedStore } from "@langchain/langgraph-checkpoint";
4
5
  import { BaseChannel } from "../channels/base.js";
5
6
  import { PregelExecutableTask, StreamMode } from "./types.js";
@@ -16,7 +17,7 @@ export type PregelLoopInitializeParams = {
16
17
  nodes: Record<string, PregelNode>;
17
18
  channelSpecs: Record<string, BaseChannel>;
18
19
  managed: ManagedValueMapping;
19
- stream: StreamProtocol;
20
+ stream: IterableReadableWritableStream;
20
21
  store?: BaseStore;
21
22
  checkSubgraphs?: boolean;
22
23
  };
@@ -39,14 +40,21 @@ type PregelLoopParams = {
39
40
  checkpointNamespace: string[];
40
41
  skipDoneTasks: boolean;
41
42
  isNested: boolean;
42
- stream: StreamProtocol;
43
+ stream: IterableReadableWritableStream;
43
44
  store?: AsyncBatchedStore;
44
45
  prevCheckpointConfig: RunnableConfig | undefined;
45
46
  };
46
- export declare class StreamProtocol {
47
- push: (chunk: StreamChunk) => void;
47
+ export declare class IterableReadableWritableStream extends IterableReadableStream<StreamChunk> {
48
48
  modes: Set<StreamMode>;
49
- constructor(pushFn: (chunk: StreamChunk) => void, modes: Set<StreamMode>);
49
+ private controller;
50
+ private passthroughFn?;
51
+ constructor(params: {
52
+ passthroughFn?: (chunk: StreamChunk) => void;
53
+ modes: Set<StreamMode>;
54
+ });
55
+ push(chunk: StreamChunk): void;
56
+ close(): void;
57
+ error(e: any): void;
50
58
  }
51
59
  export declare class PregelLoop {
52
60
  protected input?: any;
@@ -72,7 +80,7 @@ export declare class PregelLoop {
72
80
  protected prevCheckpointConfig: RunnableConfig | undefined;
73
81
  status: "pending" | "done" | "interrupt_before" | "interrupt_after" | "out_of_steps";
74
82
  tasks: Record<string, PregelExecutableTask<any, any>>;
75
- stream: StreamProtocol;
83
+ stream: IterableReadableWritableStream;
76
84
  checkpointerPromises: Promise<unknown>[];
77
85
  isNested: boolean;
78
86
  protected _checkpointerChainedPromise: Promise<unknown>;
@@ -1,3 +1,4 @@
1
+ import { IterableReadableStream } from "@langchain/core/utils/stream";
1
2
  import { copyCheckpoint, emptyCheckpoint, AsyncBatchedStore, } from "@langchain/langgraph-checkpoint";
2
3
  import { createCheckpoint, emptyChannels, } from "../channels/base.js";
3
4
  import { CHECKPOINT_NAMESPACE_SEPARATOR, CONFIG_KEY_CHECKPOINT_MAP, CONFIG_KEY_READ, CONFIG_KEY_RESUMING, CONFIG_KEY_STREAM, ERROR, INPUT, INTERRUPT, TAG_HIDDEN, TASKS, } from "../constants.js";
@@ -11,32 +12,71 @@ const INPUT_DONE = Symbol.for("INPUT_DONE");
11
12
  const INPUT_RESUMING = Symbol.for("INPUT_RESUMING");
12
13
  const DEFAULT_LOOP_LIMIT = 25;
13
14
  const SPECIAL_CHANNELS = [ERROR, INTERRUPT];
14
- export class StreamProtocol {
15
- constructor(pushFn, modes) {
16
- Object.defineProperty(this, "push", {
15
+ export class IterableReadableWritableStream extends IterableReadableStream {
16
+ constructor(params) {
17
+ let streamControllerPromiseResolver;
18
+ let streamControllerPromise = new Promise((resolve) => {
19
+ streamControllerPromiseResolver = resolve;
20
+ });
21
+ super({
22
+ start: (controller) => {
23
+ streamControllerPromiseResolver(controller);
24
+ },
25
+ });
26
+ Object.defineProperty(this, "modes", {
17
27
  enumerable: true,
18
28
  configurable: true,
19
29
  writable: true,
20
30
  value: void 0
21
31
  });
22
- Object.defineProperty(this, "modes", {
32
+ Object.defineProperty(this, "controller", {
33
+ enumerable: true,
34
+ configurable: true,
35
+ writable: true,
36
+ value: void 0
37
+ });
38
+ Object.defineProperty(this, "passthroughFn", {
23
39
  enumerable: true,
24
40
  configurable: true,
25
41
  writable: true,
26
42
  value: void 0
27
43
  });
28
- this.push = pushFn;
29
- this.modes = modes;
44
+ // .start() will always be called before the stream can be interacted
45
+ // with anyway
46
+ streamControllerPromise.then((controller) => {
47
+ this.controller = controller;
48
+ });
49
+ this.passthroughFn = params.passthroughFn;
50
+ this.modes = params.modes;
51
+ }
52
+ push(chunk) {
53
+ this.passthroughFn?.(chunk);
54
+ this.controller.enqueue(chunk);
55
+ }
56
+ close() {
57
+ try {
58
+ this.controller.close();
59
+ }
60
+ catch (e) {
61
+ // pass
62
+ }
63
+ }
64
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
+ error(e) {
66
+ this.controller.error(e);
30
67
  }
31
68
  }
32
69
  function createDuplexStream(...streams) {
33
- return new StreamProtocol((value) => {
34
- for (const stream of streams) {
35
- if (stream.modes.has(value[1])) {
36
- stream.push(value);
70
+ return new IterableReadableWritableStream({
71
+ passthroughFn: (value) => {
72
+ for (const stream of streams) {
73
+ if (stream.modes.has(value[1])) {
74
+ stream.push(value);
75
+ }
37
76
  }
38
- }
39
- }, new Set(streams.flatMap((s) => Array.from(s.modes))));
77
+ },
78
+ modes: new Set(streams.flatMap((s) => Array.from(s.modes))),
79
+ });
40
80
  }
41
81
  export class PregelLoop {
42
82
  constructor(params) {