@langchain/langgraph-sdk 0.0.105 → 0.0.109

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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @langchain/langgraph-sdk
2
2
 
3
+ ## 0.0.109
4
+
5
+ ### Patch Changes
6
+
7
+ - e8b4540: Add support for select statements in the search endpoints
8
+ - 9c57526: fix(sdk): expose subgraph events in useStream callbacks
9
+
10
+ ## 0.0.107
11
+
12
+ ### Patch Changes
13
+
14
+ - 72386a4: feat(sdk): expose stream metadata from messages via `getMessagesMetadata`
15
+ - 3ee5c20: fix(sdk): avoid setting `messages-tuple` if only `getMessagesMetadata` is requested.
16
+
17
+ ## 0.0.106
18
+
19
+ ### Patch Changes
20
+
21
+ - feat(sdk): allow setting `checkpoint: null` when submitting a run via useStream
22
+
3
23
  ## 0.0.105
4
24
 
5
25
  ### Patch Changes
package/dist/client.cjs CHANGED
@@ -300,6 +300,7 @@ class CronsClient extends BaseClient {
300
300
  offset: query?.offset ?? 0,
301
301
  sort_by: query?.sortBy ?? undefined,
302
302
  sort_order: query?.sortOrder ?? undefined,
303
+ select: query?.select ?? undefined,
303
304
  },
304
305
  });
305
306
  }
@@ -413,6 +414,7 @@ class AssistantsClient extends BaseClient {
413
414
  offset: query?.offset ?? 0,
414
415
  sort_by: query?.sortBy ?? undefined,
415
416
  sort_order: query?.sortOrder ?? undefined,
417
+ select: query?.select ?? undefined,
416
418
  },
417
419
  });
418
420
  }
@@ -532,6 +534,7 @@ class ThreadsClient extends BaseClient {
532
534
  status: query?.status,
533
535
  sort_by: query?.sortBy,
534
536
  sort_order: query?.sortOrder,
537
+ select: query?.select ?? undefined,
535
538
  },
536
539
  });
537
540
  }
@@ -795,6 +798,7 @@ class RunsClient extends BaseClient {
795
798
  limit: options?.limit ?? 10,
796
799
  offset: options?.offset ?? 0,
797
800
  status: options?.status ?? undefined,
801
+ select: options?.select ?? undefined,
798
802
  },
799
803
  });
800
804
  }
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Assistant, AssistantGraph, AssistantSortBy, AssistantVersion, CancelAction, Checkpoint, Config, Cron, CronCreateForThreadResponse, CronCreateResponse, CronSortBy, DefaultValues, GraphSchema, Item, ListNamespaceResponse, Metadata, Run, RunStatus, SearchItemsResponse, SortOrder, Subgraphs, Thread, ThreadSortBy, ThreadState, ThreadStatus } from "./schema.js";
1
+ import { Assistant, AssistantGraph, AssistantSortBy, AssistantSelectField, AssistantVersion, CancelAction, Checkpoint, Config, Cron, CronSelectField, CronCreateForThreadResponse, CronCreateResponse, CronSortBy, DefaultValues, GraphSchema, Item, ListNamespaceResponse, Metadata, Run, RunSelectField, RunStatus, SearchItemsResponse, SortOrder, Subgraphs, Thread, ThreadSelectField, ThreadSortBy, ThreadState, ThreadStatus } from "./schema.js";
2
2
  import type { Command, CronsCreatePayload, OnConflictBehavior, RunsCreatePayload, RunsStreamPayload, RunsWaitPayload, StreamEvent } from "./types.js";
3
3
  import type { StreamMode, TypedAsyncGenerator } from "./types.stream.js";
4
4
  import { AsyncCaller, AsyncCallerParams } from "./utils/async_caller.js";
@@ -85,6 +85,7 @@ export declare class CronsClient extends BaseClient {
85
85
  offset?: number;
86
86
  sortBy?: CronSortBy;
87
87
  sortOrder?: SortOrder;
88
+ select?: CronSelectField[];
88
89
  }): Promise<Cron[]>;
89
90
  }
90
91
  export declare class AssistantsClient extends BaseClient {
@@ -168,6 +169,7 @@ export declare class AssistantsClient extends BaseClient {
168
169
  offset?: number;
169
170
  sortBy?: AssistantSortBy;
170
171
  sortOrder?: SortOrder;
172
+ select?: AssistantSelectField[];
171
173
  }): Promise<Assistant[]>;
172
174
  /**
173
175
  * List all versions of an assistant.
@@ -295,6 +297,7 @@ export declare class ThreadsClient<TStateType = DefaultValues, TUpdateType = TSt
295
297
  * Must be one of 'asc' or 'desc'.
296
298
  */
297
299
  sortOrder?: SortOrder;
300
+ select?: ThreadSelectField[];
298
301
  }): Promise<Thread<ValuesType>[]>;
299
302
  /**
300
303
  * Get state for a thread.
@@ -383,6 +386,7 @@ export declare class RunsClient<TStateType = DefaultValues, TUpdateType = TState
383
386
  * Status of the run to filter by.
384
387
  */
385
388
  status?: RunStatus;
389
+ select?: RunSelectField[];
386
390
  }): Promise<Run[]>;
387
391
  /**
388
392
  * Get a run by ID.
package/dist/client.js CHANGED
@@ -295,6 +295,7 @@ export class CronsClient extends BaseClient {
295
295
  offset: query?.offset ?? 0,
296
296
  sort_by: query?.sortBy ?? undefined,
297
297
  sort_order: query?.sortOrder ?? undefined,
298
+ select: query?.select ?? undefined,
298
299
  },
299
300
  });
300
301
  }
@@ -407,6 +408,7 @@ export class AssistantsClient extends BaseClient {
407
408
  offset: query?.offset ?? 0,
408
409
  sort_by: query?.sortBy ?? undefined,
409
410
  sort_order: query?.sortOrder ?? undefined,
411
+ select: query?.select ?? undefined,
410
412
  },
411
413
  });
412
414
  }
@@ -525,6 +527,7 @@ export class ThreadsClient extends BaseClient {
525
527
  status: query?.status,
526
528
  sort_by: query?.sortBy,
527
529
  sort_order: query?.sortOrder,
530
+ select: query?.select ?? undefined,
528
531
  },
529
532
  });
530
533
  }
@@ -787,6 +790,7 @@ export class RunsClient extends BaseClient {
787
790
  limit: options?.limit ?? 10,
788
791
  offset: options?.offset ?? 0,
789
792
  status: options?.status ?? undefined,
793
+ select: options?.select ?? undefined,
790
794
  },
791
795
  });
792
796
  }
@@ -34,7 +34,7 @@ class MessageTupleManager {
34
34
  });
35
35
  this.chunks = {};
36
36
  }
37
- add(serialized) {
37
+ add(serialized, metadata) {
38
38
  // TODO: this is sometimes sent from the API
39
39
  // figure out how to prevent this or move this to LC.js
40
40
  if (serialized.type.endsWith("MessageChunk")) {
@@ -51,6 +51,7 @@ class MessageTupleManager {
51
51
  return null;
52
52
  }
53
53
  this.chunks[id] ??= {};
54
+ this.chunks[id].metadata = metadata ?? this.chunks[id].metadata;
54
55
  if (chunk) {
55
56
  const prev = this.chunks[id].chunk;
56
57
  this.chunks[id].chunk =
@@ -67,7 +68,8 @@ class MessageTupleManager {
67
68
  get(id, defaultIndex) {
68
69
  if (this.chunks[id] == null)
69
70
  return null;
70
- this.chunks[id].index ??= defaultIndex;
71
+ if (defaultIndex != null)
72
+ this.chunks[id].index ??= defaultIndex;
71
73
  return this.chunks[id];
72
74
  }
73
75
  }
@@ -282,6 +284,9 @@ function useStreamValuesState() {
282
284
  return [values?.[0] ?? null, setStreamValues, mutate];
283
285
  }
284
286
  function useStream(options) {
287
+ const matchEventType = (expected, actual, _data) => {
288
+ return expected === actual || actual.startsWith(`${expected}|`);
289
+ };
285
290
  let { messagesKey } = options;
286
291
  const { assistantId, fetchStateHistory } = options;
287
292
  const { onCreated, onError, onFinish } = options;
@@ -396,6 +401,9 @@ function useStream(options) {
396
401
  const alreadyShown = new Set();
397
402
  return getMessages(historyValues).map((message, idx) => {
398
403
  const messageId = message.id ?? idx;
404
+ const streamMetadata = message.id != null
405
+ ? messageManagerRef.current.get(message.id)?.metadata ?? undefined
406
+ : undefined;
399
407
  const firstSeenIdx = findLastIndex(history.data ?? [], (state) => getMessages(state.values)
400
408
  .map((m, idx) => m.id ?? idx)
401
409
  .includes(messageId));
@@ -418,6 +426,7 @@ function useStream(options) {
418
426
  firstSeenState: firstSeen,
419
427
  branch: branch?.branch,
420
428
  branchOptions: branch?.branchOptions,
429
+ streamMetadata,
421
430
  };
422
431
  });
423
432
  })();
@@ -448,38 +457,39 @@ function useStream(options) {
448
457
  streamError = new StreamError(data);
449
458
  break;
450
459
  }
451
- if (event === "updates")
452
- options.onUpdateEvent?.(data);
453
- if (event === "custom" ||
454
- // if `streamSubgraphs: true`, then we also want
455
- // to also receive custom events from subgraphs
456
- event.startsWith("custom|"))
457
- options.onCustomEvent?.(data, {
458
- mutate: getMutateFn("stream", historyValues),
459
- });
460
+ const namespace = event.includes("|")
461
+ ? event.split("|").slice(1)
462
+ : undefined;
463
+ const mutate = getMutateFn("stream", historyValues);
460
464
  if (event === "metadata")
461
465
  options.onMetadataEvent?.(data);
462
466
  if (event === "events")
463
467
  options.onLangChainEvent?.(data);
464
- if (event === "debug")
465
- options.onDebugEvent?.(data);
466
- if (event === "checkpoints")
467
- options.onCheckpointEvent?.(data);
468
- if (event === "tasks")
469
- options.onTaskEvent?.(data);
468
+ if (matchEventType("updates", event, data)) {
469
+ options.onUpdateEvent?.(data, { namespace, mutate });
470
+ }
471
+ if (matchEventType("custom", event, data)) {
472
+ options.onCustomEvent?.(data, { namespace, mutate });
473
+ }
474
+ if (matchEventType("checkpoints", event, data)) {
475
+ options.onCheckpointEvent?.(data, { namespace });
476
+ }
477
+ if (matchEventType("tasks", event, data)) {
478
+ options.onTaskEvent?.(data, { namespace });
479
+ }
480
+ if (matchEventType("debug", event, data)) {
481
+ options.onDebugEvent?.(data, { namespace });
482
+ }
470
483
  if (event === "values") {
471
- if ("__interrupt__" in data) {
472
- // don't update values on interrupt values event
484
+ // don't update values on interrupt values event
485
+ if ("__interrupt__" in data)
473
486
  continue;
474
- }
475
487
  setStreamValues(data);
476
488
  }
477
- if (event === "messages" ||
478
- // if `streamSubgraphs: true`, then we also want
479
- // to also receive messages from subgraphs
480
- event.startsWith("messages|")) {
481
- const [serialized] = data;
482
- const messageId = messageManagerRef.current.add(serialized);
489
+ // Consume subgraph messages as well
490
+ if (matchEventType("messages", event, data)) {
491
+ const [serialized, metadata] = data;
492
+ const messageId = messageManagerRef.current.add(serialized, metadata);
483
493
  if (!messageId) {
484
494
  console.warn("Failed to add message to manager, no message ID found");
485
495
  continue;
@@ -580,7 +590,11 @@ function useStream(options) {
580
590
  ...trackStreamModeRef.current,
581
591
  ...callbackStreamMode,
582
592
  ]);
583
- const checkpoint = submitOptions?.checkpoint ?? threadHead?.checkpoint ?? undefined;
593
+ let checkpoint = submitOptions?.checkpoint ?? threadHead?.checkpoint ?? undefined;
594
+ // Avoid specifying a checkpoint if user explicitly set it to null
595
+ if (submitOptions?.checkpoint === null) {
596
+ checkpoint = undefined;
597
+ }
584
598
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
585
599
  // @ts-expect-error
586
600
  if (checkpoint != null)
@@ -698,7 +712,7 @@ function useStream(options) {
698
712
  return getMessages(values);
699
713
  },
700
714
  getMessagesMetadata(message, index) {
701
- trackStreamMode("messages-tuple", "values");
715
+ trackStreamMode("values");
702
716
  return messageMetadata?.find((m) => m.messageId === (message.id ?? index));
703
717
  },
704
718
  };
@@ -34,6 +34,11 @@ export type MessageMetadata<StateType extends Record<string, unknown>> = {
34
34
  * This is useful for displaying branching controls.
35
35
  */
36
36
  branchOptions: string[] | undefined;
37
+ /**
38
+ * Metadata sent alongside the message during run streaming.
39
+ * @remarks This metadata only exists temporarily in browser memory during streaming and is not persisted after completion.
40
+ */
41
+ streamMetadata: Record<string, unknown> | undefined;
37
42
  };
38
43
  type BagTemplate = {
39
44
  ConfigurableType?: Record<string, unknown>;
@@ -104,11 +109,15 @@ export interface UseStreamOptions<StateType extends Record<string, unknown> = Re
104
109
  /**
105
110
  * Callback that is called when an update event is received.
106
111
  */
107
- onUpdateEvent?: (data: UpdatesStreamEvent<GetUpdateType<Bag, StateType>>["data"]) => void;
112
+ onUpdateEvent?: (data: UpdatesStreamEvent<GetUpdateType<Bag, StateType>>["data"], options: {
113
+ namespace: string[] | undefined;
114
+ mutate: (update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)) => void;
115
+ }) => void;
108
116
  /**
109
117
  * Callback that is called when a custom event is received.
110
118
  */
111
119
  onCustomEvent?: (data: CustomStreamEvent<GetCustomEventType<Bag>>["data"], options: {
120
+ namespace: string[] | undefined;
112
121
  mutate: (update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)) => void;
113
122
  }) => void;
114
123
  /**
@@ -124,15 +133,21 @@ export interface UseStreamOptions<StateType extends Record<string, unknown> = Re
124
133
  * Callback that is called when a debug event is received.
125
134
  * @internal This API is experimental and subject to change.
126
135
  */
127
- onDebugEvent?: (data: DebugStreamEvent["data"]) => void;
136
+ onDebugEvent?: (data: DebugStreamEvent["data"], options: {
137
+ namespace: string[] | undefined;
138
+ }) => void;
128
139
  /**
129
140
  * Callback that is called when a checkpoints event is received.
130
141
  */
131
- onCheckpointEvent?: (data: CheckpointsStreamEvent<StateType>["data"]) => void;
142
+ onCheckpointEvent?: (data: CheckpointsStreamEvent<StateType>["data"], options: {
143
+ namespace: string[] | undefined;
144
+ }) => void;
132
145
  /**
133
146
  * Callback that is called when a tasks event is received.
134
147
  */
135
- onTaskEvent?: (data: TasksStreamEvent<StateType, GetUpdateType<Bag, StateType>>["data"]) => void;
148
+ onTaskEvent?: (data: TasksStreamEvent<StateType, GetUpdateType<Bag, StateType>>["data"], options: {
149
+ namespace: string[] | undefined;
150
+ }) => void;
136
151
  /**
137
152
  * Callback that is called when the stream is stopped by the user.
138
153
  * Provides a mutate function to update the stream state immediately
@@ -30,7 +30,7 @@ class MessageTupleManager {
30
30
  });
31
31
  this.chunks = {};
32
32
  }
33
- add(serialized) {
33
+ add(serialized, metadata) {
34
34
  // TODO: this is sometimes sent from the API
35
35
  // figure out how to prevent this or move this to LC.js
36
36
  if (serialized.type.endsWith("MessageChunk")) {
@@ -47,6 +47,7 @@ class MessageTupleManager {
47
47
  return null;
48
48
  }
49
49
  this.chunks[id] ??= {};
50
+ this.chunks[id].metadata = metadata ?? this.chunks[id].metadata;
50
51
  if (chunk) {
51
52
  const prev = this.chunks[id].chunk;
52
53
  this.chunks[id].chunk =
@@ -63,7 +64,8 @@ class MessageTupleManager {
63
64
  get(id, defaultIndex) {
64
65
  if (this.chunks[id] == null)
65
66
  return null;
66
- this.chunks[id].index ??= defaultIndex;
67
+ if (defaultIndex != null)
68
+ this.chunks[id].index ??= defaultIndex;
67
69
  return this.chunks[id];
68
70
  }
69
71
  }
@@ -278,6 +280,9 @@ function useStreamValuesState() {
278
280
  return [values?.[0] ?? null, setStreamValues, mutate];
279
281
  }
280
282
  export function useStream(options) {
283
+ const matchEventType = (expected, actual, _data) => {
284
+ return expected === actual || actual.startsWith(`${expected}|`);
285
+ };
281
286
  let { messagesKey } = options;
282
287
  const { assistantId, fetchStateHistory } = options;
283
288
  const { onCreated, onError, onFinish } = options;
@@ -392,6 +397,9 @@ export function useStream(options) {
392
397
  const alreadyShown = new Set();
393
398
  return getMessages(historyValues).map((message, idx) => {
394
399
  const messageId = message.id ?? idx;
400
+ const streamMetadata = message.id != null
401
+ ? messageManagerRef.current.get(message.id)?.metadata ?? undefined
402
+ : undefined;
395
403
  const firstSeenIdx = findLastIndex(history.data ?? [], (state) => getMessages(state.values)
396
404
  .map((m, idx) => m.id ?? idx)
397
405
  .includes(messageId));
@@ -414,6 +422,7 @@ export function useStream(options) {
414
422
  firstSeenState: firstSeen,
415
423
  branch: branch?.branch,
416
424
  branchOptions: branch?.branchOptions,
425
+ streamMetadata,
417
426
  };
418
427
  });
419
428
  })();
@@ -444,38 +453,39 @@ export function useStream(options) {
444
453
  streamError = new StreamError(data);
445
454
  break;
446
455
  }
447
- if (event === "updates")
448
- options.onUpdateEvent?.(data);
449
- if (event === "custom" ||
450
- // if `streamSubgraphs: true`, then we also want
451
- // to also receive custom events from subgraphs
452
- event.startsWith("custom|"))
453
- options.onCustomEvent?.(data, {
454
- mutate: getMutateFn("stream", historyValues),
455
- });
456
+ const namespace = event.includes("|")
457
+ ? event.split("|").slice(1)
458
+ : undefined;
459
+ const mutate = getMutateFn("stream", historyValues);
456
460
  if (event === "metadata")
457
461
  options.onMetadataEvent?.(data);
458
462
  if (event === "events")
459
463
  options.onLangChainEvent?.(data);
460
- if (event === "debug")
461
- options.onDebugEvent?.(data);
462
- if (event === "checkpoints")
463
- options.onCheckpointEvent?.(data);
464
- if (event === "tasks")
465
- options.onTaskEvent?.(data);
464
+ if (matchEventType("updates", event, data)) {
465
+ options.onUpdateEvent?.(data, { namespace, mutate });
466
+ }
467
+ if (matchEventType("custom", event, data)) {
468
+ options.onCustomEvent?.(data, { namespace, mutate });
469
+ }
470
+ if (matchEventType("checkpoints", event, data)) {
471
+ options.onCheckpointEvent?.(data, { namespace });
472
+ }
473
+ if (matchEventType("tasks", event, data)) {
474
+ options.onTaskEvent?.(data, { namespace });
475
+ }
476
+ if (matchEventType("debug", event, data)) {
477
+ options.onDebugEvent?.(data, { namespace });
478
+ }
466
479
  if (event === "values") {
467
- if ("__interrupt__" in data) {
468
- // don't update values on interrupt values event
480
+ // don't update values on interrupt values event
481
+ if ("__interrupt__" in data)
469
482
  continue;
470
- }
471
483
  setStreamValues(data);
472
484
  }
473
- if (event === "messages" ||
474
- // if `streamSubgraphs: true`, then we also want
475
- // to also receive messages from subgraphs
476
- event.startsWith("messages|")) {
477
- const [serialized] = data;
478
- const messageId = messageManagerRef.current.add(serialized);
485
+ // Consume subgraph messages as well
486
+ if (matchEventType("messages", event, data)) {
487
+ const [serialized, metadata] = data;
488
+ const messageId = messageManagerRef.current.add(serialized, metadata);
479
489
  if (!messageId) {
480
490
  console.warn("Failed to add message to manager, no message ID found");
481
491
  continue;
@@ -576,7 +586,11 @@ export function useStream(options) {
576
586
  ...trackStreamModeRef.current,
577
587
  ...callbackStreamMode,
578
588
  ]);
579
- const checkpoint = submitOptions?.checkpoint ?? threadHead?.checkpoint ?? undefined;
589
+ let checkpoint = submitOptions?.checkpoint ?? threadHead?.checkpoint ?? undefined;
590
+ // Avoid specifying a checkpoint if user explicitly set it to null
591
+ if (submitOptions?.checkpoint === null) {
592
+ checkpoint = undefined;
593
+ }
580
594
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
581
595
  // @ts-expect-error
582
596
  if (checkpoint != null)
@@ -694,7 +708,7 @@ export function useStream(options) {
694
708
  return getMessages(values);
695
709
  },
696
710
  getMessagesMetadata(message, index) {
697
- trackStreamMode("messages-tuple", "values");
711
+ trackStreamMode("values");
698
712
  return messageMetadata?.find((m) => m.messageId === (message.id ?? index));
699
713
  },
700
714
  };
package/dist/schema.d.ts CHANGED
@@ -263,4 +263,8 @@ export type AssistantSortBy = "assistant_id" | "graph_id" | "name" | "created_at
263
263
  export type ThreadSortBy = "thread_id" | "status" | "created_at" | "updated_at";
264
264
  export type CronSortBy = "cron_id" | "assistant_id" | "thread_id" | "created_at" | "updated_at" | "next_run_date";
265
265
  export type SortOrder = "asc" | "desc";
266
+ export type AssistantSelectField = "assistant_id" | "graph_id" | "name" | "description" | "config" | "context" | "created_at" | "updated_at" | "metadata" | "version";
267
+ export type ThreadSelectField = "thread_id" | "created_at" | "updated_at" | "metadata" | "config" | "context" | "status" | "values" | "interrupts";
268
+ export type RunSelectField = "run_id" | "thread_id" | "assistant_id" | "created_at" | "updated_at" | "status" | "metadata" | "kwargs" | "multitask_strategy";
269
+ export type CronSelectField = "cron_id" | "assistant_id" | "thread_id" | "end_time" | "schedule" | "created_at" | "updated_at" | "user_id" | "payload" | "next_run_date" | "metadata" | "now";
266
270
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-sdk",
3
- "version": "0.0.105",
3
+ "version": "0.0.109",
4
4
  "description": "Client library for interacting with the LangGraph API",
5
5
  "type": "module",
6
6
  "scripts": {