@langchain/langgraph-sdk 0.0.93 → 0.0.95

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,18 @@
1
1
  # @langchain/langgraph-sdk
2
2
 
3
+ ## 0.0.95
4
+
5
+ ### Patch Changes
6
+
7
+ - 39cc88f: useStream should receive and merge messages from subgraphs
8
+ - c1ddda1: Fix fetching state with `fetchStateHistory: false` causing crash if thread is empty
9
+
10
+ ## 0.0.94
11
+
12
+ ### Patch Changes
13
+
14
+ - 11e95e0: Add isStudioUser for custom auth
15
+
3
16
  ## 0.0.93
4
17
 
5
18
  ### Patch Changes
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HTTPException = exports.Auth = void 0;
4
+ exports.isStudioUser = isStudioUser;
4
5
  class Auth {
5
6
  constructor() {
6
7
  /**
@@ -28,5 +29,17 @@ class Auth {
28
29
  }
29
30
  }
30
31
  exports.Auth = Auth;
32
+ /**
33
+ * Check if the provided user was provided by LangGraph Studio.
34
+ *
35
+ * By default, if you add custom authorization on your resources, this will also apply to interactions made from the Studio.
36
+ * If you want, you can handle logged-in Studio users in a special way.
37
+ *
38
+ * @param user - The user to check
39
+ * @returns True if the user is a studio user, false otherwise
40
+ */
41
+ function isStudioUser(user) {
42
+ return user.identity === "langgraph-studio-user";
43
+ }
31
44
  var error_js_1 = require("./error.cjs");
32
45
  Object.defineProperty(exports, "HTTPException", { enumerable: true, get: function () { return error_js_1.HTTPException; } });
@@ -12,5 +12,15 @@ TAuthReturn extends BaseAuthReturn = BaseAuthReturn, TUser extends BaseUser = To
12
12
  authenticate<T extends BaseAuthReturn>(cb: AuthenticateCallback<T>): Auth<TExtra, T>;
13
13
  on<T extends CallbackEvent>(event: T, callback: OnCallback<T, TUser>): this;
14
14
  }
15
+ /**
16
+ * Check if the provided user was provided by LangGraph Studio.
17
+ *
18
+ * By default, if you add custom authorization on your resources, this will also apply to interactions made from the Studio.
19
+ * If you want, you can handle logged-in Studio users in a special way.
20
+ *
21
+ * @param user - The user to check
22
+ * @returns True if the user is a studio user, false otherwise
23
+ */
24
+ export declare function isStudioUser(user: BaseUser): boolean;
15
25
  export type { Filters as AuthFilters, EventValueMap as AuthEventValueMap, } from "./types.js";
16
26
  export { HTTPException } from "./error.js";
@@ -24,4 +24,16 @@ export class Auth {
24
24
  return this;
25
25
  }
26
26
  }
27
+ /**
28
+ * Check if the provided user was provided by LangGraph Studio.
29
+ *
30
+ * By default, if you add custom authorization on your resources, this will also apply to interactions made from the Studio.
31
+ * If you want, you can handle logged-in Studio users in a special way.
32
+ *
33
+ * @param user - The user to check
34
+ * @returns True if the user is a studio user, false otherwise
35
+ */
36
+ export function isStudioUser(user) {
37
+ return user.identity === "langgraph-studio-user";
38
+ }
27
39
  export { HTTPException } from "./error.js";
@@ -124,7 +124,9 @@ function getBranchSequence(history) {
124
124
  task.sequence.items.push(fork);
125
125
  }
126
126
  for (const value of children) {
127
- const id = value.checkpoint.checkpoint_id;
127
+ const id = value.checkpoint?.checkpoint_id;
128
+ if (id == null)
129
+ continue;
128
130
  let { sequence } = task;
129
131
  let { path } = task;
130
132
  if (fork != null) {
@@ -159,7 +161,10 @@ function getBranchView(sequence, paths, branch) {
159
161
  const item = queue.shift();
160
162
  if (item.type === "node") {
161
163
  history.push(item.value);
162
- branchByCheckpoint[item.value.checkpoint.checkpoint_id] = {
164
+ const checkpointId = item.value.checkpoint?.checkpoint_id;
165
+ if (checkpointId == null)
166
+ continue;
167
+ branchByCheckpoint[checkpointId] = {
163
168
  branch: item.path.join(PATH_SEP),
164
169
  branchOptions: (item.path.length > 0
165
170
  ? pathMap[item.path.at(-2) ?? ROOT_ID] ?? []
@@ -173,7 +178,7 @@ function getBranchView(sequence, paths, branch) {
173
178
  const firstItem = value.items.at(0);
174
179
  if (!firstItem || firstItem.type !== "node")
175
180
  return false;
176
- return firstItem.value.checkpoint.checkpoint_id === forkId;
181
+ return firstItem.value.checkpoint?.checkpoint_id === forkId;
177
182
  })
178
183
  : -1;
179
184
  const nextItems = item.items.at(index)?.items ?? [];
@@ -184,9 +189,11 @@ function getBranchView(sequence, paths, branch) {
184
189
  }
185
190
  function fetchHistory(client, threadId, options) {
186
191
  if (options?.limit === false) {
187
- return client.threads
188
- .getState(threadId)
189
- .then((state) => [state]);
192
+ return client.threads.getState(threadId).then((state) => {
193
+ if (state.checkpoint == null)
194
+ return [];
195
+ return [state];
196
+ });
190
197
  }
191
198
  const limit = typeof options?.limit === "number" ? options.limit : 1000;
192
199
  return client.threads.getHistory(threadId, { limit });
@@ -368,8 +375,9 @@ function useStream(options) {
368
375
  .map((m, idx) => m.id ?? idx)
369
376
  .includes(messageId));
370
377
  const firstSeen = history.data[firstSeenIdx];
371
- let branch = firstSeen
372
- ? branchByCheckpoint[firstSeen.checkpoint.checkpoint_id]
378
+ const checkpointId = firstSeen?.checkpoint?.checkpoint_id;
379
+ let branch = firstSeen && checkpointId != null
380
+ ? branchByCheckpoint[checkpointId]
373
381
  : undefined;
374
382
  if (!branch?.branch?.length)
375
383
  branch = undefined;
@@ -434,7 +442,10 @@ function useStream(options) {
434
442
  }
435
443
  setStreamValues(data);
436
444
  }
437
- if (event === "messages") {
445
+ if (event === "messages" ||
446
+ // if `streamSubgraphs: true`, then we also want
447
+ // to also receive messages from subgraphs
448
+ event.startsWith("messages|")) {
438
449
  const [serialized] = data;
439
450
  const messageId = messageManagerRef.current.add(serialized);
440
451
  if (!messageId) {
@@ -120,7 +120,9 @@ function getBranchSequence(history) {
120
120
  task.sequence.items.push(fork);
121
121
  }
122
122
  for (const value of children) {
123
- const id = value.checkpoint.checkpoint_id;
123
+ const id = value.checkpoint?.checkpoint_id;
124
+ if (id == null)
125
+ continue;
124
126
  let { sequence } = task;
125
127
  let { path } = task;
126
128
  if (fork != null) {
@@ -155,7 +157,10 @@ function getBranchView(sequence, paths, branch) {
155
157
  const item = queue.shift();
156
158
  if (item.type === "node") {
157
159
  history.push(item.value);
158
- branchByCheckpoint[item.value.checkpoint.checkpoint_id] = {
160
+ const checkpointId = item.value.checkpoint?.checkpoint_id;
161
+ if (checkpointId == null)
162
+ continue;
163
+ branchByCheckpoint[checkpointId] = {
159
164
  branch: item.path.join(PATH_SEP),
160
165
  branchOptions: (item.path.length > 0
161
166
  ? pathMap[item.path.at(-2) ?? ROOT_ID] ?? []
@@ -169,7 +174,7 @@ function getBranchView(sequence, paths, branch) {
169
174
  const firstItem = value.items.at(0);
170
175
  if (!firstItem || firstItem.type !== "node")
171
176
  return false;
172
- return firstItem.value.checkpoint.checkpoint_id === forkId;
177
+ return firstItem.value.checkpoint?.checkpoint_id === forkId;
173
178
  })
174
179
  : -1;
175
180
  const nextItems = item.items.at(index)?.items ?? [];
@@ -180,9 +185,11 @@ function getBranchView(sequence, paths, branch) {
180
185
  }
181
186
  function fetchHistory(client, threadId, options) {
182
187
  if (options?.limit === false) {
183
- return client.threads
184
- .getState(threadId)
185
- .then((state) => [state]);
188
+ return client.threads.getState(threadId).then((state) => {
189
+ if (state.checkpoint == null)
190
+ return [];
191
+ return [state];
192
+ });
186
193
  }
187
194
  const limit = typeof options?.limit === "number" ? options.limit : 1000;
188
195
  return client.threads.getHistory(threadId, { limit });
@@ -364,8 +371,9 @@ export function useStream(options) {
364
371
  .map((m, idx) => m.id ?? idx)
365
372
  .includes(messageId));
366
373
  const firstSeen = history.data[firstSeenIdx];
367
- let branch = firstSeen
368
- ? branchByCheckpoint[firstSeen.checkpoint.checkpoint_id]
374
+ const checkpointId = firstSeen?.checkpoint?.checkpoint_id;
375
+ let branch = firstSeen && checkpointId != null
376
+ ? branchByCheckpoint[checkpointId]
369
377
  : undefined;
370
378
  if (!branch?.branch?.length)
371
379
  branch = undefined;
@@ -430,7 +438,10 @@ export function useStream(options) {
430
438
  }
431
439
  setStreamValues(data);
432
440
  }
433
- if (event === "messages") {
441
+ if (event === "messages" ||
442
+ // if `streamSubgraphs: true`, then we also want
443
+ // to also receive messages from subgraphs
444
+ event.startsWith("messages|")) {
434
445
  const [serialized] = data;
435
446
  const messageId = messageManagerRef.current.add(serialized);
436
447
  if (!messageId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-sdk",
3
- "version": "0.0.93",
3
+ "version": "0.0.95",
4
4
  "description": "Client library for interacting with the LangGraph API",
5
5
  "type": "module",
6
6
  "scripts": {