@langgraph-js/pure-graph 3.1.2 → 3.2.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.
Files changed (31) hide show
  1. package/dist/adapter/fetch/index.js +128 -30
  2. package/dist/adapter/fetch/index.js.map +1 -1
  3. package/dist/adapter/fetch/utils.d.ts +13 -3
  4. package/dist/adapter/nextjs/index.js +1 -1
  5. package/dist/{checkpoint-1sAx_j1E.js → checkpoint-CY59Lr2q.js} +79 -36
  6. package/dist/checkpoint-CY59Lr2q.js.map +1 -0
  7. package/dist/{createEndpoint-D1nfguxg.js → createEndpoint-vMmFiMSz.js} +20 -5
  8. package/dist/createEndpoint-vMmFiMSz.js.map +1 -0
  9. package/dist/createEndpoint.d.ts +2 -1
  10. package/dist/index.js +2 -2
  11. package/dist/queue/stream_queue.d.ts +3 -1
  12. package/dist/{queue-Cu_nO_wt.js → queue-CUe5TDP1.js} +120 -16
  13. package/dist/queue-CUe5TDP1.js.map +1 -0
  14. package/dist/remote/index.js +1 -1
  15. package/dist/shallow-checkpoint-ImbLxYNR.js +466 -0
  16. package/dist/shallow-checkpoint-ImbLxYNR.js.map +1 -0
  17. package/dist/{sqlite-adapter-BKOLSdoL.js → sqlite-adapter-CJXgit1j.js} +25 -12
  18. package/dist/sqlite-adapter-CJXgit1j.js.map +1 -0
  19. package/dist/storage/index.d.ts +4 -2
  20. package/dist/storage/kysely/sqlite-adapter.d.ts +7 -0
  21. package/dist/storage/memory/queue.d.ts +6 -0
  22. package/dist/storage/redis/queue.d.ts +14 -1
  23. package/dist/storage/sqlite/shallow-checkpoint.d.ts +59 -0
  24. package/dist/{stream-CsqWsCjt.js → stream-jYlUzTZO.js} +199 -64
  25. package/dist/stream-jYlUzTZO.js.map +1 -0
  26. package/package.json +2 -1
  27. package/dist/checkpoint-1sAx_j1E.js.map +0 -1
  28. package/dist/createEndpoint-D1nfguxg.js.map +0 -1
  29. package/dist/queue-Cu_nO_wt.js.map +0 -1
  30. package/dist/sqlite-adapter-BKOLSdoL.js.map +0 -1
  31. package/dist/stream-CsqWsCjt.js.map +0 -1
@@ -5,6 +5,7 @@ import { EventEmitter } from 'eventemitter3';
5
5
  import { load } from '@langchain/core/load';
6
6
  import { v7 } from 'uuid';
7
7
  import { BaseCheckpointSaver, TASKS, maxChannelVersion, getCheckpointId, copyCheckpoint, uuid6, WRITES_IDX_MAP } from '@langchain/langgraph-checkpoint';
8
+ import 'kysely';
8
9
 
9
10
  const getLangGraphCommand = (command) => {
10
11
  let goto = command.goto != null && !Array.isArray(command.goto) ? [command.goto] : command.goto;
@@ -320,11 +321,7 @@ class StreamQueueManager {
320
321
  * @param id 队列 ID / Queue ID
321
322
  */
322
323
  async cancelQueue(id) {
323
- const queue = this.queues.get(id);
324
- if (queue) {
325
- await queue.cancel();
326
- this.removeQueue(id);
327
- }
324
+ await this.removeQueue(id);
328
325
  }
329
326
  /**
330
327
  * 向指定 id 的队列推送数据
@@ -369,10 +366,32 @@ class StreamQueueManager {
369
366
  * @param id 队列 ID / Queue ID
370
367
  * @returns 是否成功删除 / Whether successfully deleted
371
368
  */
372
- removeQueue(id) {
373
- setTimeout(() => {
374
- return this.queues.delete(id);
375
- }, 500);
369
+ async removeQueue(id) {
370
+ const queue = this.queues.get(id);
371
+ if (!queue) {
372
+ return false;
373
+ }
374
+ try {
375
+ await queue.cancel();
376
+ } catch (e) {
377
+ console.error("Error cancelling queue:", e);
378
+ }
379
+ try {
380
+ const clearResult = queue.clear();
381
+ if (clearResult instanceof Promise) {
382
+ await clearResult;
383
+ }
384
+ } catch (e) {
385
+ console.error("Error clearing queue:", e);
386
+ }
387
+ if (typeof queue.destroy === "function") {
388
+ try {
389
+ await queue.destroy();
390
+ } catch (e) {
391
+ console.error("Error destroying queue:", e);
392
+ }
393
+ }
394
+ return this.queues.delete(id);
376
395
  }
377
396
  /**
378
397
  * 获取所有队列的 ID
@@ -447,15 +466,29 @@ class KyselyThreadsManager {
447
466
  }
448
467
  async create(payload) {
449
468
  const threadId = payload?.threadId || v7();
469
+ const now = /* @__PURE__ */ new Date();
470
+ const metadata = payload?.metadata || {};
471
+ const interrupts = {};
450
472
  if (payload?.ifExists === "raise") {
451
473
  const existing = await this.db.selectFrom("threads").select("thread_id").where("thread_id", "=", threadId).executeTakeFirst();
452
474
  if (existing) {
453
475
  throw new Error(`Thread with ID ${threadId} already exists.`);
454
476
  }
455
477
  }
456
- const now = /* @__PURE__ */ new Date();
457
- const metadata = payload?.metadata || {};
458
- const interrupts = {};
478
+ if (payload?.ifExists === "do_nothing" && payload?.threadId) {
479
+ const existing = await this.db.selectFrom("threads").selectAll().where("thread_id", "=", threadId).executeTakeFirst();
480
+ if (existing) {
481
+ return {
482
+ thread_id: existing.thread_id,
483
+ created_at: this.adapter.dbToDate(existing.created_at).toISOString(),
484
+ updated_at: this.adapter.dbToDate(existing.updated_at).toISOString(),
485
+ metadata: this.adapter.dbToJson(existing.metadata),
486
+ status: existing.status,
487
+ values: existing.values ? this.adapter.dbToJson(existing.values) : null,
488
+ interrupts: this.adapter.dbToJson(existing.interrupts)
489
+ };
490
+ }
491
+ }
459
492
  await this.db.insertInto("threads").values({
460
493
  thread_id: threadId,
461
494
  created_at: this.adapter.dateToDb(now),
@@ -595,10 +628,17 @@ class KyselyThreadsManager {
595
628
  if (targetThread.status === "busy") {
596
629
  throw new Error(`Thread with ID ${threadId} is busy, can't update state.`);
597
630
  }
598
- if (!targetThread.metadata?.graph_id) {
599
- throw new Error(`Thread with ID ${threadId} has no graph_id.`);
600
- }
601
631
  const graphId = targetThread.metadata?.graph_id;
632
+ if (!graphId) {
633
+ await this.set(threadId, {
634
+ values: thread.values ?? null
635
+ });
636
+ return {
637
+ configurable: {
638
+ thread_id: threadId
639
+ }
640
+ };
641
+ }
602
642
  const config = {
603
643
  configurable: {
604
644
  thread_id: threadId,
@@ -1145,13 +1185,19 @@ class StreamErrorEventMessage extends EventMessage {
1145
1185
 
1146
1186
  class MemoryStreamQueue extends BaseStreamQueue {
1147
1187
  data = [];
1188
+ activeGenerators = /* @__PURE__ */ new Set();
1189
+ isDestroyed = false;
1148
1190
  async push(item) {
1191
+ if (this.isDestroyed) return;
1149
1192
  const data = this.compressMessages ? await this.encodeData(item) : item;
1150
1193
  this.data.push(data);
1151
1194
  this.emit("dataChange", data);
1152
1195
  }
1153
1196
  onDataChange(listener) {
1197
+ if (this.isDestroyed) return () => {
1198
+ };
1154
1199
  this.on("dataChange", async (item) => {
1200
+ if (this.isDestroyed) return;
1155
1201
  listener(this.compressMessages ? await this.decodeData(item) : item);
1156
1202
  });
1157
1203
  return () => this.off("dataChange", listener);
@@ -1160,16 +1206,27 @@ class MemoryStreamQueue extends BaseStreamQueue {
1160
1206
  * 异步生成器:支持 for await...of 方式消费队列数据
1161
1207
  */
1162
1208
  async *onDataReceive() {
1163
- let queue = [];
1209
+ if (this.isDestroyed) {
1210
+ return;
1211
+ }
1212
+ const localAbortController = new AbortController();
1213
+ this.activeGenerators.add(localAbortController);
1214
+ let localQueue = [];
1164
1215
  let pendingResolve = null;
1165
1216
  let isStreamEnded = false;
1166
1217
  let isCleanupDone = false;
1218
+ let endTimeoutId = null;
1167
1219
  const handleData = async (item) => {
1220
+ if (isCleanupDone || localAbortController.signal.aborted) return;
1168
1221
  try {
1169
1222
  const data = this.compressMessages ? await this.decodeData(item) : item;
1170
- queue.push(data);
1223
+ localQueue.push(data);
1171
1224
  if (data.event === "__stream_end__" || data.event === "__stream_error__" || data.event === "__stream_cancel__") {
1172
- setTimeout(() => {
1225
+ if (endTimeoutId) {
1226
+ clearTimeout(endTimeoutId);
1227
+ endTimeoutId = null;
1228
+ }
1229
+ endTimeoutId = setTimeout(() => {
1173
1230
  isStreamEnded = true;
1174
1231
  if (pendingResolve) {
1175
1232
  pendingResolve();
@@ -1177,7 +1234,7 @@ class MemoryStreamQueue extends BaseStreamQueue {
1177
1234
  }
1178
1235
  }, 300);
1179
1236
  if (data.event === "__stream_cancel__") {
1180
- await this.cancel();
1237
+ localAbortController.abort("stream cancelled");
1181
1238
  }
1182
1239
  }
1183
1240
  if (pendingResolve) {
@@ -1200,35 +1257,39 @@ class MemoryStreamQueue extends BaseStreamQueue {
1200
1257
  pendingResolve = null;
1201
1258
  }
1202
1259
  };
1203
- this.cancelSignal.signal.addEventListener("abort", abortHandler);
1260
+ localAbortController.signal.addEventListener("abort", abortHandler);
1204
1261
  const cleanup = () => {
1205
1262
  if (isCleanupDone) return;
1206
1263
  isCleanupDone = true;
1264
+ if (endTimeoutId) {
1265
+ clearTimeout(endTimeoutId);
1266
+ endTimeoutId = null;
1267
+ }
1207
1268
  try {
1208
1269
  this.off("dataChange", handleData);
1209
1270
  } catch (e) {
1210
- console.error("Error removing dataChange listener:", e);
1211
1271
  }
1212
1272
  try {
1213
- this.cancelSignal.signal.removeEventListener("abort", abortHandler);
1273
+ localAbortController.signal.removeEventListener("abort", abortHandler);
1214
1274
  } catch (e) {
1215
- console.error("Error removing abort listener:", e);
1216
1275
  }
1217
1276
  if (pendingResolve) {
1218
1277
  pendingResolve();
1219
1278
  pendingResolve = null;
1220
1279
  }
1280
+ localQueue.length = 0;
1281
+ this.activeGenerators.delete(localAbortController);
1221
1282
  };
1222
1283
  try {
1223
- if (this.cancelSignal.signal.aborted) {
1284
+ if (localAbortController.signal.aborted || this.isDestroyed) {
1224
1285
  return;
1225
1286
  }
1226
- while (!isStreamEnded && !this.cancelSignal.signal.aborted) {
1227
- if (queue.length > 0) {
1228
- for (const item of queue) {
1287
+ while (!isStreamEnded && !localAbortController.signal.aborted && !this.isDestroyed) {
1288
+ if (localQueue.length > 0) {
1289
+ for (const item of localQueue) {
1229
1290
  yield item;
1230
1291
  }
1231
- queue = [];
1292
+ localQueue.length = 0;
1232
1293
  } else {
1233
1294
  await new Promise((resolve) => {
1234
1295
  pendingResolve = resolve;
@@ -1240,17 +1301,29 @@ class MemoryStreamQueue extends BaseStreamQueue {
1240
1301
  }
1241
1302
  }
1242
1303
  async getAll() {
1304
+ if (this.isDestroyed) return [];
1243
1305
  return this.compressMessages ? await Promise.all(
1244
1306
  this.data.map((i) => this.decodeData(i))
1245
- ) : this.data;
1307
+ ) : [...this.data];
1246
1308
  }
1247
1309
  clear() {
1248
- this.data = [];
1310
+ this.data.length = 0;
1249
1311
  }
1250
1312
  cancelSignal = new AbortController();
1251
1313
  async cancel() {
1252
- this.cancelSignal.abort("user cancel this run");
1253
- await this.push(new CancelEventMessage());
1314
+ for (const controller of this.activeGenerators) {
1315
+ try {
1316
+ controller.abort("user cancel this run");
1317
+ } catch (e) {
1318
+ }
1319
+ }
1320
+ this.activeGenerators.clear();
1321
+ if (!this.cancelSignal.signal.aborted) {
1322
+ this.cancelSignal.abort("user cancel this run");
1323
+ }
1324
+ if (!this.isDestroyed) {
1325
+ await this.push(new CancelEventMessage());
1326
+ }
1254
1327
  }
1255
1328
  async copyToQueue(toId, ttl) {
1256
1329
  const data = this.data.slice();
@@ -1258,6 +1331,17 @@ class MemoryStreamQueue extends BaseStreamQueue {
1258
1331
  queue.data = data;
1259
1332
  return queue;
1260
1333
  }
1334
+ /**
1335
+ * 销毁队列,释放所有资源
1336
+ */
1337
+ async destroy() {
1338
+ if (this.isDestroyed) return;
1339
+ this.isDestroyed = true;
1340
+ await this.cancel();
1341
+ this.clear();
1342
+ this.removeAllListeners();
1343
+ this.activeGenerators.clear();
1344
+ }
1261
1345
  }
1262
1346
 
1263
1347
  class MemoryThreadsManager {
@@ -1599,7 +1683,7 @@ class MemoryThreadsManager {
1599
1683
  }
1600
1684
 
1601
1685
  const createCheckPointer = async () => {
1602
- if (process.env.REDIS_URL && process.env.CHECKPOINT_TYPE === "redis" || process.env.CHECKPOINT_TYPE === "shallow/redis") {
1686
+ if (process.env.REDIS_URL && (process.env.CHECKPOINT_TYPE === "redis" || process.env.CHECKPOINT_TYPE === "shallow/redis")) {
1603
1687
  if (process.env.CHECKPOINT_TYPE === "redis") {
1604
1688
  console.debug("LG | Using redis as checkpoint");
1605
1689
  const { RedisSaver } = await import('@langchain/langgraph-checkpoint-redis');
@@ -1621,9 +1705,15 @@ const createCheckPointer = async () => {
1621
1705
  return createPGCheckpoint();
1622
1706
  }
1623
1707
  if (process.env.SQLITE_DATABASE_URI) {
1624
- console.debug("LG | Using sqlite as checkpoint");
1625
- const { SqliteSaver } = await import('./checkpoint-1sAx_j1E.js');
1626
- const db = await SqliteSaver.fromConnStringAsync(process.env.SQLITE_DATABASE_URI);
1708
+ if (process.env.CHECKPOINT_TYPE === "sqlite") {
1709
+ console.debug("LG | Using sqlite (full) as checkpoint");
1710
+ const { SqliteSaver } = await import('./checkpoint-CY59Lr2q.js');
1711
+ const db2 = await SqliteSaver.fromConnStringAsync(process.env.SQLITE_DATABASE_URI);
1712
+ return db2;
1713
+ }
1714
+ console.debug("LG | Using shallow sqlite as checkpoint (default)");
1715
+ const { SqliteShallowSaver: SqliteShallowSaver2 } = await import('./shallow-checkpoint-ImbLxYNR.js');
1716
+ const db = await SqliteShallowSaver2.fromConnStringAsync(process.env.SQLITE_DATABASE_URI);
1627
1717
  return db;
1628
1718
  }
1629
1719
  console.log("LG | You are using memory as checkpoint!");
@@ -1641,7 +1731,7 @@ const createMessageQueue = async () => {
1641
1731
  let q;
1642
1732
  if (process.env.REDIS_URL) {
1643
1733
  console.debug("LG | Using redis as stream queue");
1644
- const { RedisStreamQueue } = await import('./queue-Cu_nO_wt.js');
1734
+ const { RedisStreamQueue } = await import('./queue-CUe5TDP1.js');
1645
1735
  q = RedisStreamQueue;
1646
1736
  } else {
1647
1737
  q = MemoryStreamQueue;
@@ -1681,7 +1771,7 @@ const createThreadManager = async (config) => {
1681
1771
  }
1682
1772
  if (process.env.SQLITE_DATABASE_URI && config.checkpointer) {
1683
1773
  console.debug("LG | Using SQLite ThreadsManager");
1684
- const { SQLiteAdapter } = await import('./sqlite-adapter-BKOLSdoL.js');
1774
+ const { SQLiteAdapter } = await import('./sqlite-adapter-CJXgit1j.js');
1685
1775
  const database = config.checkpointer.db;
1686
1776
  const threadsManager = new KyselyThreadsManager(new SQLiteAdapter(database));
1687
1777
  await threadsManager.setup();
@@ -1727,7 +1817,7 @@ async function streamStateWithQueue(threads, run, queue, payload, options) {
1727
1817
  const graph = await options.getGraph(graphId, payload.config, {
1728
1818
  checkpointer: payload.temporary ? null : void 0
1729
1819
  });
1730
- const userStreamMode = payload.streamMode ?? [];
1820
+ const userStreamMode = Array.isArray(payload.streamMode) ? payload.streamMode : payload.streamMode ? [payload.streamMode] : [];
1731
1821
  const libStreamMode = /* @__PURE__ */ new Set([
1732
1822
  "values",
1733
1823
  ...userStreamMode.filter((mode) => mode !== "events" && mode !== "messages-tuple")
@@ -1749,27 +1839,28 @@ async function streamStateWithQueue(threads, run, queue, payload, options) {
1749
1839
  ...payload.config?.metadata,
1750
1840
  run_attempt: options.attempt
1751
1841
  };
1752
- const events = graph.stream(
1753
- payload.command != null ? getLangGraphCommand(payload.command) : payload.input ?? null,
1754
- {
1755
- interruptAfter: payload.interruptAfter,
1756
- interruptBefore: payload.interruptBefore,
1757
- tags: payload.config?.tags,
1758
- configurable: payload.config?.configurable,
1759
- recursionLimit: payload.config?.recursionLimit,
1760
- subgraphs: payload.streamSubgraphs,
1761
- metadata,
1762
- runId: run.run_id,
1763
- streamMode: [...libStreamMode],
1764
- signal: queue.cancelSignal.signal
1765
- }
1766
- );
1767
- let sendedMetadataMessage;
1768
- let messageChunks;
1842
+ let sendedMetadataMessage = null;
1843
+ let messageChunks = null;
1844
+ let eventsIterator = null;
1769
1845
  try {
1770
1846
  sendedMetadataMessage = /* @__PURE__ */ new Set();
1771
1847
  messageChunks = /* @__PURE__ */ new Map();
1772
- for await (const event of await events) {
1848
+ eventsIterator = await graph.stream(
1849
+ payload.command != null ? getLangGraphCommand(payload.command) : payload.input ?? null,
1850
+ {
1851
+ interruptAfter: payload.interruptAfter,
1852
+ interruptBefore: payload.interruptBefore,
1853
+ tags: payload.config?.tags,
1854
+ configurable: payload.config?.configurable,
1855
+ recursionLimit: payload.config?.recursionLimit,
1856
+ subgraphs: payload.streamSubgraphs,
1857
+ metadata,
1858
+ runId: run.run_id,
1859
+ streamMode: [...libStreamMode],
1860
+ signal: queue.cancelSignal.signal
1861
+ }
1862
+ );
1863
+ for await (const event of eventsIterator) {
1773
1864
  let ns = [];
1774
1865
  if (event.length === 3) {
1775
1866
  ns = event.splice(0, 1);
@@ -1821,14 +1912,29 @@ async function streamStateWithQueue(threads, run, queue, payload, options) {
1821
1912
  await queue.push(new EventMessage(getNameWithNs("updates"), updates));
1822
1913
  }
1823
1914
  }
1915
+ } catch (error) {
1916
+ if (!(error instanceof Error && error.message?.includes("cancel"))) {
1917
+ console.error("streamStateWithQueue error:", error);
1918
+ try {
1919
+ await queue.push(new StreamErrorEventMessage(error));
1920
+ } catch (e) {
1921
+ }
1922
+ }
1923
+ throw error;
1824
1924
  } finally {
1825
- await queue.push(new StreamEndEventMessage());
1925
+ try {
1926
+ await queue.push(new StreamEndEventMessage());
1927
+ } catch (e) {
1928
+ }
1826
1929
  if (sendedMetadataMessage) {
1827
1930
  sendedMetadataMessage.clear();
1931
+ sendedMetadataMessage = null;
1828
1932
  }
1829
1933
  if (messageChunks) {
1830
1934
  messageChunks.clear();
1935
+ messageChunks = null;
1831
1936
  }
1937
+ eventsIterator = null;
1832
1938
  }
1833
1939
  }
1834
1940
  const serialiseAsDict = (obj, indent = 0) => {
@@ -1849,12 +1955,17 @@ async function* streamState(threads, run, payload, options) {
1849
1955
  run = await run;
1850
1956
  const queueId = run.run_id;
1851
1957
  const threadId = run.thread_id;
1958
+ let state = null;
1959
+ let queue = null;
1960
+ let backgroundTask = null;
1961
+ let isCleaningUp = false;
1852
1962
  try {
1853
1963
  await threads.set(threadId, { status: "busy" });
1854
1964
  await threads.updateRun(run.run_id, { status: "running" });
1855
- const queue = LangGraphGlobal.globalMessageQueue.createQueue(queueId);
1856
- const state = queue.onDataReceive();
1857
- streamStateWithQueue(threads, run, queue, payload, options).catch((error) => {
1965
+ queue = LangGraphGlobal.globalMessageQueue.createQueue(queueId);
1966
+ state = queue.onDataReceive();
1967
+ backgroundTask = streamStateWithQueue(threads, run, queue, payload, options).catch((error) => {
1968
+ if (isCleaningUp) return;
1858
1969
  if (error.message !== "user cancel this run") console.error("Queue task error:", error);
1859
1970
  LangGraphGlobal.globalMessageQueue.pushToQueue(queueId, new StreamErrorEventMessage(error));
1860
1971
  });
@@ -1867,16 +1978,40 @@ async function* streamState(threads, run, payload, options) {
1867
1978
  await threads.updateRun(run.run_id, { status: "error" });
1868
1979
  await threads.set(threadId, { status: "error" });
1869
1980
  } finally {
1981
+ isCleaningUp = true;
1982
+ if (state) {
1983
+ try {
1984
+ await state.return(void 0);
1985
+ } catch (e) {
1986
+ }
1987
+ state = null;
1988
+ }
1989
+ if (queue && !queue.cancelSignal.signal.aborted) {
1990
+ try {
1991
+ queue.cancelSignal.abort("Stream consumer disconnected");
1992
+ } catch (e) {
1993
+ }
1994
+ }
1995
+ if (backgroundTask) {
1996
+ try {
1997
+ await Promise.race([
1998
+ backgroundTask,
1999
+ new Promise((resolve) => setTimeout(resolve, 1e3))
2000
+ ]);
2001
+ } catch (e) {
2002
+ }
2003
+ backgroundTask = null;
2004
+ }
1870
2005
  const nowState = await threads.get(threadId);
1871
2006
  if (nowState.status === "interrupted") {
1872
2007
  await LangGraphGlobal.globalMessageQueue.copyQueue(queueId, threadId, 3e4);
1873
2008
  } else {
1874
2009
  await threads.set(threadId, { status: "idle", interrupts: {} });
1875
2010
  }
1876
- await LangGraphGlobal.globalMessageQueue.clearQueue(queueId);
1877
- LangGraphGlobal.globalMessageQueue.removeQueue(queueId);
2011
+ await LangGraphGlobal.globalMessageQueue.removeQueue(queueId);
2012
+ queue = null;
1878
2013
  }
1879
2014
  }
1880
2015
 
1881
2016
  export { BaseStreamQueue as B, CancelEventMessage as C, GRAPHS as G, KyselyThreadsManager as K, LangGraphGlobal as L, streamState as a, getGraph as g, registerGraph as r, serialiseAsDict as s };
1882
- //# sourceMappingURL=stream-CsqWsCjt.js.map
2017
+ //# sourceMappingURL=stream-jYlUzTZO.js.map