@langchain/langgraph-sdk 0.0.109 → 0.0.112

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,19 @@
1
1
  # @langchain/langgraph-sdk
2
2
 
3
+ ## 0.0.112
4
+
5
+ ### Patch Changes
6
+
7
+ - a50e02e: feat(sdk): add thread streaming endpoint
8
+ - 7e210a1: feat(sdk): add durability param to run methods
9
+ - 5766b62: Fix `isThreadLoading: false` when initially mounting in useStream
10
+
11
+ ## 0.0.111
12
+
13
+ ### Patch Changes
14
+
15
+ - b5f14d0: Add methods to connect with the /count endpoints
16
+
3
17
  ## 0.0.109
4
18
 
5
19
  ### Patch Changes
package/dist/client.cjs CHANGED
@@ -244,6 +244,7 @@ class CronsClient extends BaseClient {
244
244
  multitask_strategy: payload?.multitaskStrategy,
245
245
  if_not_exists: payload?.ifNotExists,
246
246
  checkpoint_during: payload?.checkpointDuring,
247
+ durability: payload?.durability,
247
248
  };
248
249
  return this.fetch(`/threads/${threadId}/runs/crons`, {
249
250
  method: "POST",
@@ -270,6 +271,7 @@ class CronsClient extends BaseClient {
270
271
  multitask_strategy: payload?.multitaskStrategy,
271
272
  if_not_exists: payload?.ifNotExists,
272
273
  checkpoint_during: payload?.checkpointDuring,
274
+ durability: payload?.durability,
273
275
  };
274
276
  return this.fetch(`/runs/crons`, {
275
277
  method: "POST",
@@ -304,6 +306,22 @@ class CronsClient extends BaseClient {
304
306
  },
305
307
  });
306
308
  }
309
+ /**
310
+ * Count cron jobs matching filters.
311
+ *
312
+ * @param query.assistantId Assistant ID to filter by.
313
+ * @param query.threadId Thread ID to filter by.
314
+ * @returns Number of cron jobs matching the criteria.
315
+ */
316
+ async count(query) {
317
+ return this.fetch(`/runs/crons/count`, {
318
+ method: "POST",
319
+ json: {
320
+ assistant_id: query?.assistantId ?? undefined,
321
+ thread_id: query?.threadId ?? undefined,
322
+ },
323
+ });
324
+ }
307
325
  }
308
326
  exports.CronsClient = CronsClient;
309
327
  class AssistantsClient extends BaseClient {
@@ -418,6 +436,22 @@ class AssistantsClient extends BaseClient {
418
436
  },
419
437
  });
420
438
  }
439
+ /**
440
+ * Count assistants matching filters.
441
+ *
442
+ * @param query.metadata Metadata to filter by. Exact match for each key/value.
443
+ * @param query.graphId Optional graph id to filter by.
444
+ * @returns Number of assistants matching the criteria.
445
+ */
446
+ async count(query) {
447
+ return this.fetch(`/assistants/count`, {
448
+ method: "POST",
449
+ json: {
450
+ metadata: query?.metadata ?? undefined,
451
+ graph_id: query?.graphId ?? undefined,
452
+ },
453
+ });
454
+ }
421
455
  /**
422
456
  * List all versions of an assistant.
423
457
  *
@@ -538,6 +572,24 @@ class ThreadsClient extends BaseClient {
538
572
  },
539
573
  });
540
574
  }
575
+ /**
576
+ * Count threads matching filters.
577
+ *
578
+ * @param query.metadata Thread metadata to filter on.
579
+ * @param query.values State values to filter on.
580
+ * @param query.status Thread status to filter on.
581
+ * @returns Number of threads matching the criteria.
582
+ */
583
+ async count(query) {
584
+ return this.fetch(`/threads/count`, {
585
+ method: "POST",
586
+ json: {
587
+ metadata: query?.metadata ?? undefined,
588
+ values: query?.values ?? undefined,
589
+ status: query?.status ?? undefined,
590
+ },
591
+ });
592
+ }
541
593
  /**
542
594
  * Get state for a thread.
543
595
  *
@@ -616,6 +668,24 @@ class ThreadsClient extends BaseClient {
616
668
  },
617
669
  });
618
670
  }
671
+ async *joinStream(threadId, options
672
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
673
+ ) {
674
+ const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(`/threads/${threadId}/stream`, {
675
+ method: "GET",
676
+ headers: options?.lastEventId
677
+ ? { "Last-Event-ID": options.lastEventId }
678
+ : undefined,
679
+ params: options?.streamMode
680
+ ? { stream_mode: options.streamMode }
681
+ : undefined,
682
+ }));
683
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
684
+ const stream = (response.body || new ReadableStream({ start: (ctrl) => ctrl.close() }))
685
+ .pipeThrough((0, sse_js_1.BytesLineDecoder)())
686
+ .pipeThrough((0, sse_js_1.SSEDecoder)());
687
+ yield* stream_js_1.IterableReadableStream.fromReadableStream(stream);
688
+ }
619
689
  }
620
690
  exports.ThreadsClient = ThreadsClient;
621
691
  class RunsClient extends BaseClient {
@@ -649,6 +719,7 @@ class RunsClient extends BaseClient {
649
719
  after_seconds: payload?.afterSeconds,
650
720
  if_not_exists: payload?.ifNotExists,
651
721
  checkpoint_during: payload?.checkpointDuring,
722
+ durability: payload?.durability,
652
723
  };
653
724
  const endpoint = threadId == null ? `/runs/stream` : `/threads/${threadId}/runs/stream`;
654
725
  const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(endpoint, {
@@ -694,6 +765,7 @@ class RunsClient extends BaseClient {
694
765
  after_seconds: payload?.afterSeconds,
695
766
  if_not_exists: payload?.ifNotExists,
696
767
  checkpoint_during: payload?.checkpointDuring,
768
+ durability: payload?.durability,
697
769
  langsmith_tracer: payload?._langsmithTracer
698
770
  ? {
699
771
  project_name: payload?._langsmithTracer?.projectName,
@@ -756,6 +828,7 @@ class RunsClient extends BaseClient {
756
828
  after_seconds: payload?.afterSeconds,
757
829
  if_not_exists: payload?.ifNotExists,
758
830
  checkpoint_during: payload?.checkpointDuring,
831
+ durability: payload?.durability,
759
832
  langsmith_tracer: payload?._langsmithTracer
760
833
  ? {
761
834
  project_name: payload?._langsmithTracer?.projectName,
package/dist/client.d.ts CHANGED
@@ -1,6 +1,6 @@
1
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
- import type { StreamMode, TypedAsyncGenerator } from "./types.stream.js";
3
+ import type { StreamMode, ThreadStreamMode, TypedAsyncGenerator } from "./types.stream.js";
4
4
  import { AsyncCaller, AsyncCallerParams } from "./utils/async_caller.js";
5
5
  type HeaderValue = string | undefined | null;
6
6
  /**
@@ -87,6 +87,17 @@ export declare class CronsClient extends BaseClient {
87
87
  sortOrder?: SortOrder;
88
88
  select?: CronSelectField[];
89
89
  }): Promise<Cron[]>;
90
+ /**
91
+ * Count cron jobs matching filters.
92
+ *
93
+ * @param query.assistantId Assistant ID to filter by.
94
+ * @param query.threadId Thread ID to filter by.
95
+ * @returns Number of cron jobs matching the criteria.
96
+ */
97
+ count(query?: {
98
+ assistantId?: string;
99
+ threadId?: string;
100
+ }): Promise<number>;
90
101
  }
91
102
  export declare class AssistantsClient extends BaseClient {
92
103
  /**
@@ -171,6 +182,17 @@ export declare class AssistantsClient extends BaseClient {
171
182
  sortOrder?: SortOrder;
172
183
  select?: AssistantSelectField[];
173
184
  }): Promise<Assistant[]>;
185
+ /**
186
+ * Count assistants matching filters.
187
+ *
188
+ * @param query.metadata Metadata to filter by. Exact match for each key/value.
189
+ * @param query.graphId Optional graph id to filter by.
190
+ * @returns Number of assistants matching the criteria.
191
+ */
192
+ count(query?: {
193
+ metadata?: Metadata;
194
+ graphId?: string;
195
+ }): Promise<number>;
174
196
  /**
175
197
  * List all versions of an assistant.
176
198
  *
@@ -299,6 +321,19 @@ export declare class ThreadsClient<TStateType = DefaultValues, TUpdateType = TSt
299
321
  sortOrder?: SortOrder;
300
322
  select?: ThreadSelectField[];
301
323
  }): Promise<Thread<ValuesType>[]>;
324
+ /**
325
+ * Count threads matching filters.
326
+ *
327
+ * @param query.metadata Thread metadata to filter on.
328
+ * @param query.values State values to filter on.
329
+ * @param query.status Thread status to filter on.
330
+ * @returns Number of threads matching the criteria.
331
+ */
332
+ count<ValuesType = TStateType>(query?: {
333
+ metadata?: Metadata;
334
+ values?: ValuesType;
335
+ status?: ThreadStatus;
336
+ }): Promise<number>;
302
337
  /**
303
338
  * Get state for a thread.
304
339
  *
@@ -340,6 +375,14 @@ export declare class ThreadsClient<TStateType = DefaultValues, TUpdateType = TSt
340
375
  checkpoint?: Partial<Omit<Checkpoint, "thread_id">>;
341
376
  metadata?: Metadata;
342
377
  }): Promise<ThreadState<ValuesType>[]>;
378
+ joinStream(threadId: string, options?: {
379
+ lastEventId?: string;
380
+ streamMode?: ThreadStreamMode | ThreadStreamMode[];
381
+ }): AsyncGenerator<{
382
+ id?: string;
383
+ event: StreamEvent;
384
+ data: any;
385
+ }>;
343
386
  }
344
387
  export declare class RunsClient<TStateType = DefaultValues, TUpdateType = TStateType, TCustomEventType = unknown> extends BaseClient {
345
388
  stream<TStreamMode extends StreamMode | StreamMode[] = StreamMode, TSubgraphs extends boolean = false>(threadId: null, assistantId: string, payload?: Omit<RunsStreamPayload<TStreamMode, TSubgraphs>, "multitaskStrategy" | "onCompletion">): TypedAsyncGenerator<TStreamMode, TSubgraphs, TStateType, TUpdateType, TCustomEventType>;
package/dist/client.js CHANGED
@@ -239,6 +239,7 @@ export class CronsClient extends BaseClient {
239
239
  multitask_strategy: payload?.multitaskStrategy,
240
240
  if_not_exists: payload?.ifNotExists,
241
241
  checkpoint_during: payload?.checkpointDuring,
242
+ durability: payload?.durability,
242
243
  };
243
244
  return this.fetch(`/threads/${threadId}/runs/crons`, {
244
245
  method: "POST",
@@ -265,6 +266,7 @@ export class CronsClient extends BaseClient {
265
266
  multitask_strategy: payload?.multitaskStrategy,
266
267
  if_not_exists: payload?.ifNotExists,
267
268
  checkpoint_during: payload?.checkpointDuring,
269
+ durability: payload?.durability,
268
270
  };
269
271
  return this.fetch(`/runs/crons`, {
270
272
  method: "POST",
@@ -299,6 +301,22 @@ export class CronsClient extends BaseClient {
299
301
  },
300
302
  });
301
303
  }
304
+ /**
305
+ * Count cron jobs matching filters.
306
+ *
307
+ * @param query.assistantId Assistant ID to filter by.
308
+ * @param query.threadId Thread ID to filter by.
309
+ * @returns Number of cron jobs matching the criteria.
310
+ */
311
+ async count(query) {
312
+ return this.fetch(`/runs/crons/count`, {
313
+ method: "POST",
314
+ json: {
315
+ assistant_id: query?.assistantId ?? undefined,
316
+ thread_id: query?.threadId ?? undefined,
317
+ },
318
+ });
319
+ }
302
320
  }
303
321
  export class AssistantsClient extends BaseClient {
304
322
  /**
@@ -412,6 +430,22 @@ export class AssistantsClient extends BaseClient {
412
430
  },
413
431
  });
414
432
  }
433
+ /**
434
+ * Count assistants matching filters.
435
+ *
436
+ * @param query.metadata Metadata to filter by. Exact match for each key/value.
437
+ * @param query.graphId Optional graph id to filter by.
438
+ * @returns Number of assistants matching the criteria.
439
+ */
440
+ async count(query) {
441
+ return this.fetch(`/assistants/count`, {
442
+ method: "POST",
443
+ json: {
444
+ metadata: query?.metadata ?? undefined,
445
+ graph_id: query?.graphId ?? undefined,
446
+ },
447
+ });
448
+ }
415
449
  /**
416
450
  * List all versions of an assistant.
417
451
  *
@@ -531,6 +565,24 @@ export class ThreadsClient extends BaseClient {
531
565
  },
532
566
  });
533
567
  }
568
+ /**
569
+ * Count threads matching filters.
570
+ *
571
+ * @param query.metadata Thread metadata to filter on.
572
+ * @param query.values State values to filter on.
573
+ * @param query.status Thread status to filter on.
574
+ * @returns Number of threads matching the criteria.
575
+ */
576
+ async count(query) {
577
+ return this.fetch(`/threads/count`, {
578
+ method: "POST",
579
+ json: {
580
+ metadata: query?.metadata ?? undefined,
581
+ values: query?.values ?? undefined,
582
+ status: query?.status ?? undefined,
583
+ },
584
+ });
585
+ }
534
586
  /**
535
587
  * Get state for a thread.
536
588
  *
@@ -609,6 +661,24 @@ export class ThreadsClient extends BaseClient {
609
661
  },
610
662
  });
611
663
  }
664
+ async *joinStream(threadId, options
665
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
666
+ ) {
667
+ const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(`/threads/${threadId}/stream`, {
668
+ method: "GET",
669
+ headers: options?.lastEventId
670
+ ? { "Last-Event-ID": options.lastEventId }
671
+ : undefined,
672
+ params: options?.streamMode
673
+ ? { stream_mode: options.streamMode }
674
+ : undefined,
675
+ }));
676
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
677
+ const stream = (response.body || new ReadableStream({ start: (ctrl) => ctrl.close() }))
678
+ .pipeThrough(BytesLineDecoder())
679
+ .pipeThrough(SSEDecoder());
680
+ yield* IterableReadableStream.fromReadableStream(stream);
681
+ }
612
682
  }
613
683
  export class RunsClient extends BaseClient {
614
684
  /**
@@ -641,6 +711,7 @@ export class RunsClient extends BaseClient {
641
711
  after_seconds: payload?.afterSeconds,
642
712
  if_not_exists: payload?.ifNotExists,
643
713
  checkpoint_during: payload?.checkpointDuring,
714
+ durability: payload?.durability,
644
715
  };
645
716
  const endpoint = threadId == null ? `/runs/stream` : `/threads/${threadId}/runs/stream`;
646
717
  const response = await this.asyncCaller.fetch(...this.prepareFetchOptions(endpoint, {
@@ -686,6 +757,7 @@ export class RunsClient extends BaseClient {
686
757
  after_seconds: payload?.afterSeconds,
687
758
  if_not_exists: payload?.ifNotExists,
688
759
  checkpoint_during: payload?.checkpointDuring,
760
+ durability: payload?.durability,
689
761
  langsmith_tracer: payload?._langsmithTracer
690
762
  ? {
691
763
  project_name: payload?._langsmithTracer?.projectName,
@@ -748,6 +820,7 @@ export class RunsClient extends BaseClient {
748
820
  after_seconds: payload?.afterSeconds,
749
821
  if_not_exists: payload?.ifNotExists,
750
822
  checkpoint_during: payload?.checkpointDuring,
823
+ durability: payload?.durability,
751
824
  langsmith_tracer: payload?._langsmithTracer
752
825
  ? {
753
826
  project_name: payload?._langsmithTracer?.projectName,
@@ -202,7 +202,11 @@ function fetchHistory(client, threadId, options) {
202
202
  }
203
203
  function useThreadHistory(threadId, client, limit, clearCallbackRef, submittingRef, onErrorRef) {
204
204
  const [history, setHistory] = (0, react_1.useState)(undefined);
205
- const [isLoading, setIsLoading] = (0, react_1.useState)(false);
205
+ const [isLoading, setIsLoading] = (0, react_1.useState)(() => {
206
+ if (threadId == null)
207
+ return false;
208
+ return true;
209
+ });
206
210
  const [error, setError] = (0, react_1.useState)(undefined);
207
211
  const clientHash = (0, client_js_1.getClientConfigHash)(client);
208
212
  const clientRef = (0, react_1.useRef)(client);
@@ -236,7 +240,7 @@ function useThreadHistory(threadId, client, limit, clearCallbackRef, submittingR
236
240
  if (submittingRef.current)
237
241
  return;
238
242
  void fetcher(threadId);
239
- }, [fetcher, clientHash, limit, submittingRef, threadId]);
243
+ }, [fetcher, submittingRef, clientHash, limit, threadId]);
240
244
  return {
241
245
  data: history,
242
246
  isLoading,
@@ -619,6 +623,7 @@ function useStream(options) {
619
623
  streamMode,
620
624
  streamSubgraphs: submitOptions?.streamSubgraphs,
621
625
  streamResumable,
626
+ durability: submitOptions?.durability,
622
627
  onRunCreated(params) {
623
628
  callbackMeta = {
624
629
  run_id: params.run_id,
@@ -1,5 +1,5 @@
1
1
  import { Client, type ClientConfig } from "../client.js";
2
- import type { Command, DisconnectMode, MultitaskStrategy, OnCompletionBehavior } from "../types.js";
2
+ import type { Command, DisconnectMode, Durability, MultitaskStrategy, OnCompletionBehavior } from "../types.js";
3
3
  import type { Message } from "../types.messages.js";
4
4
  import type { Checkpoint, Config, Interrupt, Metadata, ThreadState } from "../schema.js";
5
5
  import type { CheckpointsStreamEvent, CustomStreamEvent, DebugStreamEvent, EventsStreamEvent, MetadataStreamEvent, StreamMode, TasksStreamEvent, UpdatesStreamEvent } from "../types.stream.js";
@@ -304,6 +304,14 @@ interface SubmitOptions<StateType extends Record<string, unknown> = Record<strin
304
304
  */
305
305
  streamSubgraphs?: boolean;
306
306
  streamResumable?: boolean;
307
+ /**
308
+ * Whether to checkpoint during the run (or only at the end/interruption).
309
+ * - `"async"`: Save checkpoint asynchronously while the next step executes (default).
310
+ * - `"sync"`: Save checkpoint synchronously before the next step starts.
311
+ * - `"exit"`: Save checkpoint only when the graph exits.
312
+ * @default "async"
313
+ */
314
+ durability?: Durability;
307
315
  /**
308
316
  * The ID to use when creating a new thread. When provided, this ID will be used
309
317
  * for thread creation when threadId is `null` or `undefined`.
@@ -198,7 +198,11 @@ function fetchHistory(client, threadId, options) {
198
198
  }
199
199
  function useThreadHistory(threadId, client, limit, clearCallbackRef, submittingRef, onErrorRef) {
200
200
  const [history, setHistory] = useState(undefined);
201
- const [isLoading, setIsLoading] = useState(false);
201
+ const [isLoading, setIsLoading] = useState(() => {
202
+ if (threadId == null)
203
+ return false;
204
+ return true;
205
+ });
202
206
  const [error, setError] = useState(undefined);
203
207
  const clientHash = getClientConfigHash(client);
204
208
  const clientRef = useRef(client);
@@ -232,7 +236,7 @@ function useThreadHistory(threadId, client, limit, clearCallbackRef, submittingR
232
236
  if (submittingRef.current)
233
237
  return;
234
238
  void fetcher(threadId);
235
- }, [fetcher, clientHash, limit, submittingRef, threadId]);
239
+ }, [fetcher, submittingRef, clientHash, limit, threadId]);
236
240
  return {
237
241
  data: history,
238
242
  isLoading,
@@ -615,6 +619,7 @@ export function useStream(options) {
615
619
  streamMode,
616
620
  streamSubgraphs: submitOptions?.streamSubgraphs,
617
621
  streamResumable,
622
+ durability: submitOptions?.durability,
618
623
  onRunCreated(params) {
619
624
  callbackMeta = {
620
625
  run_id: params.run_id,
package/dist/types.d.ts CHANGED
@@ -5,6 +5,7 @@ export type MultitaskStrategy = "reject" | "interrupt" | "rollback" | "enqueue";
5
5
  export type OnConflictBehavior = "raise" | "do_nothing";
6
6
  export type OnCompletionBehavior = "complete" | "continue";
7
7
  export type DisconnectMode = "cancel" | "continue";
8
+ export type Durability = "exit" | "async" | "sync";
8
9
  export type StreamEvent = "events" | "metadata" | "debug" | "updates" | "values" | "messages/partial" | "messages/metadata" | "messages/complete" | "messages" | (string & {});
9
10
  export interface Send {
10
11
  node: string;
@@ -54,8 +55,17 @@ export interface RunsInvokePayload {
54
55
  checkpoint?: Omit<Checkpoint, "thread_id">;
55
56
  /**
56
57
  * Whether to checkpoint during the run (or only at the end/interruption).
58
+ * @deprecated Use `durability` instead.
57
59
  */
58
60
  checkpointDuring?: boolean;
61
+ /**
62
+ * Whether to checkpoint during the run (or only at the end/interruption).
63
+ * - `"async"`: Save checkpoint asynchronously while the next step executes (default).
64
+ * - `"sync"`: Save checkpoint synchronously before the next step starts.
65
+ * - `"exit"`: Save checkpoint only when the graph exits.
66
+ * @default "async"
67
+ */
68
+ durability?: Durability;
59
69
  /**
60
70
  * Interrupt execution before entering these nodes.
61
71
  */
@@ -12,6 +12,7 @@ import type { SubgraphCheckpointsStreamEvent } from "./types.stream.subgraph.js"
12
12
  * - "custom": Stream custom events.
13
13
  */
14
14
  export type StreamMode = "values" | "messages" | "updates" | "events" | "debug" | "tasks" | "checkpoints" | "custom" | "messages-tuple";
15
+ export type ThreadStreamMode = "run_modes" | "lifecycle" | "state_update";
15
16
  type MessageTupleMetadata = {
16
17
  tags: string[];
17
18
  [key: string]: unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-sdk",
3
- "version": "0.0.109",
3
+ "version": "0.0.112",
4
4
  "description": "Client library for interacting with the LangGraph API",
5
5
  "type": "module",
6
6
  "scripts": {