@ai-sdk/langchain 3.0.0-beta.18 → 3.0.0-beta.180
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 +1194 -0
- package/README.md +5 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +391 -120
- package/dist/index.js.map +1 -1
- package/package.json +15 -15
- package/src/adapter.ts +74 -17
- package/src/transport.ts +9 -9
- package/src/types.ts +28 -12
- package/src/utils.ts +498 -94
- package/dist/index.d.mts +0 -159
- package/dist/index.mjs +0 -1087
- package/dist/index.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/langchain",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.180",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"license": "Apache-2.0",
|
|
5
6
|
"sideEffects": false,
|
|
6
7
|
"main": "./dist/index.js",
|
|
7
|
-
"module": "./dist/index.mjs",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"files": [
|
|
10
10
|
"dist/**/*",
|
|
@@ -20,20 +20,20 @@
|
|
|
20
20
|
"./package.json": "./package.json",
|
|
21
21
|
".": {
|
|
22
22
|
"types": "./dist/index.d.ts",
|
|
23
|
-
"import": "./dist/index.
|
|
24
|
-
"
|
|
23
|
+
"import": "./dist/index.js",
|
|
24
|
+
"default": "./dist/index.js"
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"ai": "7.0.0-beta.
|
|
28
|
+
"ai": "7.0.0-beta.180"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@langchain/core": "^1.1.
|
|
32
|
-
"@langchain/langgraph": "^1.0
|
|
33
|
-
"@types/node": "
|
|
34
|
-
"tsup": "^8",
|
|
31
|
+
"@langchain/core": "^1.1.46",
|
|
32
|
+
"@langchain/langgraph": "^1.3.0",
|
|
33
|
+
"@types/node": "22.19.19",
|
|
34
|
+
"tsup": "^8.5.1",
|
|
35
35
|
"typescript": "5.8.3",
|
|
36
|
-
"@ai-sdk/provider-utils": "5.0.0-beta.
|
|
36
|
+
"@ai-sdk/provider-utils": "5.0.0-beta.49",
|
|
37
37
|
"@vercel/ai-tsconfig": "0.0.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
@@ -46,15 +46,17 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"engines": {
|
|
49
|
-
"node": ">=
|
|
49
|
+
"node": ">=22"
|
|
50
50
|
},
|
|
51
51
|
"publishConfig": {
|
|
52
|
-
"access": "public"
|
|
52
|
+
"access": "public",
|
|
53
|
+
"provenance": true
|
|
53
54
|
},
|
|
54
55
|
"homepage": "https://ai-sdk.dev/docs",
|
|
55
56
|
"repository": {
|
|
56
57
|
"type": "git",
|
|
57
|
-
"url": "
|
|
58
|
+
"url": "https://github.com/vercel/ai",
|
|
59
|
+
"directory": "packages/langchain"
|
|
58
60
|
},
|
|
59
61
|
"bugs": {
|
|
60
62
|
"url": "https://github.com/vercel/ai/issues"
|
|
@@ -66,9 +68,7 @@
|
|
|
66
68
|
"build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
|
|
67
69
|
"build:watch": "pnpm clean && tsup --watch",
|
|
68
70
|
"clean": "del-cli dist *.tsbuildinfo",
|
|
69
|
-
"lint": "eslint \"./**/*.ts*\"",
|
|
70
71
|
"type-check": "tsc --build",
|
|
71
|
-
"prettier-check": "prettier --check \"./**/*.ts*\"",
|
|
72
72
|
"test": "pnpm test:node && pnpm test:edge",
|
|
73
73
|
"test:update": "pnpm test:node -u",
|
|
74
74
|
"test:watch": "vitest --config vitest.node.config.js",
|
package/src/adapter.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SystemMessage,
|
|
3
|
-
BaseMessage,
|
|
4
|
-
AIMessageChunk,
|
|
3
|
+
type BaseMessage,
|
|
4
|
+
type AIMessageChunk,
|
|
5
5
|
} from '@langchain/core/messages';
|
|
6
6
|
import {
|
|
7
|
+
convertToModelMessages,
|
|
7
8
|
type UIMessage,
|
|
8
9
|
type UIMessageChunk,
|
|
9
|
-
convertToModelMessages,
|
|
10
10
|
type ModelMessage,
|
|
11
11
|
} from 'ai';
|
|
12
12
|
import {
|
|
@@ -18,9 +18,11 @@ import {
|
|
|
18
18
|
parseLangGraphEvent,
|
|
19
19
|
isToolResultPart,
|
|
20
20
|
extractReasoningFromContentBlocks,
|
|
21
|
+
extractCitationsFromContentBlocks,
|
|
22
|
+
emitSourceChunks,
|
|
21
23
|
} from './utils';
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
+
import type { LangGraphEventState } from './types';
|
|
25
|
+
import type { StreamCallbacks } from './stream-callbacks';
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
28
|
* Converts AI SDK UIMessages to LangChain BaseMessage objects.
|
|
@@ -132,6 +134,7 @@ function processStreamEventsEvent(
|
|
|
132
134
|
textStarted: boolean;
|
|
133
135
|
textMessageId: string | null;
|
|
134
136
|
reasoningMessageId: string | null;
|
|
137
|
+
emittedSourceIds: Set<string>;
|
|
135
138
|
},
|
|
136
139
|
controller: ReadableStreamDefaultController<UIMessageChunk>,
|
|
137
140
|
): void {
|
|
@@ -150,8 +153,41 @@ function processStreamEventsEvent(
|
|
|
150
153
|
switch (event.event) {
|
|
151
154
|
case 'on_chat_model_start': {
|
|
152
155
|
/**
|
|
153
|
-
*
|
|
154
|
-
*
|
|
156
|
+
* End the previous model turn's reasoning stream before a new LLM invocation.
|
|
157
|
+
* Without this, reasoning-delta chunks from the next turn could attach to the
|
|
158
|
+
* wrong reasoning part in the UI message stream.
|
|
159
|
+
*/
|
|
160
|
+
if (state.reasoningStarted) {
|
|
161
|
+
controller.enqueue({
|
|
162
|
+
type: 'reasoning-end',
|
|
163
|
+
id:
|
|
164
|
+
state.reasoningMessageId != null
|
|
165
|
+
? state.reasoningMessageId
|
|
166
|
+
: state.messageId,
|
|
167
|
+
});
|
|
168
|
+
state.reasoningStarted = false;
|
|
169
|
+
state.reasoningMessageId = null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* End the previous model turn's text stream before a new LLM invocation.
|
|
174
|
+
* The streamEvents adapter otherwise leaves `textStarted` true, so all later
|
|
175
|
+
* text-delta chunks append to the first text part — tools still grow the parts
|
|
176
|
+
* array, which breaks chronological order in the assistant message.
|
|
177
|
+
*/
|
|
178
|
+
if (state.textStarted) {
|
|
179
|
+
controller.enqueue({
|
|
180
|
+
type: 'text-end',
|
|
181
|
+
id:
|
|
182
|
+
state.textMessageId != null ? state.textMessageId : state.messageId,
|
|
183
|
+
});
|
|
184
|
+
state.textStarted = false;
|
|
185
|
+
state.textMessageId = null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Handle model start — capture message metadata if available.
|
|
190
|
+
* `run_id` is on the event in streamEvents v2; fall back to `data` for compatibility.
|
|
155
191
|
*/
|
|
156
192
|
const runId = event.run_id || (event.data.run_id as string | undefined);
|
|
157
193
|
if (runId) {
|
|
@@ -241,6 +277,16 @@ function processStreamEventsEvent(
|
|
|
241
277
|
id: state.textMessageId ?? state.messageId,
|
|
242
278
|
});
|
|
243
279
|
}
|
|
280
|
+
|
|
281
|
+
const citations = extractCitationsFromContentBlocks(chunk);
|
|
282
|
+
if (citations.length > 0) {
|
|
283
|
+
emitSourceChunks(
|
|
284
|
+
citations,
|
|
285
|
+
state.messageId,
|
|
286
|
+
state.emittedSourceIds,
|
|
287
|
+
controller,
|
|
288
|
+
);
|
|
289
|
+
}
|
|
244
290
|
}
|
|
245
291
|
break;
|
|
246
292
|
}
|
|
@@ -378,27 +424,24 @@ export function toUIMessageStream<TState = unknown>(
|
|
|
378
424
|
textMessageId: null as string | null,
|
|
379
425
|
/** Track the ID used for reasoning-start to ensure reasoning-end uses the same ID */
|
|
380
426
|
reasoningMessageId: null as string | null,
|
|
427
|
+
emittedSourceIds: new Set<string>(),
|
|
381
428
|
};
|
|
382
429
|
|
|
383
430
|
/**
|
|
384
431
|
* State for LangGraph stream handling
|
|
385
432
|
*/
|
|
386
433
|
const langGraphState: LangGraphEventState = {
|
|
387
|
-
messageSeen:
|
|
388
|
-
|
|
389
|
-
{ text?: boolean; reasoning?: boolean; tool?: Record<string, boolean> }
|
|
390
|
-
>,
|
|
391
|
-
messageConcat: {} as Record<string, AIMessageChunk>,
|
|
434
|
+
messageSeen: new Map(),
|
|
435
|
+
messageConcat: new Map(),
|
|
392
436
|
emittedToolCalls: new Set<string>(),
|
|
437
|
+
emittedToolInputs: new Set<string>(),
|
|
393
438
|
emittedImages: new Set<string>(),
|
|
394
439
|
emittedReasoningIds: new Set<string>(),
|
|
395
|
-
messageReasoningIds:
|
|
396
|
-
toolCallInfoByIndex:
|
|
397
|
-
string,
|
|
398
|
-
Record<number, { id: string; name: string }>
|
|
399
|
-
>,
|
|
440
|
+
messageReasoningIds: new Map(),
|
|
441
|
+
toolCallInfoByIndex: new Map(),
|
|
400
442
|
currentStep: null as number | null,
|
|
401
443
|
emittedToolCallsByKey: new Map<string, string>(),
|
|
444
|
+
emittedSourceIds: new Set<string>(),
|
|
402
445
|
};
|
|
403
446
|
|
|
404
447
|
/**
|
|
@@ -535,6 +578,20 @@ export function toUIMessageStream<TState = unknown>(
|
|
|
535
578
|
}
|
|
536
579
|
controller.enqueue({ type: 'finish' });
|
|
537
580
|
} else if (streamType === 'langgraph') {
|
|
581
|
+
/**
|
|
582
|
+
* Close any open text/reasoning parts before finishing.
|
|
583
|
+
* This handles streams without values events (e.g. streamMode: 'messages')
|
|
584
|
+
* where the values handler never ran to emit *-end events.
|
|
585
|
+
*/
|
|
586
|
+
for (const [id, seen] of langGraphState.messageSeen) {
|
|
587
|
+
if (seen.text) {
|
|
588
|
+
controller.enqueue({ type: 'text-end', id });
|
|
589
|
+
}
|
|
590
|
+
if (seen.reasoning) {
|
|
591
|
+
controller.enqueue({ type: 'reasoning-end', id });
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
538
595
|
/**
|
|
539
596
|
* Emit finish-step if a step was started
|
|
540
597
|
*/
|
package/src/transport.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { AIMessageChunk } from '@langchain/core/messages';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import type { AIMessageChunk } from '@langchain/core/messages';
|
|
2
|
+
import type {
|
|
3
|
+
UIMessage,
|
|
4
|
+
UIMessageChunk,
|
|
5
|
+
ChatTransport,
|
|
6
|
+
ChatRequestOptions,
|
|
7
7
|
} from 'ai';
|
|
8
8
|
import {
|
|
9
9
|
RemoteGraph,
|
|
@@ -45,9 +45,9 @@ export type LangSmithDeploymentTransportOptions = Omit<
|
|
|
45
45
|
* });
|
|
46
46
|
* ```
|
|
47
47
|
*/
|
|
48
|
-
export class LangSmithDeploymentTransport<
|
|
49
|
-
|
|
50
|
-
{
|
|
48
|
+
export class LangSmithDeploymentTransport<
|
|
49
|
+
UI_MESSAGE extends UIMessage,
|
|
50
|
+
> implements ChatTransport<UI_MESSAGE> {
|
|
51
51
|
protected graph: RemoteGraph;
|
|
52
52
|
|
|
53
53
|
constructor(options: LangSmithDeploymentTransportOptions) {
|
package/src/types.ts
CHANGED
|
@@ -1,33 +1,49 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AIMessageChunk } from '@langchain/core/messages';
|
|
2
|
+
|
|
3
|
+
export interface LangGraphMessageSeen {
|
|
4
|
+
text?: boolean;
|
|
5
|
+
reasoning?: boolean;
|
|
6
|
+
tool?: Set<string>;
|
|
7
|
+
}
|
|
2
8
|
|
|
3
9
|
/**
|
|
4
10
|
* State for LangGraph event processing
|
|
5
11
|
*/
|
|
6
12
|
export interface LangGraphEventState {
|
|
7
13
|
/** Tracks which message IDs have been seen */
|
|
8
|
-
messageSeen:
|
|
9
|
-
string,
|
|
10
|
-
{ text?: boolean; reasoning?: boolean; tool?: Record<string, boolean> }
|
|
11
|
-
>;
|
|
14
|
+
messageSeen: Map<string, LangGraphMessageSeen>;
|
|
12
15
|
/** Accumulates message chunks for later reference */
|
|
13
|
-
messageConcat:
|
|
14
|
-
/**
|
|
16
|
+
messageConcat: Map<string, AIMessageChunk>;
|
|
17
|
+
/** Tracks which tool call IDs have emitted tool-input-start */
|
|
15
18
|
emittedToolCalls: Set<string>;
|
|
19
|
+
/** Tracks which tool call IDs have emitted complete tool inputs */
|
|
20
|
+
emittedToolInputs: Set<string>;
|
|
16
21
|
/** Maps image IDs to their message IDs (for chunks that don't include the ID) */
|
|
17
22
|
emittedImages: Set<string>;
|
|
18
23
|
/** Maps reasoning block IDs to their message IDs (for chunks that don't include the ID) */
|
|
19
24
|
emittedReasoningIds: Set<string>;
|
|
20
25
|
/** Maps message IDs to their reasoning block IDs (for chunks that don't include the ID) */
|
|
21
|
-
messageReasoningIds:
|
|
26
|
+
messageReasoningIds: Map<string, string>;
|
|
22
27
|
/** Maps message ID + tool call index to tool call info (for streaming chunks without ID) */
|
|
23
|
-
toolCallInfoByIndex:
|
|
24
|
-
string,
|
|
25
|
-
Record<number, { id: string; name: string }>
|
|
26
|
-
>;
|
|
28
|
+
toolCallInfoByIndex: Map<string, Map<number, { id: string; name: string }>>;
|
|
27
29
|
/** Tracks the current LangGraph step for start-step/finish-step events */
|
|
28
30
|
currentStep: number | null;
|
|
29
31
|
/** Maps tool call key (name:argsJson) to tool call ID for HITL interrupt handling */
|
|
30
32
|
emittedToolCallsByKey: Map<string, string>;
|
|
33
|
+
/** Tracks source IDs already emitted to avoid duplicates across messages/values events */
|
|
34
|
+
emittedSourceIds: Set<string>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A LangChain citation projected to the fields the AI SDK source parts can carry.
|
|
39
|
+
*/
|
|
40
|
+
export interface NormalizedCitation {
|
|
41
|
+
url?: string;
|
|
42
|
+
title?: string;
|
|
43
|
+
source?: string;
|
|
44
|
+
citedText?: string;
|
|
45
|
+
startIndex?: number;
|
|
46
|
+
endIndex?: number;
|
|
31
47
|
}
|
|
32
48
|
|
|
33
49
|
/**
|