@langchain/langgraph-api 0.0.59 → 0.0.61

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,20 +1,40 @@
1
1
  import { HTTPException } from "hono/http-exception";
2
2
  import { v4 as uuid4, v5 as uuid5 } from "uuid";
3
- import { handleAuthEvent, isAuthMatching } from "../auth/custom.mjs";
3
+ import { handleAuthEvent, isAuthMatching } from "../auth/index.mjs";
4
4
  import { getLangGraphCommand } from "../command.mjs";
5
5
  import { getGraph, NAMESPACE_GRAPH } from "../graph/load.mjs";
6
6
  import { logger } from "../logging.mjs";
7
7
  import { serializeError } from "../utils/serde.mjs";
8
8
  import { checkpointer } from "./checkpoint.mjs";
9
- import { FileSystemPersistence } from "./persist.mjs";
10
9
  import { store } from "./store.mjs";
11
- export const conn = new FileSystemPersistence(".langgraphjs_ops.json", () => ({
12
- runs: {},
13
- threads: {},
14
- assistants: {},
15
- assistant_versions: [],
16
- retry_counter: {},
17
- }));
10
+ export class FileSystemOps {
11
+ conn;
12
+ assistants;
13
+ runs;
14
+ threads;
15
+ constructor(conn) {
16
+ this.conn = conn;
17
+ this.assistants = new FileSystemAssistants(this.conn);
18
+ this.runs = new FileSystemRuns(this.conn);
19
+ this.threads = new FileSystemThreads(this.conn);
20
+ }
21
+ truncate(flags) {
22
+ return this.conn.with((STORE) => {
23
+ if (flags.runs)
24
+ STORE.runs = {};
25
+ if (flags.threads)
26
+ STORE.threads = {};
27
+ if (flags.assistants) {
28
+ STORE.assistants = Object.fromEntries(Object.entries(STORE.assistants).filter(([key, assistant]) => assistant.metadata?.created_by === "system" &&
29
+ uuid5(assistant.graph_id, NAMESPACE_GRAPH) === key));
30
+ }
31
+ if (flags.checkpointer)
32
+ checkpointer.clear();
33
+ if (flags.store)
34
+ store.clear();
35
+ });
36
+ }
37
+ }
18
38
  class TimeoutError extends Error {
19
39
  }
20
40
  class AbortError extends Error {
@@ -113,22 +133,6 @@ class StreamManagerImpl {
113
133
  }
114
134
  }
115
135
  export const StreamManager = new StreamManagerImpl();
116
- export const truncate = (flags) => {
117
- return conn.with((STORE) => {
118
- if (flags.runs)
119
- STORE.runs = {};
120
- if (flags.threads)
121
- STORE.threads = {};
122
- if (flags.assistants) {
123
- STORE.assistants = Object.fromEntries(Object.entries(STORE.assistants).filter(([key, assistant]) => assistant.metadata?.created_by === "system" &&
124
- uuid5(assistant.graph_id, NAMESPACE_GRAPH) === key));
125
- }
126
- if (flags.checkpointer)
127
- checkpointer.clear();
128
- if (flags.store)
129
- store.clear();
130
- });
131
- };
132
136
  const isObject = (value) => {
133
137
  return typeof value === "object" && value !== null;
134
138
  };
@@ -148,15 +152,19 @@ const isJsonbContained = (superset, subset) => {
148
152
  }
149
153
  return true;
150
154
  };
151
- export class Assistants {
152
- static async *search(options, auth) {
155
+ export class FileSystemAssistants {
156
+ conn;
157
+ constructor(conn) {
158
+ this.conn = conn;
159
+ }
160
+ async *search(options, auth) {
153
161
  const [filters] = await handleAuthEvent(auth, "assistants:search", {
154
162
  graph_id: options.graph_id,
155
163
  metadata: options.metadata,
156
164
  limit: options.limit,
157
165
  offset: options.offset,
158
166
  });
159
- yield* conn.withGenerator(async function* (STORE) {
167
+ yield* this.conn.withGenerator(async function* (STORE) {
160
168
  let filtered = Object.values(STORE.assistants)
161
169
  .filter((assistant) => {
162
170
  if (options.graph_id != null &&
@@ -190,11 +198,11 @@ export class Assistants {
190
198
  }
191
199
  });
192
200
  }
193
- static async get(assistant_id, auth) {
201
+ async get(assistant_id, auth) {
194
202
  const [filters] = await handleAuthEvent(auth, "assistants:read", {
195
203
  assistant_id,
196
204
  });
197
- return conn.with((STORE) => {
205
+ return this.conn.with((STORE) => {
198
206
  const result = STORE.assistants[assistant_id];
199
207
  if (result == null)
200
208
  throw new HTTPException(404, { message: "Assistant not found" });
@@ -204,7 +212,7 @@ export class Assistants {
204
212
  return { ...result, name: result.name ?? result.graph_id };
205
213
  });
206
214
  }
207
- static async put(assistant_id, options, auth) {
215
+ async put(assistant_id, options, auth) {
208
216
  const [filters, mutable] = await handleAuthEvent(auth, "assistants:create", {
209
217
  assistant_id,
210
218
  config: options.config,
@@ -214,7 +222,7 @@ export class Assistants {
214
222
  if_exists: options.if_exists,
215
223
  name: options.name,
216
224
  });
217
- return conn.with((STORE) => {
225
+ return this.conn.with((STORE) => {
218
226
  if (STORE.assistants[assistant_id] != null) {
219
227
  const existingAssistant = STORE.assistants[assistant_id];
220
228
  if (!isAuthMatching(existingAssistant?.metadata, filters)) {
@@ -250,7 +258,7 @@ export class Assistants {
250
258
  return STORE.assistants[assistant_id];
251
259
  });
252
260
  }
253
- static async patch(assistantId, options, auth) {
261
+ async patch(assistantId, options, auth) {
254
262
  const [filters, mutable] = await handleAuthEvent(auth, "assistants:update", {
255
263
  assistant_id: assistantId,
256
264
  graph_id: options?.graph_id,
@@ -258,7 +266,7 @@ export class Assistants {
258
266
  metadata: options?.metadata,
259
267
  name: options?.name,
260
268
  });
261
- return conn.with((STORE) => {
269
+ return this.conn.with((STORE) => {
262
270
  const assistant = STORE.assistants[assistantId];
263
271
  if (!assistant) {
264
272
  throw new HTTPException(404, { message: "Assistant not found" });
@@ -307,11 +315,11 @@ export class Assistants {
307
315
  return assistant;
308
316
  });
309
317
  }
310
- static async delete(assistant_id, auth) {
318
+ async delete(assistant_id, auth) {
311
319
  const [filters] = await handleAuthEvent(auth, "assistants:delete", {
312
320
  assistant_id,
313
321
  });
314
- return conn.with((STORE) => {
322
+ return this.conn.with((STORE) => {
315
323
  const assistant = STORE.assistants[assistant_id];
316
324
  if (!assistant) {
317
325
  throw new HTTPException(404, { message: "Assistant not found" });
@@ -330,12 +338,12 @@ export class Assistants {
330
338
  return [assistant.assistant_id];
331
339
  });
332
340
  }
333
- static async setLatest(assistant_id, version, auth) {
341
+ async setLatest(assistant_id, version, auth) {
334
342
  const [filters] = await handleAuthEvent(auth, "assistants:update", {
335
343
  assistant_id,
336
344
  version,
337
345
  });
338
- return conn.with((STORE) => {
346
+ return this.conn.with((STORE) => {
339
347
  const assistant = STORE.assistants[assistant_id];
340
348
  if (!assistant) {
341
349
  throw new HTTPException(404, { message: "Assistant not found" });
@@ -360,11 +368,11 @@ export class Assistants {
360
368
  return STORE.assistants[assistant_id];
361
369
  });
362
370
  }
363
- static async getVersions(assistant_id, options, auth) {
371
+ async getVersions(assistant_id, options, auth) {
364
372
  const [filters] = await handleAuthEvent(auth, "assistants:read", {
365
373
  assistant_id,
366
374
  });
367
- return conn.with((STORE) => {
375
+ return this.conn.with((STORE) => {
368
376
  const versions = STORE.assistant_versions
369
377
  .filter((version) => {
370
378
  if (version["assistant_id"] !== assistant_id)
@@ -382,9 +390,39 @@ export class Assistants {
382
390
  return versions.slice(options.offset, options.offset + options.limit);
383
391
  });
384
392
  }
393
+ async count(options, auth) {
394
+ const [filters] = await handleAuthEvent(auth, "assistants:search", {
395
+ graph_id: options.graph_id,
396
+ metadata: options.metadata,
397
+ limit: 0,
398
+ offset: 0,
399
+ });
400
+ return this.conn.with((STORE) => {
401
+ return Object.values(STORE.assistants).filter((assistant) => {
402
+ if (options.graph_id != null &&
403
+ assistant["graph_id"] !== options.graph_id) {
404
+ return false;
405
+ }
406
+ if (options.metadata != null &&
407
+ !isJsonbContained(assistant["metadata"], options.metadata)) {
408
+ return false;
409
+ }
410
+ if (!isAuthMatching(assistant["metadata"], filters)) {
411
+ return false;
412
+ }
413
+ return true;
414
+ }).length;
415
+ });
416
+ }
385
417
  }
386
- export class Threads {
387
- static async *search(options, auth) {
418
+ export class FileSystemThreads {
419
+ conn;
420
+ state;
421
+ constructor(conn) {
422
+ this.conn = conn;
423
+ this.state = new FileSystemThreads.State(conn, this);
424
+ }
425
+ async *search(options, auth) {
388
426
  const [filters] = await handleAuthEvent(auth, "threads:search", {
389
427
  metadata: options.metadata,
390
428
  status: options.status,
@@ -392,7 +430,7 @@ export class Threads {
392
430
  limit: options.limit,
393
431
  offset: options.offset,
394
432
  });
395
- yield* conn.withGenerator(async function* (STORE) {
433
+ yield* this.conn.withGenerator(async function* (STORE) {
396
434
  const filtered = Object.values(STORE.threads)
397
435
  .filter((thread) => {
398
436
  if (options.metadata != null &&
@@ -433,11 +471,11 @@ export class Threads {
433
471
  });
434
472
  }
435
473
  // TODO: make this accept `undefined`
436
- static async get(thread_id, auth) {
474
+ async get(thread_id, auth) {
437
475
  const [filters] = await handleAuthEvent(auth, "threads:read", {
438
476
  thread_id,
439
477
  });
440
- return conn.with((STORE) => {
478
+ return this.conn.with((STORE) => {
441
479
  const result = STORE.threads[thread_id];
442
480
  if (result == null) {
443
481
  throw new HTTPException(404, {
@@ -452,13 +490,13 @@ export class Threads {
452
490
  return result;
453
491
  });
454
492
  }
455
- static async put(thread_id, options, auth) {
493
+ async put(thread_id, options, auth) {
456
494
  const [filters, mutable] = await handleAuthEvent(auth, "threads:create", {
457
495
  thread_id,
458
496
  metadata: options.metadata,
459
497
  if_exists: options.if_exists,
460
498
  });
461
- return conn.with((STORE) => {
499
+ return this.conn.with((STORE) => {
462
500
  const now = new Date();
463
501
  if (STORE.threads[thread_id] != null) {
464
502
  const existingThread = STORE.threads[thread_id];
@@ -482,12 +520,12 @@ export class Threads {
482
520
  return STORE.threads[thread_id];
483
521
  });
484
522
  }
485
- static async patch(threadId, options, auth) {
523
+ async patch(threadId, options, auth) {
486
524
  const [filters, mutable] = await handleAuthEvent(auth, "threads:update", {
487
525
  thread_id: threadId,
488
526
  metadata: options.metadata,
489
527
  });
490
- return conn.with((STORE) => {
528
+ return this.conn.with((STORE) => {
491
529
  const thread = STORE.threads[threadId];
492
530
  if (!thread) {
493
531
  throw new HTTPException(404, { message: "Thread not found" });
@@ -507,8 +545,8 @@ export class Threads {
507
545
  return thread;
508
546
  });
509
547
  }
510
- static async setStatus(threadId, options) {
511
- return conn.with((STORE) => {
548
+ async setStatus(threadId, options) {
549
+ return this.conn.with((STORE) => {
512
550
  const thread = STORE.threads[threadId];
513
551
  if (!thread)
514
552
  throw new HTTPException(404, { message: "Thread not found" });
@@ -542,11 +580,11 @@ export class Threads {
542
580
  : undefined;
543
581
  });
544
582
  }
545
- static async delete(thread_id, auth) {
583
+ async delete(thread_id, auth) {
546
584
  const [filters] = await handleAuthEvent(auth, "threads:delete", {
547
585
  thread_id,
548
586
  });
549
- return conn.with((STORE) => {
587
+ return this.conn.with((STORE) => {
550
588
  const thread = STORE.threads[thread_id];
551
589
  if (!thread) {
552
590
  throw new HTTPException(404, {
@@ -568,11 +606,11 @@ export class Threads {
568
606
  return [thread.thread_id];
569
607
  });
570
608
  }
571
- static async copy(thread_id, auth) {
609
+ async copy(thread_id, auth) {
572
610
  const [filters] = await handleAuthEvent(auth, "threads:read", {
573
611
  thread_id,
574
612
  });
575
- return conn.with((STORE) => {
613
+ return this.conn.with((STORE) => {
576
614
  const thread = STORE.threads[thread_id];
577
615
  if (!thread)
578
616
  throw new HTTPException(409, { message: "Thread not found" });
@@ -593,11 +631,48 @@ export class Threads {
593
631
  return STORE.threads[newThreadId];
594
632
  });
595
633
  }
634
+ async count(options, auth) {
635
+ const [filters] = await handleAuthEvent(auth, "threads:search", {
636
+ metadata: options.metadata,
637
+ values: options.values,
638
+ status: options.status,
639
+ limit: 0,
640
+ offset: 0,
641
+ });
642
+ return this.conn.with((STORE) => {
643
+ return Object.values(STORE.threads).filter((thread) => {
644
+ if (options.metadata != null &&
645
+ !isJsonbContained(thread["metadata"], options.metadata)) {
646
+ return false;
647
+ }
648
+ if (options.values != null &&
649
+ typeof thread["values"] !== "undefined" &&
650
+ !isJsonbContained(thread["values"], options.values)) {
651
+ return false;
652
+ }
653
+ if (options.status != null && thread["status"] !== options.status) {
654
+ return false;
655
+ }
656
+ if (!isAuthMatching(thread["metadata"], filters)) {
657
+ return false;
658
+ }
659
+ return true;
660
+ }).length;
661
+ });
662
+ }
596
663
  static State = class {
597
- static async get(config, options, auth) {
664
+ conn;
665
+ threads;
666
+ constructor(conn, threads) {
667
+ this.conn = conn;
668
+ this.threads = threads;
669
+ }
670
+ async get(config, options, auth) {
598
671
  const subgraphs = options.subgraphs ?? false;
599
672
  const threadId = config.configurable?.thread_id;
600
- const thread = threadId ? await Threads.get(threadId, auth) : undefined;
673
+ const thread = threadId
674
+ ? await this.threads.get(threadId, auth)
675
+ : undefined;
601
676
  const metadata = thread?.metadata ?? {};
602
677
  const graphId = metadata?.graph_id;
603
678
  if (!thread || graphId == null) {
@@ -623,12 +698,14 @@ export class Threads {
623
698
  }
624
699
  return result;
625
700
  }
626
- static async post(config, values, asNode, auth) {
701
+ async post(config, values, asNode, auth) {
627
702
  const threadId = config.configurable?.thread_id;
628
703
  const [filters] = await handleAuthEvent(auth, "threads:update", {
629
704
  thread_id: threadId,
630
705
  });
631
- const thread = threadId ? await Threads.get(threadId, auth) : undefined;
706
+ const thread = threadId
707
+ ? await this.threads.get(threadId, auth)
708
+ : undefined;
632
709
  if (!thread)
633
710
  throw new HTTPException(404, {
634
711
  message: `Thread ${threadId} not found`,
@@ -637,7 +714,7 @@ export class Threads {
637
714
  throw new HTTPException(403);
638
715
  }
639
716
  // do a check if there are no pending runs
640
- await conn.with(async (STORE) => {
717
+ await this.conn.with(async (STORE) => {
641
718
  if (Object.values(STORE.runs).some((run) => run.thread_id === threadId &&
642
719
  (run.status === "pending" || run.status === "running"))) {
643
720
  throw new HTTPException(409, { message: "Thread is busy" });
@@ -659,9 +736,9 @@ export class Threads {
659
736
  updateConfig.configurable ??= {};
660
737
  updateConfig.configurable.checkpoint_ns ??= "";
661
738
  const nextConfig = await graph.updateState(updateConfig, values, asNode);
662
- const state = await Threads.State.get(config, { subgraphs: false }, auth);
739
+ const state = await this.get(config, { subgraphs: false }, auth);
663
740
  // update thread values
664
- await conn.with(async (STORE) => {
741
+ await this.conn.with(async (STORE) => {
665
742
  for (const thread of Object.values(STORE.threads)) {
666
743
  if (thread.thread_id === threadId) {
667
744
  thread.values = state.values;
@@ -671,14 +748,14 @@ export class Threads {
671
748
  });
672
749
  return { checkpoint: nextConfig.configurable };
673
750
  }
674
- static async bulk(config, supersteps, auth) {
751
+ async bulk(config, supersteps, auth) {
675
752
  const threadId = config.configurable?.thread_id;
676
753
  if (!threadId)
677
754
  return [];
678
755
  const [filters] = await handleAuthEvent(auth, "threads:update", {
679
756
  thread_id: threadId,
680
757
  });
681
- const thread = await Threads.get(threadId, auth);
758
+ const thread = await this.threads.get(threadId, auth);
682
759
  if (!isAuthMatching(thread["metadata"], filters)) {
683
760
  throw new HTTPException(403);
684
761
  }
@@ -703,9 +780,9 @@ export class Threads {
703
780
  asNode: j.as_node,
704
781
  })),
705
782
  })));
706
- const state = await Threads.State.get(config, { subgraphs: false }, auth);
783
+ const state = await this.get(config, { subgraphs: false }, auth);
707
784
  // update thread values
708
- await conn.with(async (STORE) => {
785
+ await this.conn.with(async (STORE) => {
709
786
  for (const thread of Object.values(STORE.threads)) {
710
787
  if (thread.thread_id === threadId) {
711
788
  thread.values = state.values;
@@ -715,14 +792,14 @@ export class Threads {
715
792
  });
716
793
  return { checkpoint: nextConfig.configurable };
717
794
  }
718
- static async list(config, options, auth) {
795
+ async list(config, options, auth) {
719
796
  const threadId = config.configurable?.thread_id;
720
797
  if (!threadId)
721
798
  return [];
722
799
  const [filters] = await handleAuthEvent(auth, "threads:read", {
723
800
  thread_id: threadId,
724
801
  });
725
- const thread = await Threads.get(threadId, auth);
802
+ const thread = await this.threads.get(threadId, auth);
726
803
  if (!isAuthMatching(thread["metadata"], filters))
727
804
  return [];
728
805
  const graphId = thread.metadata?.graph_id;
@@ -747,9 +824,17 @@ export class Threads {
747
824
  }
748
825
  };
749
826
  }
750
- export class Runs {
751
- static async *next() {
752
- yield* conn.withGenerator(async function* (STORE, options) {
827
+ export class FileSystemRuns {
828
+ conn;
829
+ threads;
830
+ stream;
831
+ constructor(conn) {
832
+ this.conn = conn;
833
+ this.threads = new FileSystemThreads(conn);
834
+ this.stream = new FileSystemRuns.Stream(conn, this);
835
+ }
836
+ async *next() {
837
+ yield* this.conn.withGenerator(async function* (STORE, options) {
753
838
  const now = new Date();
754
839
  const pendingRunIds = Object.values(STORE.runs)
755
840
  .filter((run) => run.status === "pending" && run.created_at < now)
@@ -790,8 +875,8 @@ export class Runs {
790
875
  }
791
876
  });
792
877
  }
793
- static async put(runId, assistantId, kwargs, options, auth) {
794
- return conn.with(async (STORE) => {
878
+ async put(runId, assistantId, kwargs, options, auth) {
879
+ return this.conn.with(async (STORE) => {
795
880
  const assistant = STORE.assistants[assistantId];
796
881
  if (!assistant) {
797
882
  throw new HTTPException(404, {
@@ -897,11 +982,11 @@ export class Runs {
897
982
  return [newRun, ...inflightRuns];
898
983
  });
899
984
  }
900
- static async get(runId, thread_id, auth) {
985
+ async get(runId, thread_id, auth) {
901
986
  const [filters] = await handleAuthEvent(auth, "threads:read", {
902
987
  thread_id,
903
988
  });
904
- return conn.with(async (STORE) => {
989
+ return this.conn.with(async (STORE) => {
905
990
  const run = STORE.runs[runId];
906
991
  if (!run ||
907
992
  run.run_id !== runId ||
@@ -915,12 +1000,12 @@ export class Runs {
915
1000
  return run;
916
1001
  });
917
1002
  }
918
- static async delete(run_id, thread_id, auth) {
1003
+ async delete(run_id, thread_id, auth) {
919
1004
  const [filters] = await handleAuthEvent(auth, "threads:delete", {
920
1005
  run_id,
921
1006
  thread_id,
922
1007
  });
923
- return conn.with(async (STORE) => {
1008
+ return this.conn.with(async (STORE) => {
924
1009
  const run = STORE.runs[run_id];
925
1010
  if (!run || (thread_id != null && run.thread_id !== thread_id))
926
1011
  throw new HTTPException(404, { message: "Run not found" });
@@ -936,8 +1021,8 @@ export class Runs {
936
1021
  return run.run_id;
937
1022
  });
938
1023
  }
939
- static async wait(runId, threadId, auth) {
940
- const runStream = Runs.Stream.join(runId, threadId, { ignore404: threadId == null, lastEventId: undefined }, auth);
1024
+ async wait(runId, threadId, auth) {
1025
+ const runStream = this.stream.join(runId, threadId, { ignore404: threadId == null, lastEventId: undefined }, auth);
941
1026
  const lastChunk = new Promise(async (resolve, reject) => {
942
1027
  try {
943
1028
  let lastChunk = null;
@@ -957,17 +1042,17 @@ export class Runs {
957
1042
  });
958
1043
  return lastChunk;
959
1044
  }
960
- static async join(runId, threadId, auth) {
1045
+ async join(runId, threadId, auth) {
961
1046
  // check if thread exists
962
- await Threads.get(threadId, auth);
963
- const lastChunk = await Runs.wait(runId, threadId, auth);
1047
+ await this.threads.get(threadId, auth);
1048
+ const lastChunk = await this.wait(runId, threadId, auth);
964
1049
  if (lastChunk != null)
965
1050
  return lastChunk;
966
- const thread = await Threads.get(threadId, auth);
1051
+ const thread = await this.threads.get(threadId, auth);
967
1052
  return thread.values ?? null;
968
1053
  }
969
- static async cancel(threadId, runIds, options, auth) {
970
- return conn.with(async (STORE) => {
1054
+ async cancel(threadId, runIds, options, auth) {
1055
+ return this.conn.with(async (STORE) => {
971
1056
  const action = options.action ?? "interrupt";
972
1057
  const promises = [];
973
1058
  const [filters] = await handleAuthEvent(auth, "threads:update", {
@@ -1004,7 +1089,7 @@ export class Runs {
1004
1089
  run_id: runId,
1005
1090
  thread_id: threadId,
1006
1091
  });
1007
- promises.push(Runs.delete(runId, threadId, auth));
1092
+ promises.push(this.delete(runId, threadId, auth));
1008
1093
  }
1009
1094
  }
1010
1095
  else {
@@ -1027,13 +1112,13 @@ export class Runs {
1027
1112
  }
1028
1113
  });
1029
1114
  }
1030
- static async search(threadId, options, auth) {
1115
+ async search(threadId, options, auth) {
1031
1116
  const [filters] = await handleAuthEvent(auth, "threads:search", {
1032
1117
  thread_id: threadId,
1033
1118
  metadata: options.metadata,
1034
1119
  status: options.status,
1035
1120
  });
1036
- return conn.with(async (STORE) => {
1121
+ return this.conn.with(async (STORE) => {
1037
1122
  const runs = Object.values(STORE.runs).filter((run) => {
1038
1123
  if (run.thread_id !== threadId)
1039
1124
  return false;
@@ -1052,8 +1137,8 @@ export class Runs {
1052
1137
  return runs.slice(options?.offset ?? 0, options?.limit ?? 10);
1053
1138
  });
1054
1139
  }
1055
- static async setStatus(runId, status) {
1056
- return conn.with(async (STORE) => {
1140
+ async setStatus(runId, status) {
1141
+ return this.conn.with(async (STORE) => {
1057
1142
  const run = STORE.runs[runId];
1058
1143
  if (!run)
1059
1144
  throw new Error(`Run ${runId} not found`);
@@ -1062,7 +1147,15 @@ export class Runs {
1062
1147
  });
1063
1148
  }
1064
1149
  static Stream = class {
1065
- static async *join(runId, threadId, options, auth) {
1150
+ conn;
1151
+ runs;
1152
+ constructor(conn, runs) {
1153
+ this.conn = conn;
1154
+ this.runs = runs;
1155
+ }
1156
+ async *join(runId, threadId, options, auth) {
1157
+ const conn = this.conn;
1158
+ const runs = this.runs;
1066
1159
  yield* conn.withGenerator(async function* (STORE) {
1067
1160
  // TODO: what if we're joining an already completed run? Should we check before?
1068
1161
  const signal = options?.cancelOnDisconnect;
@@ -1105,7 +1198,7 @@ export class Runs {
1105
1198
  catch (error) {
1106
1199
  if (error instanceof AbortError)
1107
1200
  break;
1108
- const run = await Runs.get(runId, threadId, auth);
1201
+ const run = await runs.get(runId, threadId, auth);
1109
1202
  if (run == null) {
1110
1203
  if (!options?.ignore404)
1111
1204
  yield { event: "error", data: "Run not found" };
@@ -1117,11 +1210,11 @@ export class Runs {
1117
1210
  }
1118
1211
  }
1119
1212
  if (signal?.aborted && threadId != null) {
1120
- await Runs.cancel(threadId, [runId], { action: "interrupt" }, auth);
1213
+ await runs.cancel(threadId, [runId], { action: "interrupt" }, auth);
1121
1214
  }
1122
1215
  });
1123
1216
  }
1124
- static async publish(payload) {
1217
+ async publish(payload) {
1125
1218
  const queue = StreamManager.getQueue(payload.runId, {
1126
1219
  ifNotFound: "create",
1127
1220
  resumable: payload.resumable,