@langchain/langgraph-sdk 0.0.73 → 0.0.75

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.cjs CHANGED
@@ -32,6 +32,19 @@ function getApiKey(apiKey) {
32
32
  return undefined;
33
33
  }
34
34
  exports.getApiKey = getApiKey;
35
+ const REGEX_RUN_METADATA = /(\/threads\/(?<thread_id>.+))?\/runs\/(?<run_id>.+)/;
36
+ function getRunMetadataFromResponse(response) {
37
+ const contentLocation = response.headers.get("Content-Location");
38
+ if (!contentLocation)
39
+ return undefined;
40
+ const match = REGEX_RUN_METADATA.exec(contentLocation);
41
+ if (!match?.groups?.run_id)
42
+ return undefined;
43
+ return {
44
+ run_id: match.groups.run_id,
45
+ thread_id: match.groups.thread_id || undefined,
46
+ };
47
+ }
35
48
  class BaseClient {
36
49
  constructor(config) {
37
50
  Object.defineProperty(this, "asyncCaller", {
@@ -100,6 +113,9 @@ class BaseClient {
100
113
  };
101
114
  delete mutatedOptions.json;
102
115
  }
116
+ if (mutatedOptions.withResponse) {
117
+ delete mutatedOptions.withResponse;
118
+ }
103
119
  let timeoutSignal = null;
104
120
  if (typeof options?.timeoutMs !== "undefined") {
105
121
  if (options.timeoutMs != null) {
@@ -126,10 +142,16 @@ class BaseClient {
126
142
  }
127
143
  async fetch(path, options) {
128
144
  const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(path, options));
129
- if (response.status === 202 || response.status === 204) {
130
- return undefined;
145
+ const body = (() => {
146
+ if (response.status === 202 || response.status === 204) {
147
+ return undefined;
148
+ }
149
+ return response.json();
150
+ })();
151
+ if (options?.withResponse) {
152
+ return [await body, response];
131
153
  }
132
- return response.json();
154
+ return body;
133
155
  }
134
156
  }
135
157
  class CronsClient extends BaseClient {
@@ -152,6 +174,7 @@ class CronsClient extends BaseClient {
152
174
  webhook: payload?.webhook,
153
175
  multitask_strategy: payload?.multitaskStrategy,
154
176
  if_not_exists: payload?.ifNotExists,
177
+ checkpoint_during: payload?.checkpointDuring,
155
178
  };
156
179
  return this.fetch(`/threads/${threadId}/runs/crons`, {
157
180
  method: "POST",
@@ -176,6 +199,7 @@ class CronsClient extends BaseClient {
176
199
  webhook: payload?.webhook,
177
200
  multitask_strategy: payload?.multitaskStrategy,
178
201
  if_not_exists: payload?.ifNotExists,
202
+ checkpoint_during: payload?.checkpointDuring,
179
203
  };
180
204
  return this.fetch(`/runs/crons`, {
181
205
  method: "POST",
@@ -545,6 +569,7 @@ class RunsClient extends BaseClient {
545
569
  on_disconnect: payload?.onDisconnect,
546
570
  after_seconds: payload?.afterSeconds,
547
571
  if_not_exists: payload?.ifNotExists,
572
+ checkpoint_during: payload?.checkpointDuring,
548
573
  };
549
574
  const endpoint = threadId == null ? `/runs/stream` : `/threads/${threadId}/runs/stream`;
550
575
  const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(endpoint, {
@@ -553,6 +578,9 @@ class RunsClient extends BaseClient {
553
578
  timeoutMs: null,
554
579
  signal: payload?.signal,
555
580
  }));
581
+ const runMetadata = getRunMetadataFromResponse(response);
582
+ if (runMetadata)
583
+ payload?.onRunCreated?.(runMetadata);
556
584
  const stream = (response.body || new ReadableStream({ start: (ctrl) => ctrl.close() }))
557
585
  .pipeThrough(new sse_js_1.BytesLineDecoder())
558
586
  .pipeThrough(new sse_js_1.SSEDecoder());
@@ -583,12 +611,18 @@ class RunsClient extends BaseClient {
583
611
  multitask_strategy: payload?.multitaskStrategy,
584
612
  after_seconds: payload?.afterSeconds,
585
613
  if_not_exists: payload?.ifNotExists,
614
+ checkpoint_during: payload?.checkpointDuring,
586
615
  };
587
- return this.fetch(`/threads/${threadId}/runs`, {
616
+ const [run, response] = await this.fetch(`/threads/${threadId}/runs`, {
588
617
  method: "POST",
589
618
  json,
590
619
  signal: payload?.signal,
620
+ withResponse: true,
591
621
  });
622
+ const runMetadata = getRunMetadataFromResponse(response);
623
+ if (runMetadata)
624
+ payload?.onRunCreated?.(runMetadata);
625
+ return run;
592
626
  }
593
627
  /**
594
628
  * Create a batch of stateless background runs.
@@ -632,24 +666,29 @@ class RunsClient extends BaseClient {
632
666
  on_disconnect: payload?.onDisconnect,
633
667
  after_seconds: payload?.afterSeconds,
634
668
  if_not_exists: payload?.ifNotExists,
669
+ checkpoint_during: payload?.checkpointDuring,
635
670
  };
636
671
  const endpoint = threadId == null ? `/runs/wait` : `/threads/${threadId}/runs/wait`;
637
- const response = await this.fetch(endpoint, {
672
+ const [run, response] = await this.fetch(endpoint, {
638
673
  method: "POST",
639
674
  json,
640
675
  timeoutMs: null,
641
676
  signal: payload?.signal,
677
+ withResponse: true,
642
678
  });
679
+ const runMetadata = getRunMetadataFromResponse(response);
680
+ if (runMetadata)
681
+ payload?.onRunCreated?.(runMetadata);
643
682
  const raiseError = payload?.raiseError !== undefined ? payload.raiseError : true;
644
683
  if (raiseError &&
645
- "__error__" in response &&
646
- typeof response.__error__ === "object" &&
647
- response.__error__ &&
648
- "error" in response.__error__ &&
649
- "message" in response.__error__) {
650
- throw new Error(`${response.__error__?.error}: ${response.__error__?.message}`);
684
+ "__error__" in run &&
685
+ typeof run.__error__ === "object" &&
686
+ run.__error__ &&
687
+ "error" in run.__error__ &&
688
+ "message" in run.__error__) {
689
+ throw new Error(`${run.__error__?.error}: ${run.__error__?.message}`);
651
690
  }
652
- return response;
691
+ return run;
653
692
  }
654
693
  /**
655
694
  * List all runs for a thread.
@@ -710,13 +749,12 @@ class RunsClient extends BaseClient {
710
749
  }
711
750
  /**
712
751
  * Stream output from a run in real-time, until the run is done.
713
- * Output is not buffered, so any output produced before this call will
714
- * not be received here.
715
752
  *
716
- * @param threadId The ID of the thread.
753
+ * @param threadId The ID of the thread. Can be set to `null` | `undefined` for stateless runs.
717
754
  * @param runId The ID of the run.
718
755
  * @param options Additional options for controlling the stream behavior:
719
756
  * - signal: An AbortSignal that can be used to cancel the stream request
757
+ * - lastEventId: The ID of the last event received. Can be used to reconnect to a stream without losing events.
720
758
  * - cancelOnDisconnect: When true, automatically cancels the run if the client disconnects from the stream
721
759
  * - streamMode: Controls what types of events to receive from the stream (can be a single mode or array of modes)
722
760
  * Must be a subset of the stream modes passed when creating the run. Background runs default to having the union of all
@@ -729,10 +767,15 @@ class RunsClient extends BaseClient {
729
767
  options instanceof AbortSignal
730
768
  ? { signal: options }
731
769
  : options;
732
- const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(`/threads/${threadId}/runs/${runId}/stream`, {
770
+ const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(threadId != null
771
+ ? `/threads/${threadId}/runs/${runId}/stream`
772
+ : `/runs/${runId}/stream`, {
733
773
  method: "GET",
734
774
  timeoutMs: null,
735
775
  signal: opts?.signal,
776
+ headers: opts?.lastEventId
777
+ ? { "Last-Event-ID": opts.lastEventId }
778
+ : undefined,
736
779
  params: {
737
780
  cancel_on_disconnect: opts?.cancelOnDisconnect ? "1" : "0",
738
781
  stream_mode: opts?.streamMode,
package/dist/client.d.ts CHANGED
@@ -31,12 +31,21 @@ declare class BaseClient {
31
31
  json?: unknown;
32
32
  params?: Record<string, unknown>;
33
33
  timeoutMs?: number | null;
34
+ withResponse?: boolean;
34
35
  }): [url: URL, init: RequestInit];
36
+ protected fetch<T>(path: string, options: RequestInit & {
37
+ json?: unknown;
38
+ params?: Record<string, unknown>;
39
+ timeoutMs?: number | null;
40
+ signal?: AbortSignal;
41
+ withResponse: true;
42
+ }): Promise<[T, Response]>;
35
43
  protected fetch<T>(path: string, options?: RequestInit & {
36
44
  json?: unknown;
37
45
  params?: Record<string, unknown>;
38
46
  timeoutMs?: number | null;
39
47
  signal?: AbortSignal;
48
+ withResponse?: false;
40
49
  }): Promise<T>;
41
50
  }
42
51
  export declare class CronsClient extends BaseClient {
@@ -398,24 +407,25 @@ export declare class RunsClient<TStateType = DefaultValues, TUpdateType = TState
398
407
  }): Promise<void>;
399
408
  /**
400
409
  * Stream output from a run in real-time, until the run is done.
401
- * Output is not buffered, so any output produced before this call will
402
- * not be received here.
403
410
  *
404
- * @param threadId The ID of the thread.
411
+ * @param threadId The ID of the thread. Can be set to `null` | `undefined` for stateless runs.
405
412
  * @param runId The ID of the run.
406
413
  * @param options Additional options for controlling the stream behavior:
407
414
  * - signal: An AbortSignal that can be used to cancel the stream request
415
+ * - lastEventId: The ID of the last event received. Can be used to reconnect to a stream without losing events.
408
416
  * - cancelOnDisconnect: When true, automatically cancels the run if the client disconnects from the stream
409
417
  * - streamMode: Controls what types of events to receive from the stream (can be a single mode or array of modes)
410
418
  * Must be a subset of the stream modes passed when creating the run. Background runs default to having the union of all
411
419
  * stream modes enabled.
412
420
  * @returns An async generator yielding stream parts.
413
421
  */
414
- joinStream(threadId: string, runId: string, options?: {
422
+ joinStream(threadId: string | undefined | null, runId: string, options?: {
415
423
  signal?: AbortSignal;
416
424
  cancelOnDisconnect?: boolean;
425
+ lastEventId?: string;
417
426
  streamMode?: StreamMode | StreamMode[];
418
427
  } | AbortSignal): AsyncGenerator<{
428
+ id?: string;
419
429
  event: StreamEvent;
420
430
  data: any;
421
431
  }>;
package/dist/client.js CHANGED
@@ -28,6 +28,19 @@ export function getApiKey(apiKey) {
28
28
  }
29
29
  return undefined;
30
30
  }
31
+ const REGEX_RUN_METADATA = /(\/threads\/(?<thread_id>.+))?\/runs\/(?<run_id>.+)/;
32
+ function getRunMetadataFromResponse(response) {
33
+ const contentLocation = response.headers.get("Content-Location");
34
+ if (!contentLocation)
35
+ return undefined;
36
+ const match = REGEX_RUN_METADATA.exec(contentLocation);
37
+ if (!match?.groups?.run_id)
38
+ return undefined;
39
+ return {
40
+ run_id: match.groups.run_id,
41
+ thread_id: match.groups.thread_id || undefined,
42
+ };
43
+ }
31
44
  class BaseClient {
32
45
  constructor(config) {
33
46
  Object.defineProperty(this, "asyncCaller", {
@@ -96,6 +109,9 @@ class BaseClient {
96
109
  };
97
110
  delete mutatedOptions.json;
98
111
  }
112
+ if (mutatedOptions.withResponse) {
113
+ delete mutatedOptions.withResponse;
114
+ }
99
115
  let timeoutSignal = null;
100
116
  if (typeof options?.timeoutMs !== "undefined") {
101
117
  if (options.timeoutMs != null) {
@@ -122,10 +138,16 @@ class BaseClient {
122
138
  }
123
139
  async fetch(path, options) {
124
140
  const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(path, options));
125
- if (response.status === 202 || response.status === 204) {
126
- return undefined;
141
+ const body = (() => {
142
+ if (response.status === 202 || response.status === 204) {
143
+ return undefined;
144
+ }
145
+ return response.json();
146
+ })();
147
+ if (options?.withResponse) {
148
+ return [await body, response];
127
149
  }
128
- return response.json();
150
+ return body;
129
151
  }
130
152
  }
131
153
  export class CronsClient extends BaseClient {
@@ -148,6 +170,7 @@ export class CronsClient extends BaseClient {
148
170
  webhook: payload?.webhook,
149
171
  multitask_strategy: payload?.multitaskStrategy,
150
172
  if_not_exists: payload?.ifNotExists,
173
+ checkpoint_during: payload?.checkpointDuring,
151
174
  };
152
175
  return this.fetch(`/threads/${threadId}/runs/crons`, {
153
176
  method: "POST",
@@ -172,6 +195,7 @@ export class CronsClient extends BaseClient {
172
195
  webhook: payload?.webhook,
173
196
  multitask_strategy: payload?.multitaskStrategy,
174
197
  if_not_exists: payload?.ifNotExists,
198
+ checkpoint_during: payload?.checkpointDuring,
175
199
  };
176
200
  return this.fetch(`/runs/crons`, {
177
201
  method: "POST",
@@ -538,6 +562,7 @@ export class RunsClient extends BaseClient {
538
562
  on_disconnect: payload?.onDisconnect,
539
563
  after_seconds: payload?.afterSeconds,
540
564
  if_not_exists: payload?.ifNotExists,
565
+ checkpoint_during: payload?.checkpointDuring,
541
566
  };
542
567
  const endpoint = threadId == null ? `/runs/stream` : `/threads/${threadId}/runs/stream`;
543
568
  const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(endpoint, {
@@ -546,6 +571,9 @@ export class RunsClient extends BaseClient {
546
571
  timeoutMs: null,
547
572
  signal: payload?.signal,
548
573
  }));
574
+ const runMetadata = getRunMetadataFromResponse(response);
575
+ if (runMetadata)
576
+ payload?.onRunCreated?.(runMetadata);
549
577
  const stream = (response.body || new ReadableStream({ start: (ctrl) => ctrl.close() }))
550
578
  .pipeThrough(new BytesLineDecoder())
551
579
  .pipeThrough(new SSEDecoder());
@@ -576,12 +604,18 @@ export class RunsClient extends BaseClient {
576
604
  multitask_strategy: payload?.multitaskStrategy,
577
605
  after_seconds: payload?.afterSeconds,
578
606
  if_not_exists: payload?.ifNotExists,
607
+ checkpoint_during: payload?.checkpointDuring,
579
608
  };
580
- return this.fetch(`/threads/${threadId}/runs`, {
609
+ const [run, response] = await this.fetch(`/threads/${threadId}/runs`, {
581
610
  method: "POST",
582
611
  json,
583
612
  signal: payload?.signal,
613
+ withResponse: true,
584
614
  });
615
+ const runMetadata = getRunMetadataFromResponse(response);
616
+ if (runMetadata)
617
+ payload?.onRunCreated?.(runMetadata);
618
+ return run;
585
619
  }
586
620
  /**
587
621
  * Create a batch of stateless background runs.
@@ -625,24 +659,29 @@ export class RunsClient extends BaseClient {
625
659
  on_disconnect: payload?.onDisconnect,
626
660
  after_seconds: payload?.afterSeconds,
627
661
  if_not_exists: payload?.ifNotExists,
662
+ checkpoint_during: payload?.checkpointDuring,
628
663
  };
629
664
  const endpoint = threadId == null ? `/runs/wait` : `/threads/${threadId}/runs/wait`;
630
- const response = await this.fetch(endpoint, {
665
+ const [run, response] = await this.fetch(endpoint, {
631
666
  method: "POST",
632
667
  json,
633
668
  timeoutMs: null,
634
669
  signal: payload?.signal,
670
+ withResponse: true,
635
671
  });
672
+ const runMetadata = getRunMetadataFromResponse(response);
673
+ if (runMetadata)
674
+ payload?.onRunCreated?.(runMetadata);
636
675
  const raiseError = payload?.raiseError !== undefined ? payload.raiseError : true;
637
676
  if (raiseError &&
638
- "__error__" in response &&
639
- typeof response.__error__ === "object" &&
640
- response.__error__ &&
641
- "error" in response.__error__ &&
642
- "message" in response.__error__) {
643
- throw new Error(`${response.__error__?.error}: ${response.__error__?.message}`);
677
+ "__error__" in run &&
678
+ typeof run.__error__ === "object" &&
679
+ run.__error__ &&
680
+ "error" in run.__error__ &&
681
+ "message" in run.__error__) {
682
+ throw new Error(`${run.__error__?.error}: ${run.__error__?.message}`);
644
683
  }
645
- return response;
684
+ return run;
646
685
  }
647
686
  /**
648
687
  * List all runs for a thread.
@@ -703,13 +742,12 @@ export class RunsClient extends BaseClient {
703
742
  }
704
743
  /**
705
744
  * Stream output from a run in real-time, until the run is done.
706
- * Output is not buffered, so any output produced before this call will
707
- * not be received here.
708
745
  *
709
- * @param threadId The ID of the thread.
746
+ * @param threadId The ID of the thread. Can be set to `null` | `undefined` for stateless runs.
710
747
  * @param runId The ID of the run.
711
748
  * @param options Additional options for controlling the stream behavior:
712
749
  * - signal: An AbortSignal that can be used to cancel the stream request
750
+ * - lastEventId: The ID of the last event received. Can be used to reconnect to a stream without losing events.
713
751
  * - cancelOnDisconnect: When true, automatically cancels the run if the client disconnects from the stream
714
752
  * - streamMode: Controls what types of events to receive from the stream (can be a single mode or array of modes)
715
753
  * Must be a subset of the stream modes passed when creating the run. Background runs default to having the union of all
@@ -722,10 +760,15 @@ export class RunsClient extends BaseClient {
722
760
  options instanceof AbortSignal
723
761
  ? { signal: options }
724
762
  : options;
725
- const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(`/threads/${threadId}/runs/${runId}/stream`, {
763
+ const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(threadId != null
764
+ ? `/threads/${threadId}/runs/${runId}/stream`
765
+ : `/runs/${runId}/stream`, {
726
766
  method: "GET",
727
767
  timeoutMs: null,
728
768
  signal: opts?.signal,
769
+ headers: opts?.lastEventId
770
+ ? { "Last-Event-ID": opts.lastEventId }
771
+ : undefined,
729
772
  params: {
730
773
  cancel_on_disconnect: opts?.cancelOnDisconnect ? "1" : "0",
731
774
  stream_mode: opts?.streamMode,
package/dist/types.d.ts CHANGED
@@ -46,6 +46,10 @@ interface RunsInvokePayload {
46
46
  * Checkpoint for when creating a new run.
47
47
  */
48
48
  checkpoint?: Omit<Checkpoint, "thread_id">;
49
+ /**
50
+ * Whether to checkpoint during the run (or only at the end/interruption).
51
+ */
52
+ checkpointDuring?: boolean;
49
53
  /**
50
54
  * Interrupt execution before entering these nodes.
51
55
  */
@@ -100,6 +104,13 @@ interface RunsInvokePayload {
100
104
  * One or more commands to invoke the graph with.
101
105
  */
102
106
  command?: Command;
107
+ /**
108
+ * Callback when a run is created.
109
+ */
110
+ onRunCreated?: (params: {
111
+ run_id: string;
112
+ thread_id?: string;
113
+ }) => void;
103
114
  }
104
115
  export interface RunsStreamPayload<TStreamMode extends StreamMode | StreamMode[] = [], TSubgraphs extends boolean = false> extends RunsInvokePayload {
105
116
  /**
@@ -15,9 +15,11 @@ type MessageTupleMetadata = {
15
15
  [key: string]: unknown;
16
16
  };
17
17
  type AsSubgraph<TEvent extends {
18
+ id?: string;
18
19
  event: string;
19
20
  data: unknown;
20
21
  }> = {
22
+ id?: TEvent["id"];
21
23
  event: TEvent["event"] | `${TEvent["event"]}|${string}`;
22
24
  data: TEvent["data"];
23
25
  };
@@ -25,6 +27,7 @@ type AsSubgraph<TEvent extends {
25
27
  * Stream event with values after completion of each step.
26
28
  */
27
29
  export type ValuesStreamEvent<StateType> = {
30
+ id?: string;
28
31
  event: "values";
29
32
  data: StateType;
30
33
  };
@@ -43,6 +46,7 @@ export type SubgraphMessagesTupleStreamEvent = AsSubgraph<MessagesTupleStreamEve
43
46
  * Metadata stream event with information about the run and thread
44
47
  */
45
48
  export type MetadataStreamEvent = {
49
+ id?: string;
46
50
  event: "metadata";
47
51
  data: {
48
52
  run_id: string;
@@ -53,6 +57,7 @@ export type MetadataStreamEvent = {
53
57
  * Stream event with error information.
54
58
  */
55
59
  export type ErrorStreamEvent = {
60
+ id?: string;
56
61
  event: "error";
57
62
  data: {
58
63
  error: string;
@@ -67,6 +72,7 @@ export type SubgraphErrorStreamEvent = AsSubgraph<ErrorStreamEvent>;
67
72
  * produced the update as well as the update.
68
73
  */
69
74
  export type UpdatesStreamEvent<UpdateType> = {
75
+ id?: string;
70
76
  event: "updates";
71
77
  data: {
72
78
  [node: string]: UpdateType;
@@ -84,6 +90,7 @@ export type CustomStreamEvent<T> = {
84
90
  /** @internal */
85
91
  export type SubgraphCustomStreamEvent<T> = AsSubgraph<CustomStreamEvent<T>>;
86
92
  type MessagesMetadataStreamEvent = {
93
+ id?: string;
87
94
  event: "messages/metadata";
88
95
  data: {
89
96
  [messageId: string]: {
@@ -92,10 +99,12 @@ type MessagesMetadataStreamEvent = {
92
99
  };
93
100
  };
94
101
  type MessagesCompleteStreamEvent = {
102
+ id?: string;
95
103
  event: "messages/complete";
96
104
  data: Message[];
97
105
  };
98
106
  type MessagesPartialStreamEvent = {
107
+ id?: string;
99
108
  event: "messages/partial";
100
109
  data: Message[];
101
110
  };
@@ -110,6 +119,7 @@ export type SubgraphMessagesStreamEvent = AsSubgraph<MessagesMetadataStreamEvent
110
119
  * Stream event with detailed debug information.
111
120
  */
112
121
  export type DebugStreamEvent = {
122
+ id?: string;
113
123
  event: "debug";
114
124
  data: unknown;
115
125
  };
@@ -119,6 +129,7 @@ export type SubgraphDebugStreamEvent = AsSubgraph<DebugStreamEvent>;
119
129
  * Stream event with events occurring during execution.
120
130
  */
121
131
  export type EventsStreamEvent = {
132
+ id?: string;
122
133
  event: "events";
123
134
  data: {
124
135
  event: `on_${"chat_model" | "llm" | "chain" | "tool" | "retriever" | "prompt"}_${"start" | "stream" | "end"}` | (string & {});
@@ -137,6 +148,7 @@ export type SubgraphEventsStreamEvent = AsSubgraph<EventsStreamEvent>;
137
148
  * the `RunsStreamPayload` to receive this event.
138
149
  */
139
150
  export type FeedbackStreamEvent = {
151
+ id?: string;
140
152
  event: "feedback";
141
153
  data: {
142
154
  [feedbackKey: string]: string;
@@ -94,6 +94,7 @@ class SSEDecoder extends TransformStream {
94
94
  if (!event && !data.length && !lastEventId && retry == null)
95
95
  return;
96
96
  const sse = {
97
+ id: lastEventId || undefined,
97
98
  event,
98
99
  data: data.length ? decodeArraysToJson(decoder, data) : null,
99
100
  };
@@ -133,6 +134,7 @@ class SSEDecoder extends TransformStream {
133
134
  flush(controller) {
134
135
  if (event) {
135
136
  controller.enqueue({
137
+ id: lastEventId || undefined,
136
138
  event,
137
139
  data: data.length ? decodeArraysToJson(decoder, data) : null,
138
140
  });
@@ -2,6 +2,7 @@ export declare class BytesLineDecoder extends TransformStream<Uint8Array, Uint8A
2
2
  constructor();
3
3
  }
4
4
  interface StreamPart {
5
+ id: string | undefined;
5
6
  event: string;
6
7
  data: unknown;
7
8
  }
package/dist/utils/sse.js CHANGED
@@ -90,6 +90,7 @@ export class SSEDecoder extends TransformStream {
90
90
  if (!event && !data.length && !lastEventId && retry == null)
91
91
  return;
92
92
  const sse = {
93
+ id: lastEventId || undefined,
93
94
  event,
94
95
  data: data.length ? decodeArraysToJson(decoder, data) : null,
95
96
  };
@@ -129,6 +130,7 @@ export class SSEDecoder extends TransformStream {
129
130
  flush(controller) {
130
131
  if (event) {
131
132
  controller.enqueue({
133
+ id: lastEventId || undefined,
132
134
  event,
133
135
  data: data.length ? decodeArraysToJson(decoder, data) : null,
134
136
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-sdk",
3
- "version": "0.0.73",
3
+ "version": "0.0.75",
4
4
  "description": "Client library for interacting with the LangGraph API",
5
5
  "type": "module",
6
6
  "packageManager": "yarn@1.22.19",
@@ -10,7 +10,7 @@
10
10
  "prepack": "yarn run build",
11
11
  "format": "prettier --write src",
12
12
  "lint": "prettier --check src && tsc --noEmit",
13
- "test": "NODE_OPTIONS=--experimental-vm-modules jest --testPathIgnorePatterns=\\.int\\.test.ts",
13
+ "test": "vitest",
14
14
  "typedoc": "typedoc && typedoc src/react/index.ts --out docs/react --options typedoc.react.json && typedoc src/auth/index.ts --out docs/auth --options typedoc.auth.json"
15
15
  },
16
16
  "main": "index.js",
@@ -22,28 +22,32 @@
22
22
  "uuid": "^9.0.0"
23
23
  },
24
24
  "devDependencies": {
25
- "@jest/globals": "^29.7.0",
26
25
  "@langchain/core": "^0.3.31",
27
26
  "@langchain/scripts": "^0.1.4",
27
+ "@testing-library/dom": "^10.4.0",
28
+ "@testing-library/jest-dom": "^6.6.3",
29
+ "@testing-library/react": "^16.3.0",
30
+ "@testing-library/user-event": "^14.6.1",
28
31
  "@tsconfig/recommended": "^1.0.2",
29
- "@types/jest": "^29.5.12",
30
32
  "@types/node": "^20.12.12",
31
- "@types/uuid": "^9.0.1",
32
33
  "@types/react": "^19.0.8",
33
34
  "@types/react-dom": "^19.0.3",
35
+ "@types/uuid": "^9.0.1",
36
+ "@vitejs/plugin-react": "^4.4.1",
34
37
  "concat-md": "^0.5.1",
35
- "jest": "^29.7.0",
38
+ "jsdom": "^26.1.0",
39
+ "msw": "^2.8.2",
36
40
  "prettier": "^3.2.5",
37
- "ts-jest": "^29.1.2",
41
+ "react": "^19.0.0",
42
+ "react-dom": "^19.0.0",
38
43
  "typedoc": "^0.27.7",
39
44
  "typedoc-plugin-markdown": "^4.4.2",
40
45
  "typescript": "^5.4.5",
41
- "react": "^19.0.0",
42
- "react-dom": "^19.0.0"
46
+ "vitest": "^3.1.3"
43
47
  },
44
48
  "peerDependencies": {
45
- "react": "^18 || ^19",
46
- "@langchain/core": ">=0.2.31 <0.4.0"
49
+ "@langchain/core": ">=0.2.31 <0.4.0",
50
+ "react": "^18 || ^19"
47
51
  },
48
52
  "peerDependenciesMeta": {
49
53
  "react": {