@ai-sdk/langchain 2.0.87 → 2.0.89
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 +18 -0
- package/README.md +33 -1
- package/dist/index.d.mts +34 -8
- package/dist/index.d.ts +34 -8
- package/dist/index.js +27 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +27 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/adapter.ts +57 -4
- package/src/stream-callbacks.ts +29 -23
- package/src/utils.ts +14 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @ai-sdk/langchain
|
|
2
2
|
|
|
3
|
+
## 2.0.89
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ai@6.0.83
|
|
8
|
+
|
|
9
|
+
## 2.0.88
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 2b29f7a: Add `onFinish`, `onError`, and `onAbort` callbacks to `StreamCallbacks` for `toUIMessageStream`.
|
|
14
|
+
|
|
15
|
+
- `onFinish(state)`: Called on successful completion with final LangGraph state (or `undefined` for other stream types)
|
|
16
|
+
- `onError(error)`: Called when stream encounters an error
|
|
17
|
+
- `onAbort()`: Called when stream is aborted
|
|
18
|
+
|
|
19
|
+
Also adds `parseLangGraphEvent` helper for parsing LangGraph event tuples.
|
|
20
|
+
|
|
3
21
|
## 2.0.87
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -56,6 +56,30 @@ return createUIMessageStreamResponse({
|
|
|
56
56
|
});
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
### Streaming with Callbacks
|
|
60
|
+
|
|
61
|
+
Use callbacks to access the final LangGraph state, handle errors, or detect aborts:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
const langchainStream = await graph.stream(
|
|
65
|
+
{ messages: langchainMessages },
|
|
66
|
+
{ streamMode: ['values', 'messages'] },
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
return createUIMessageStreamResponse({
|
|
70
|
+
stream: toUIMessageStream<MyGraphState>(langchainStream, {
|
|
71
|
+
onFinish: async finalState => {
|
|
72
|
+
if (finalState) {
|
|
73
|
+
await saveConversation(finalState.messages);
|
|
74
|
+
await sendAnalytics(finalState);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
onError: error => console.error('Stream failed:', error),
|
|
78
|
+
onAbort: () => console.log('Client disconnected'),
|
|
79
|
+
}),
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
59
83
|
### Streaming with `streamEvents`
|
|
60
84
|
|
|
61
85
|
You can also use `toUIMessageStream` with `streamEvents()` for more granular event handling:
|
|
@@ -195,13 +219,21 @@ Converts AI SDK `ModelMessage` objects to LangChain `BaseMessage` objects.
|
|
|
195
219
|
|
|
196
220
|
**Returns:** `BaseMessage[]`
|
|
197
221
|
|
|
198
|
-
### `toUIMessageStream(stream)`
|
|
222
|
+
### `toUIMessageStream(stream, callbacks?)`
|
|
199
223
|
|
|
200
224
|
Converts a LangChain/LangGraph stream to an AI SDK `UIMessageStream`.
|
|
201
225
|
|
|
202
226
|
**Parameters:**
|
|
203
227
|
|
|
204
228
|
- `stream`: `AsyncIterable | ReadableStream` - A stream from LangChain `model.stream()`, LangGraph `graph.stream()`, or `streamEvents()`
|
|
229
|
+
- `callbacks?`: `StreamCallbacks<TState>` - Optional lifecycle callbacks:
|
|
230
|
+
- `onStart()` - Called when stream initializes
|
|
231
|
+
- `onToken(token)` - Called for each token
|
|
232
|
+
- `onText(text)` - Called for each text chunk
|
|
233
|
+
- `onFinal(text)` - Called with aggregated text (on success, error, or abort)
|
|
234
|
+
- `onFinish(state)` - Called on success with LangGraph state (or `undefined` for other streams)
|
|
235
|
+
- `onError(error)` - Called when stream errors
|
|
236
|
+
- `onAbort()` - Called when stream is aborted
|
|
205
237
|
|
|
206
238
|
**Returns:** `ReadableStream<UIMessageChunk>`
|
|
207
239
|
|
package/dist/index.d.mts
CHANGED
|
@@ -3,17 +3,26 @@ import { UIMessage, UIMessageChunk, ModelMessage, ChatTransport, ChatRequestOpti
|
|
|
3
3
|
import { RemoteGraph, RemoteGraphParams } from '@langchain/langgraph/remote';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Callback options for stream lifecycle events.
|
|
7
7
|
*/
|
|
8
|
-
interface StreamCallbacks {
|
|
9
|
-
/**
|
|
8
|
+
interface StreamCallbacks<TState = unknown> {
|
|
9
|
+
/** Called once when the stream is initialized. */
|
|
10
10
|
onStart?: () => Promise<void> | void;
|
|
11
|
-
/**
|
|
12
|
-
onFinal?: (completion: string) => Promise<void> | void;
|
|
13
|
-
/** `onToken`: Called for each tokenized message. */
|
|
11
|
+
/** Called for each tokenized message. */
|
|
14
12
|
onToken?: (token: string) => Promise<void> | void;
|
|
15
|
-
/**
|
|
13
|
+
/** Called for each text chunk. */
|
|
16
14
|
onText?: (text: string) => Promise<void> | void;
|
|
15
|
+
/** Called with aggregated text when stream ends (success, error, or abort). */
|
|
16
|
+
onFinal?: (completion: string) => Promise<void> | void;
|
|
17
|
+
/**
|
|
18
|
+
* Called on successful completion. Receives final graph state for LangGraph
|
|
19
|
+
* streams (from last "values" event), undefined for other stream types.
|
|
20
|
+
*/
|
|
21
|
+
onFinish?: (finalState: TState | undefined) => Promise<void> | void;
|
|
22
|
+
/** Called when the stream encounters an error. */
|
|
23
|
+
onError?: (error: Error) => Promise<void> | void;
|
|
24
|
+
/** Called when the stream is aborted. */
|
|
25
|
+
onAbort?: () => Promise<void> | void;
|
|
17
26
|
}
|
|
18
27
|
|
|
19
28
|
/**
|
|
@@ -81,9 +90,26 @@ declare function convertModelMessages(modelMessages: ModelMessage[]): BaseMessag
|
|
|
81
90
|
* return createUIMessageStreamResponse({
|
|
82
91
|
* stream: toUIMessageStream(streamEvents),
|
|
83
92
|
* });
|
|
93
|
+
*
|
|
94
|
+
* // With callbacks for LangGraph state
|
|
95
|
+
* const graphStream = await graph.stream(
|
|
96
|
+
* { messages },
|
|
97
|
+
* { streamMode: ['values', 'messages'] }
|
|
98
|
+
* );
|
|
99
|
+
* return createUIMessageStreamResponse({
|
|
100
|
+
* stream: toUIMessageStream<MyStateType>(graphStream, {
|
|
101
|
+
* onFinish: async (finalState) => {
|
|
102
|
+
* if (finalState) {
|
|
103
|
+
* await saveToDatabase(finalState);
|
|
104
|
+
* }
|
|
105
|
+
* },
|
|
106
|
+
* onError: (error) => console.error('Stream failed:', error),
|
|
107
|
+
* onAbort: () => console.log('Stream aborted'),
|
|
108
|
+
* }),
|
|
109
|
+
* });
|
|
84
110
|
* ```
|
|
85
111
|
*/
|
|
86
|
-
declare function toUIMessageStream(stream: AsyncIterable<AIMessageChunk> | ReadableStream, callbacks?: StreamCallbacks): ReadableStream<UIMessageChunk>;
|
|
112
|
+
declare function toUIMessageStream<TState = unknown>(stream: AsyncIterable<AIMessageChunk> | ReadableStream, callbacks?: StreamCallbacks<TState>): ReadableStream<UIMessageChunk>;
|
|
87
113
|
|
|
88
114
|
/**
|
|
89
115
|
* Options for configuring a LangSmith deployment transport.
|
package/dist/index.d.ts
CHANGED
|
@@ -3,17 +3,26 @@ import { UIMessage, UIMessageChunk, ModelMessage, ChatTransport, ChatRequestOpti
|
|
|
3
3
|
import { RemoteGraph, RemoteGraphParams } from '@langchain/langgraph/remote';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Callback options for stream lifecycle events.
|
|
7
7
|
*/
|
|
8
|
-
interface StreamCallbacks {
|
|
9
|
-
/**
|
|
8
|
+
interface StreamCallbacks<TState = unknown> {
|
|
9
|
+
/** Called once when the stream is initialized. */
|
|
10
10
|
onStart?: () => Promise<void> | void;
|
|
11
|
-
/**
|
|
12
|
-
onFinal?: (completion: string) => Promise<void> | void;
|
|
13
|
-
/** `onToken`: Called for each tokenized message. */
|
|
11
|
+
/** Called for each tokenized message. */
|
|
14
12
|
onToken?: (token: string) => Promise<void> | void;
|
|
15
|
-
/**
|
|
13
|
+
/** Called for each text chunk. */
|
|
16
14
|
onText?: (text: string) => Promise<void> | void;
|
|
15
|
+
/** Called with aggregated text when stream ends (success, error, or abort). */
|
|
16
|
+
onFinal?: (completion: string) => Promise<void> | void;
|
|
17
|
+
/**
|
|
18
|
+
* Called on successful completion. Receives final graph state for LangGraph
|
|
19
|
+
* streams (from last "values" event), undefined for other stream types.
|
|
20
|
+
*/
|
|
21
|
+
onFinish?: (finalState: TState | undefined) => Promise<void> | void;
|
|
22
|
+
/** Called when the stream encounters an error. */
|
|
23
|
+
onError?: (error: Error) => Promise<void> | void;
|
|
24
|
+
/** Called when the stream is aborted. */
|
|
25
|
+
onAbort?: () => Promise<void> | void;
|
|
17
26
|
}
|
|
18
27
|
|
|
19
28
|
/**
|
|
@@ -81,9 +90,26 @@ declare function convertModelMessages(modelMessages: ModelMessage[]): BaseMessag
|
|
|
81
90
|
* return createUIMessageStreamResponse({
|
|
82
91
|
* stream: toUIMessageStream(streamEvents),
|
|
83
92
|
* });
|
|
93
|
+
*
|
|
94
|
+
* // With callbacks for LangGraph state
|
|
95
|
+
* const graphStream = await graph.stream(
|
|
96
|
+
* { messages },
|
|
97
|
+
* { streamMode: ['values', 'messages'] }
|
|
98
|
+
* );
|
|
99
|
+
* return createUIMessageStreamResponse({
|
|
100
|
+
* stream: toUIMessageStream<MyStateType>(graphStream, {
|
|
101
|
+
* onFinish: async (finalState) => {
|
|
102
|
+
* if (finalState) {
|
|
103
|
+
* await saveToDatabase(finalState);
|
|
104
|
+
* }
|
|
105
|
+
* },
|
|
106
|
+
* onError: (error) => console.error('Stream failed:', error),
|
|
107
|
+
* onAbort: () => console.log('Stream aborted'),
|
|
108
|
+
* }),
|
|
109
|
+
* });
|
|
84
110
|
* ```
|
|
85
111
|
*/
|
|
86
|
-
declare function toUIMessageStream(stream: AsyncIterable<AIMessageChunk> | ReadableStream, callbacks?: StreamCallbacks): ReadableStream<UIMessageChunk>;
|
|
112
|
+
declare function toUIMessageStream<TState = unknown>(stream: AsyncIterable<AIMessageChunk> | ReadableStream, callbacks?: StreamCallbacks<TState>): ReadableStream<UIMessageChunk>;
|
|
87
113
|
|
|
88
114
|
/**
|
|
89
115
|
* Options for configuring a LangSmith deployment transport.
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,9 @@ var import_ai = require("ai");
|
|
|
33
33
|
|
|
34
34
|
// src/utils.ts
|
|
35
35
|
var import_messages = require("@langchain/core/messages");
|
|
36
|
+
function parseLangGraphEvent(event) {
|
|
37
|
+
return event.length === 3 ? [event[1], event[2]] : [event[0], event[1]];
|
|
38
|
+
}
|
|
36
39
|
function convertToolResultPart(block) {
|
|
37
40
|
const content = (() => {
|
|
38
41
|
if (block.output.type === "text" || block.output.type === "error-text") {
|
|
@@ -462,7 +465,7 @@ function processLangGraphEvent(event, state, controller) {
|
|
|
462
465
|
toolCallInfoByIndex,
|
|
463
466
|
emittedToolCallsByKey
|
|
464
467
|
} = state;
|
|
465
|
-
const [type, data] = event
|
|
468
|
+
const [type, data] = parseLangGraphEvent(event);
|
|
466
469
|
switch (type) {
|
|
467
470
|
case "custom": {
|
|
468
471
|
let customTypeName = "custom";
|
|
@@ -922,8 +925,15 @@ function processStreamEventsEvent(event, state, controller) {
|
|
|
922
925
|
}
|
|
923
926
|
}
|
|
924
927
|
}
|
|
928
|
+
function isAbortError(error) {
|
|
929
|
+
if (error instanceof Error) {
|
|
930
|
+
return error.name === "AbortError" || error instanceof DOMException && error.name === "AbortError";
|
|
931
|
+
}
|
|
932
|
+
return false;
|
|
933
|
+
}
|
|
925
934
|
function toUIMessageStream(stream, callbacks) {
|
|
926
935
|
const textChunks = [];
|
|
936
|
+
let lastValuesData;
|
|
927
937
|
const modelState = {
|
|
928
938
|
started: false,
|
|
929
939
|
messageId: "langchain-msg-1",
|
|
@@ -979,7 +989,7 @@ function toUIMessageStream(stream, callbacks) {
|
|
|
979
989
|
};
|
|
980
990
|
return new ReadableStream({
|
|
981
991
|
async start(controller) {
|
|
982
|
-
var _a, _b, _c, _d;
|
|
992
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
983
993
|
await ((_a = callbacks == null ? void 0 : callbacks.onStart) == null ? void 0 : _a.call(callbacks));
|
|
984
994
|
const wrappedController = createCallbackController(controller);
|
|
985
995
|
controller.enqueue({ type: "start" });
|
|
@@ -1009,8 +1019,13 @@ function toUIMessageStream(stream, callbacks) {
|
|
|
1009
1019
|
wrappedController
|
|
1010
1020
|
);
|
|
1011
1021
|
} else {
|
|
1022
|
+
const eventArray = value;
|
|
1023
|
+
const [type, data] = parseLangGraphEvent(eventArray);
|
|
1024
|
+
if (type === "values") {
|
|
1025
|
+
lastValuesData = data;
|
|
1026
|
+
}
|
|
1012
1027
|
processLangGraphEvent(
|
|
1013
|
-
|
|
1028
|
+
eventArray,
|
|
1014
1029
|
langGraphState,
|
|
1015
1030
|
wrappedController
|
|
1016
1031
|
);
|
|
@@ -1037,10 +1052,18 @@ function toUIMessageStream(stream, callbacks) {
|
|
|
1037
1052
|
controller.enqueue({ type: "finish" });
|
|
1038
1053
|
}
|
|
1039
1054
|
await ((_d = callbacks == null ? void 0 : callbacks.onFinal) == null ? void 0 : _d.call(callbacks, textChunks.join("")));
|
|
1055
|
+
await ((_e = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _e.call(callbacks, lastValuesData));
|
|
1040
1056
|
} catch (error) {
|
|
1057
|
+
const errorObj = error instanceof Error ? error : new Error(String(error));
|
|
1058
|
+
await ((_f = callbacks == null ? void 0 : callbacks.onFinal) == null ? void 0 : _f.call(callbacks, textChunks.join("")));
|
|
1059
|
+
if (isAbortError(error)) {
|
|
1060
|
+
await ((_g = callbacks == null ? void 0 : callbacks.onAbort) == null ? void 0 : _g.call(callbacks));
|
|
1061
|
+
} else {
|
|
1062
|
+
await ((_h = callbacks == null ? void 0 : callbacks.onError) == null ? void 0 : _h.call(callbacks, errorObj));
|
|
1063
|
+
}
|
|
1041
1064
|
controller.enqueue({
|
|
1042
1065
|
type: "error",
|
|
1043
|
-
errorText:
|
|
1066
|
+
errorText: errorObj.message
|
|
1044
1067
|
});
|
|
1045
1068
|
} finally {
|
|
1046
1069
|
controller.close();
|