@langchain/langgraph-sdk 0.0.103 → 0.0.105
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 +14 -0
- package/dist/react/stream.cjs +36 -12
- package/dist/react/stream.d.ts +7 -2
- package/dist/react/stream.js +36 -12
- package/dist/schema.d.ts +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @langchain/langgraph-sdk
|
|
2
2
|
|
|
3
|
+
## 0.0.105
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7054a6a: add context to assistantBase interface
|
|
8
|
+
|
|
9
|
+
## 0.0.104
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- af9ec5a: feat(sdk): add `isThreadLoading` option to `useStream`, handle thread error fetching
|
|
14
|
+
- 8e1ec9e: feat(sdk): add Context API support for useStream
|
|
15
|
+
- f43e48c: fix(sdk): handle subgraph custom events in stream processing of useStream
|
|
16
|
+
|
|
3
17
|
## 0.0.103
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/dist/react/stream.cjs
CHANGED
|
@@ -198,25 +198,38 @@ function fetchHistory(client, threadId, options) {
|
|
|
198
198
|
const limit = typeof options?.limit === "number" ? options.limit : 1000;
|
|
199
199
|
return client.threads.getHistory(threadId, { limit });
|
|
200
200
|
}
|
|
201
|
-
function useThreadHistory(threadId, client, limit, clearCallbackRef, submittingRef) {
|
|
202
|
-
const [history, setHistory] = (0, react_1.useState)(
|
|
201
|
+
function useThreadHistory(threadId, client, limit, clearCallbackRef, submittingRef, onErrorRef) {
|
|
202
|
+
const [history, setHistory] = (0, react_1.useState)(undefined);
|
|
203
|
+
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
204
|
+
const [error, setError] = (0, react_1.useState)(undefined);
|
|
203
205
|
const clientHash = (0, client_js_1.getClientConfigHash)(client);
|
|
204
206
|
const clientRef = (0, react_1.useRef)(client);
|
|
205
207
|
clientRef.current = client;
|
|
206
208
|
const fetcher = (0, react_1.useCallback)((threadId) => {
|
|
207
209
|
if (threadId != null) {
|
|
208
210
|
const client = clientRef.current;
|
|
211
|
+
setIsLoading(true);
|
|
209
212
|
return fetchHistory(client, threadId, {
|
|
210
213
|
limit,
|
|
211
|
-
})
|
|
214
|
+
})
|
|
215
|
+
.then((history) => {
|
|
212
216
|
setHistory(history);
|
|
213
217
|
return history;
|
|
218
|
+
}, (error) => {
|
|
219
|
+
setError(error);
|
|
220
|
+
onErrorRef.current?.(error);
|
|
221
|
+
return Promise.reject(error);
|
|
222
|
+
})
|
|
223
|
+
.finally(() => {
|
|
224
|
+
setIsLoading(false);
|
|
214
225
|
});
|
|
215
226
|
}
|
|
216
|
-
setHistory(
|
|
227
|
+
setHistory(undefined);
|
|
228
|
+
setError(undefined);
|
|
229
|
+
setIsLoading(false);
|
|
217
230
|
clearCallbackRef.current?.();
|
|
218
231
|
return Promise.resolve([]);
|
|
219
|
-
}, [clearCallbackRef, limit]);
|
|
232
|
+
}, [clearCallbackRef, onErrorRef, limit]);
|
|
220
233
|
(0, react_1.useEffect)(() => {
|
|
221
234
|
if (submittingRef.current)
|
|
222
235
|
return;
|
|
@@ -224,6 +237,8 @@ function useThreadHistory(threadId, client, limit, clearCallbackRef, submittingR
|
|
|
224
237
|
}, [fetcher, clientHash, limit, submittingRef, threadId]);
|
|
225
238
|
return {
|
|
226
239
|
data: history,
|
|
240
|
+
isLoading,
|
|
241
|
+
error,
|
|
227
242
|
mutate: (mutateId) => fetcher(mutateId ?? threadId),
|
|
228
243
|
};
|
|
229
244
|
}
|
|
@@ -346,20 +361,22 @@ function useStream(options) {
|
|
|
346
361
|
setStreamValues(null);
|
|
347
362
|
messageManagerRef.current.clear();
|
|
348
363
|
};
|
|
364
|
+
const onErrorRef = (0, react_1.useRef)(undefined);
|
|
365
|
+
onErrorRef.current = options.onError;
|
|
349
366
|
const historyLimit = typeof fetchStateHistory === "object" && fetchStateHistory != null
|
|
350
367
|
? fetchStateHistory.limit ?? true
|
|
351
368
|
: fetchStateHistory ?? true;
|
|
352
|
-
const history = useThreadHistory(threadId, client, historyLimit, clearCallbackRef, submittingRef);
|
|
369
|
+
const history = useThreadHistory(threadId, client, historyLimit, clearCallbackRef, submittingRef, onErrorRef);
|
|
353
370
|
const getMessages = (0, react_1.useMemo)(() => {
|
|
354
371
|
return (value) => Array.isArray(value[messagesKey])
|
|
355
372
|
? value[messagesKey]
|
|
356
373
|
: [];
|
|
357
374
|
}, [messagesKey]);
|
|
358
|
-
const { rootSequence, paths } = getBranchSequence(history.data);
|
|
375
|
+
const { rootSequence, paths } = getBranchSequence(history.data ?? []);
|
|
359
376
|
const { history: flatHistory, branchByCheckpoint } = getBranchView(rootSequence, paths, branch);
|
|
360
377
|
const threadHead = flatHistory.at(-1);
|
|
361
378
|
const historyValues = threadHead?.values ?? options.initialValues ?? {};
|
|
362
|
-
const
|
|
379
|
+
const historyValueError = (() => {
|
|
363
380
|
const error = threadHead?.tasks?.at(-1)?.error;
|
|
364
381
|
if (error == null)
|
|
365
382
|
return undefined;
|
|
@@ -379,10 +396,10 @@ function useStream(options) {
|
|
|
379
396
|
const alreadyShown = new Set();
|
|
380
397
|
return getMessages(historyValues).map((message, idx) => {
|
|
381
398
|
const messageId = message.id ?? idx;
|
|
382
|
-
const firstSeenIdx = findLastIndex(history.data, (state) => getMessages(state.values)
|
|
399
|
+
const firstSeenIdx = findLastIndex(history.data ?? [], (state) => getMessages(state.values)
|
|
383
400
|
.map((m, idx) => m.id ?? idx)
|
|
384
401
|
.includes(messageId));
|
|
385
|
-
const firstSeen = history.data[firstSeenIdx];
|
|
402
|
+
const firstSeen = history.data?.[firstSeenIdx];
|
|
386
403
|
const checkpointId = firstSeen?.checkpoint?.checkpoint_id;
|
|
387
404
|
let branch = firstSeen && checkpointId != null
|
|
388
405
|
? branchByCheckpoint[checkpointId]
|
|
@@ -433,7 +450,10 @@ function useStream(options) {
|
|
|
433
450
|
}
|
|
434
451
|
if (event === "updates")
|
|
435
452
|
options.onUpdateEvent?.(data);
|
|
436
|
-
if (event === "custom"
|
|
453
|
+
if (event === "custom" ||
|
|
454
|
+
// if `streamSubgraphs: true`, then we also want
|
|
455
|
+
// to also receive custom events from subgraphs
|
|
456
|
+
event.startsWith("custom|"))
|
|
437
457
|
options.onCustomEvent?.(data, {
|
|
438
458
|
mutate: getMutateFn("stream", historyValues),
|
|
439
459
|
});
|
|
@@ -553,6 +573,8 @@ function useStream(options) {
|
|
|
553
573
|
onThreadId(thread.thread_id);
|
|
554
574
|
usableThreadId = thread.thread_id;
|
|
555
575
|
}
|
|
576
|
+
if (!usableThreadId)
|
|
577
|
+
throw new Error("Failed to obtain valid thread ID.");
|
|
556
578
|
const streamMode = unique([
|
|
557
579
|
...(submitOptions?.streamMode ?? []),
|
|
558
580
|
...trackStreamModeRef.current,
|
|
@@ -569,6 +591,7 @@ function useStream(options) {
|
|
|
569
591
|
const stream = client.runs.stream(usableThreadId, assistantId, {
|
|
570
592
|
input: values,
|
|
571
593
|
config: submitOptions?.config,
|
|
594
|
+
context: submitOptions?.context,
|
|
572
595
|
command: submitOptions?.command,
|
|
573
596
|
interruptBefore: submitOptions?.interruptBefore,
|
|
574
597
|
interruptAfter: submitOptions?.interruptAfter,
|
|
@@ -631,7 +654,7 @@ function useStream(options) {
|
|
|
631
654
|
void joinStreamRef.current?.(reconnectKey.runId);
|
|
632
655
|
}
|
|
633
656
|
}, [reconnectKey]);
|
|
634
|
-
const error = streamError ??
|
|
657
|
+
const error = streamError ?? historyValueError ?? history.error;
|
|
635
658
|
const values = streamValues ?? historyValues;
|
|
636
659
|
return {
|
|
637
660
|
get values() {
|
|
@@ -648,6 +671,7 @@ function useStream(options) {
|
|
|
648
671
|
branch,
|
|
649
672
|
setBranch,
|
|
650
673
|
history: flatHistory,
|
|
674
|
+
isThreadLoading: history.isLoading && history.data == null,
|
|
651
675
|
get experimental_branchTree() {
|
|
652
676
|
if (historyLimit === false) {
|
|
653
677
|
throw new Error("`experimental_branchTree` is not available when `fetchStateHistory` is set to `false`");
|
package/dist/react/stream.d.ts
CHANGED
|
@@ -203,6 +203,10 @@ export interface UseStream<StateType extends Record<string, unknown> = Record<st
|
|
|
203
203
|
* Whether the stream is currently running.
|
|
204
204
|
*/
|
|
205
205
|
isLoading: boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Whether the thread is currently being loaded.
|
|
208
|
+
*/
|
|
209
|
+
isThreadLoading: boolean;
|
|
206
210
|
/**
|
|
207
211
|
* Stops the stream.
|
|
208
212
|
*/
|
|
@@ -264,8 +268,9 @@ export interface UseStream<StateType extends Record<string, unknown> = Record<st
|
|
|
264
268
|
type ConfigWithConfigurable<ConfigurableType extends Record<string, unknown>> = Config & {
|
|
265
269
|
configurable?: ConfigurableType;
|
|
266
270
|
};
|
|
267
|
-
interface SubmitOptions<StateType extends Record<string, unknown> = Record<string, unknown>,
|
|
268
|
-
config?: ConfigWithConfigurable<
|
|
271
|
+
interface SubmitOptions<StateType extends Record<string, unknown> = Record<string, unknown>, ContextType extends Record<string, unknown> = Record<string, unknown>> {
|
|
272
|
+
config?: ConfigWithConfigurable<ContextType>;
|
|
273
|
+
context?: ContextType;
|
|
269
274
|
checkpoint?: Omit<Checkpoint, "thread_id"> | null;
|
|
270
275
|
command?: Command;
|
|
271
276
|
interruptBefore?: "*" | string[];
|
package/dist/react/stream.js
CHANGED
|
@@ -194,25 +194,38 @@ function fetchHistory(client, threadId, options) {
|
|
|
194
194
|
const limit = typeof options?.limit === "number" ? options.limit : 1000;
|
|
195
195
|
return client.threads.getHistory(threadId, { limit });
|
|
196
196
|
}
|
|
197
|
-
function useThreadHistory(threadId, client, limit, clearCallbackRef, submittingRef) {
|
|
198
|
-
const [history, setHistory] = useState(
|
|
197
|
+
function useThreadHistory(threadId, client, limit, clearCallbackRef, submittingRef, onErrorRef) {
|
|
198
|
+
const [history, setHistory] = useState(undefined);
|
|
199
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
200
|
+
const [error, setError] = useState(undefined);
|
|
199
201
|
const clientHash = getClientConfigHash(client);
|
|
200
202
|
const clientRef = useRef(client);
|
|
201
203
|
clientRef.current = client;
|
|
202
204
|
const fetcher = useCallback((threadId) => {
|
|
203
205
|
if (threadId != null) {
|
|
204
206
|
const client = clientRef.current;
|
|
207
|
+
setIsLoading(true);
|
|
205
208
|
return fetchHistory(client, threadId, {
|
|
206
209
|
limit,
|
|
207
|
-
})
|
|
210
|
+
})
|
|
211
|
+
.then((history) => {
|
|
208
212
|
setHistory(history);
|
|
209
213
|
return history;
|
|
214
|
+
}, (error) => {
|
|
215
|
+
setError(error);
|
|
216
|
+
onErrorRef.current?.(error);
|
|
217
|
+
return Promise.reject(error);
|
|
218
|
+
})
|
|
219
|
+
.finally(() => {
|
|
220
|
+
setIsLoading(false);
|
|
210
221
|
});
|
|
211
222
|
}
|
|
212
|
-
setHistory(
|
|
223
|
+
setHistory(undefined);
|
|
224
|
+
setError(undefined);
|
|
225
|
+
setIsLoading(false);
|
|
213
226
|
clearCallbackRef.current?.();
|
|
214
227
|
return Promise.resolve([]);
|
|
215
|
-
}, [clearCallbackRef, limit]);
|
|
228
|
+
}, [clearCallbackRef, onErrorRef, limit]);
|
|
216
229
|
useEffect(() => {
|
|
217
230
|
if (submittingRef.current)
|
|
218
231
|
return;
|
|
@@ -220,6 +233,8 @@ function useThreadHistory(threadId, client, limit, clearCallbackRef, submittingR
|
|
|
220
233
|
}, [fetcher, clientHash, limit, submittingRef, threadId]);
|
|
221
234
|
return {
|
|
222
235
|
data: history,
|
|
236
|
+
isLoading,
|
|
237
|
+
error,
|
|
223
238
|
mutate: (mutateId) => fetcher(mutateId ?? threadId),
|
|
224
239
|
};
|
|
225
240
|
}
|
|
@@ -342,20 +357,22 @@ export function useStream(options) {
|
|
|
342
357
|
setStreamValues(null);
|
|
343
358
|
messageManagerRef.current.clear();
|
|
344
359
|
};
|
|
360
|
+
const onErrorRef = useRef(undefined);
|
|
361
|
+
onErrorRef.current = options.onError;
|
|
345
362
|
const historyLimit = typeof fetchStateHistory === "object" && fetchStateHistory != null
|
|
346
363
|
? fetchStateHistory.limit ?? true
|
|
347
364
|
: fetchStateHistory ?? true;
|
|
348
|
-
const history = useThreadHistory(threadId, client, historyLimit, clearCallbackRef, submittingRef);
|
|
365
|
+
const history = useThreadHistory(threadId, client, historyLimit, clearCallbackRef, submittingRef, onErrorRef);
|
|
349
366
|
const getMessages = useMemo(() => {
|
|
350
367
|
return (value) => Array.isArray(value[messagesKey])
|
|
351
368
|
? value[messagesKey]
|
|
352
369
|
: [];
|
|
353
370
|
}, [messagesKey]);
|
|
354
|
-
const { rootSequence, paths } = getBranchSequence(history.data);
|
|
371
|
+
const { rootSequence, paths } = getBranchSequence(history.data ?? []);
|
|
355
372
|
const { history: flatHistory, branchByCheckpoint } = getBranchView(rootSequence, paths, branch);
|
|
356
373
|
const threadHead = flatHistory.at(-1);
|
|
357
374
|
const historyValues = threadHead?.values ?? options.initialValues ?? {};
|
|
358
|
-
const
|
|
375
|
+
const historyValueError = (() => {
|
|
359
376
|
const error = threadHead?.tasks?.at(-1)?.error;
|
|
360
377
|
if (error == null)
|
|
361
378
|
return undefined;
|
|
@@ -375,10 +392,10 @@ export function useStream(options) {
|
|
|
375
392
|
const alreadyShown = new Set();
|
|
376
393
|
return getMessages(historyValues).map((message, idx) => {
|
|
377
394
|
const messageId = message.id ?? idx;
|
|
378
|
-
const firstSeenIdx = findLastIndex(history.data, (state) => getMessages(state.values)
|
|
395
|
+
const firstSeenIdx = findLastIndex(history.data ?? [], (state) => getMessages(state.values)
|
|
379
396
|
.map((m, idx) => m.id ?? idx)
|
|
380
397
|
.includes(messageId));
|
|
381
|
-
const firstSeen = history.data[firstSeenIdx];
|
|
398
|
+
const firstSeen = history.data?.[firstSeenIdx];
|
|
382
399
|
const checkpointId = firstSeen?.checkpoint?.checkpoint_id;
|
|
383
400
|
let branch = firstSeen && checkpointId != null
|
|
384
401
|
? branchByCheckpoint[checkpointId]
|
|
@@ -429,7 +446,10 @@ export function useStream(options) {
|
|
|
429
446
|
}
|
|
430
447
|
if (event === "updates")
|
|
431
448
|
options.onUpdateEvent?.(data);
|
|
432
|
-
if (event === "custom"
|
|
449
|
+
if (event === "custom" ||
|
|
450
|
+
// if `streamSubgraphs: true`, then we also want
|
|
451
|
+
// to also receive custom events from subgraphs
|
|
452
|
+
event.startsWith("custom|"))
|
|
433
453
|
options.onCustomEvent?.(data, {
|
|
434
454
|
mutate: getMutateFn("stream", historyValues),
|
|
435
455
|
});
|
|
@@ -549,6 +569,8 @@ export function useStream(options) {
|
|
|
549
569
|
onThreadId(thread.thread_id);
|
|
550
570
|
usableThreadId = thread.thread_id;
|
|
551
571
|
}
|
|
572
|
+
if (!usableThreadId)
|
|
573
|
+
throw new Error("Failed to obtain valid thread ID.");
|
|
552
574
|
const streamMode = unique([
|
|
553
575
|
...(submitOptions?.streamMode ?? []),
|
|
554
576
|
...trackStreamModeRef.current,
|
|
@@ -565,6 +587,7 @@ export function useStream(options) {
|
|
|
565
587
|
const stream = client.runs.stream(usableThreadId, assistantId, {
|
|
566
588
|
input: values,
|
|
567
589
|
config: submitOptions?.config,
|
|
590
|
+
context: submitOptions?.context,
|
|
568
591
|
command: submitOptions?.command,
|
|
569
592
|
interruptBefore: submitOptions?.interruptBefore,
|
|
570
593
|
interruptAfter: submitOptions?.interruptAfter,
|
|
@@ -627,7 +650,7 @@ export function useStream(options) {
|
|
|
627
650
|
void joinStreamRef.current?.(reconnectKey.runId);
|
|
628
651
|
}
|
|
629
652
|
}, [reconnectKey]);
|
|
630
|
-
const error = streamError ??
|
|
653
|
+
const error = streamError ?? historyValueError ?? history.error;
|
|
631
654
|
const values = streamValues ?? historyValues;
|
|
632
655
|
return {
|
|
633
656
|
get values() {
|
|
@@ -644,6 +667,7 @@ export function useStream(options) {
|
|
|
644
667
|
branch,
|
|
645
668
|
setBranch,
|
|
646
669
|
history: flatHistory,
|
|
670
|
+
isThreadLoading: history.isLoading && history.data == null,
|
|
647
671
|
get experimental_branchTree() {
|
|
648
672
|
if (historyLimit === false) {
|
|
649
673
|
throw new Error("`experimental_branchTree` is not available when `fetchStateHistory` is set to `false`");
|
package/dist/schema.d.ts
CHANGED
|
@@ -76,6 +76,8 @@ export interface AssistantBase {
|
|
|
76
76
|
graph_id: string;
|
|
77
77
|
/** The assistant config. */
|
|
78
78
|
config: Config;
|
|
79
|
+
/** The assistant context. */
|
|
80
|
+
context: unknown;
|
|
79
81
|
/** The time the assistant was created. */
|
|
80
82
|
created_at: string;
|
|
81
83
|
/** The assistant metadata. */
|