@librechat/agents 2.4.21 → 2.4.30
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/dist/cjs/llm/anthropic/index.cjs +1 -1
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/types.cjs +50 -0
- package/dist/cjs/llm/anthropic/types.cjs.map +1 -0
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +227 -21
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +1 -0
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +91 -51
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/esm/llm/anthropic/index.mjs +1 -1
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/anthropic/types.mjs +48 -0
- package/dist/esm/llm/anthropic/types.mjs.map +1 -0
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +228 -22
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs +1 -0
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +91 -51
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/run.mjs.map +1 -1
- package/dist/types/llm/anthropic/index.d.ts +3 -4
- package/dist/types/llm/anthropic/types.d.ts +4 -35
- package/dist/types/llm/anthropic/utils/message_inputs.d.ts +2 -2
- package/dist/types/llm/anthropic/utils/message_outputs.d.ts +1 -3
- package/dist/types/llm/anthropic/utils/output_parsers.d.ts +22 -0
- package/dist/types/llm/openai/index.d.ts +3 -2
- package/dist/types/messages/core.d.ts +1 -1
- package/dist/types/tools/example.d.ts +21 -3
- package/package.json +9 -9
- package/src/llm/anthropic/index.ts +6 -5
- package/src/llm/anthropic/llm.spec.ts +176 -179
- package/src/llm/anthropic/types.ts +64 -39
- package/src/llm/anthropic/utils/message_inputs.ts +275 -37
- package/src/llm/anthropic/utils/message_outputs.ts +4 -21
- package/src/llm/anthropic/utils/output_parsers.ts +114 -0
- package/src/llm/openai/index.ts +7 -6
- package/src/messages/core.ts +197 -96
- package/src/run.ts +1 -1
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
1
|
import Anthropic from '@anthropic-ai/sdk';
|
|
3
|
-
import type { Tool as AnthropicTool } from '@anthropic-ai/sdk/resources';
|
|
4
2
|
import { BindToolsInput } from '@langchain/core/language_models/chat_models';
|
|
5
3
|
|
|
6
4
|
export type AnthropicToolResponse = {
|
|
@@ -11,9 +9,10 @@ export type AnthropicToolResponse = {
|
|
|
11
9
|
input: Record<string, any>;
|
|
12
10
|
};
|
|
13
11
|
|
|
12
|
+
export type AnthropicStreamUsage = Anthropic.Usage;
|
|
14
13
|
export type AnthropicMessageParam = Anthropic.MessageParam;
|
|
15
|
-
export type AnthropicMessageDeltaEvent= Anthropic.MessageDeltaEvent;
|
|
16
|
-
export type AnthropicMessageStartEvent= Anthropic.MessageStartEvent;
|
|
14
|
+
export type AnthropicMessageDeltaEvent = Anthropic.MessageDeltaEvent;
|
|
15
|
+
export type AnthropicMessageStartEvent = Anthropic.MessageStartEvent;
|
|
17
16
|
export type AnthropicMessageResponse =
|
|
18
17
|
| Anthropic.ContentBlock
|
|
19
18
|
| AnthropicToolResponse;
|
|
@@ -21,6 +20,7 @@ export type AnthropicMessageCreateParams =
|
|
|
21
20
|
Anthropic.MessageCreateParamsNonStreaming;
|
|
22
21
|
export type AnthropicStreamingMessageCreateParams =
|
|
23
22
|
Anthropic.MessageCreateParamsStreaming;
|
|
23
|
+
export type AnthropicThinkingConfigParam = Anthropic.ThinkingConfigParam;
|
|
24
24
|
export type AnthropicMessageStreamEvent = Anthropic.MessageStreamEvent;
|
|
25
25
|
export type AnthropicRequestOptions = Anthropic.RequestOptions;
|
|
26
26
|
export type AnthropicToolChoice =
|
|
@@ -32,7 +32,7 @@ export type AnthropicToolChoice =
|
|
|
32
32
|
| 'auto'
|
|
33
33
|
| 'none'
|
|
34
34
|
| string;
|
|
35
|
-
export type ChatAnthropicToolType =
|
|
35
|
+
export type ChatAnthropicToolType = Anthropic.Messages.Tool | BindToolsInput;
|
|
36
36
|
export type AnthropicTextBlockParam = Anthropic.Messages.TextBlockParam;
|
|
37
37
|
export type AnthropicImageBlockParam = Anthropic.Messages.ImageBlockParam;
|
|
38
38
|
export type AnthropicToolUseBlockParam = Anthropic.Messages.ToolUseBlockParam;
|
|
@@ -41,39 +41,64 @@ export type AnthropicToolResultBlockParam =
|
|
|
41
41
|
export type AnthropicDocumentBlockParam = Anthropic.Messages.DocumentBlockParam;
|
|
42
42
|
export type AnthropicThinkingBlockParam = Anthropic.Messages.ThinkingBlockParam;
|
|
43
43
|
export type AnthropicRedactedThinkingBlockParam =
|
|
44
|
-
|
|
44
|
+
Anthropic.Messages.RedactedThinkingBlockParam;
|
|
45
|
+
|
|
46
|
+
export function isAnthropicImageBlockParam(
|
|
47
|
+
block: unknown
|
|
48
|
+
): block is AnthropicImageBlockParam {
|
|
49
|
+
if (block == null) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if (typeof block !== 'object') {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (!('type' in block) || block.type !== 'image') {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!('source' in block) || typeof block.source !== 'object') {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (block.source == null) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!('type' in block.source)) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (block.source.type === 'base64') {
|
|
72
|
+
if (!('media_type' in block.source)) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (typeof block.source.media_type !== 'string') {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!('data' in block.source)) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (typeof block.source.data !== 'string') {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (block.source.type === 'url') {
|
|
92
|
+
if (!('url' in block.source)) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (typeof block.source.url !== 'string') {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
45
99
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
* @see https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching#pricing
|
|
49
|
-
*/
|
|
50
|
-
export interface AnthropicStreamUsage {
|
|
51
|
-
/**
|
|
52
|
-
* The number of input tokens used in the request
|
|
53
|
-
*/
|
|
54
|
-
input_tokens: number;
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
55
102
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
*/
|
|
59
|
-
cache_creation_input_tokens?: number;
|
|
60
|
-
/**
|
|
61
|
-
* The number of cache input tokens used (read operations)
|
|
62
|
-
*/
|
|
63
|
-
cache_read_input_tokens?: number;
|
|
64
|
-
/**
|
|
65
|
-
* The number of output tokens generated in the response
|
|
66
|
-
*/
|
|
67
|
-
output_tokens: number;
|
|
68
|
-
/**
|
|
69
|
-
* The total number of tokens generated in the response
|
|
70
|
-
*/
|
|
71
|
-
total_tokens: number;
|
|
72
|
-
/**
|
|
73
|
-
* Details about input token usage
|
|
74
|
-
*/
|
|
75
|
-
input_token_details?: {
|
|
76
|
-
cache_creation: number;
|
|
77
|
-
cache_read: number;
|
|
78
|
-
};
|
|
79
|
-
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
@@ -1,47 +1,80 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
1
2
|
/* eslint-disable no-console */
|
|
2
3
|
/**
|
|
3
4
|
* This util file contains functions for converting LangChain messages to Anthropic messages.
|
|
4
5
|
*/
|
|
5
6
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
ToolMessage,
|
|
9
|
-
isAIMessage,
|
|
7
|
+
type BaseMessage,
|
|
8
|
+
type SystemMessage,
|
|
10
9
|
HumanMessage,
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
type AIMessage,
|
|
11
|
+
type ToolMessage,
|
|
12
|
+
type MessageContent,
|
|
13
|
+
isAIMessage,
|
|
14
|
+
type StandardContentBlockConverter,
|
|
15
|
+
type StandardTextBlock,
|
|
16
|
+
type StandardImageBlock,
|
|
17
|
+
type StandardFileBlock,
|
|
18
|
+
MessageContentComplex,
|
|
19
|
+
isDataContentBlock,
|
|
20
|
+
convertToProviderContentBlock,
|
|
21
|
+
parseBase64DataUrl,
|
|
13
22
|
} from '@langchain/core/messages';
|
|
14
23
|
import { ToolCall } from '@langchain/core/messages/tool';
|
|
15
24
|
import type {
|
|
16
|
-
AnthropicToolResponse,
|
|
17
|
-
AnthropicMessageParam,
|
|
18
|
-
AnthropicTextBlockParam,
|
|
19
25
|
AnthropicImageBlockParam,
|
|
20
|
-
AnthropicToolUseBlockParam,
|
|
21
26
|
AnthropicMessageCreateParams,
|
|
27
|
+
AnthropicTextBlockParam,
|
|
28
|
+
AnthropicToolResponse,
|
|
22
29
|
AnthropicToolResultBlockParam,
|
|
30
|
+
AnthropicToolUseBlockParam,
|
|
23
31
|
AnthropicDocumentBlockParam,
|
|
24
32
|
AnthropicThinkingBlockParam,
|
|
25
33
|
AnthropicRedactedThinkingBlockParam,
|
|
26
34
|
} from '@/llm/anthropic/types';
|
|
35
|
+
import { isAnthropicImageBlockParam } from '@/llm/anthropic/types';
|
|
36
|
+
|
|
37
|
+
function _formatImage(imageUrl: string) {
|
|
38
|
+
const parsed = parseBase64DataUrl({ dataUrl: imageUrl });
|
|
39
|
+
if (parsed) {
|
|
40
|
+
return {
|
|
41
|
+
type: 'base64',
|
|
42
|
+
media_type: parsed.mime_type,
|
|
43
|
+
data: parsed.data,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
let parsedUrl: URL;
|
|
27
47
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (match === null) {
|
|
48
|
+
try {
|
|
49
|
+
parsedUrl = new URL(imageUrl);
|
|
50
|
+
} catch {
|
|
32
51
|
throw new Error(
|
|
33
52
|
[
|
|
34
|
-
|
|
53
|
+
`Malformed image URL: ${JSON.stringify(
|
|
54
|
+
imageUrl
|
|
55
|
+
)}. Content blocks of type 'image_url' must be a valid http, https, or base64-encoded data URL.`,
|
|
35
56
|
'Example: data:image/png;base64,/9j/4AAQSk...',
|
|
57
|
+
'Example: https://example.com/image.jpg',
|
|
36
58
|
].join('\n\n')
|
|
37
59
|
);
|
|
38
60
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
|
|
62
|
+
if (parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:') {
|
|
63
|
+
return {
|
|
64
|
+
type: 'url',
|
|
65
|
+
url: imageUrl,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
throw new Error(
|
|
70
|
+
[
|
|
71
|
+
`Invalid image URL protocol: ${JSON.stringify(
|
|
72
|
+
parsedUrl.protocol
|
|
73
|
+
)}. Anthropic only supports images as http, https, or base64-encoded data URLs on 'image_url' content blocks.`,
|
|
74
|
+
'Example: data:image/png;base64,/9j/4AAQSk...',
|
|
75
|
+
'Example: https://example.com/image.jpg',
|
|
76
|
+
].join('\n\n')
|
|
77
|
+
);
|
|
45
78
|
}
|
|
46
79
|
|
|
47
80
|
function _ensureMessageContents(
|
|
@@ -52,16 +85,15 @@ function _ensureMessageContents(
|
|
|
52
85
|
for (const message of messages) {
|
|
53
86
|
if (message._getType() === 'tool') {
|
|
54
87
|
if (typeof message.content === 'string') {
|
|
55
|
-
const previousMessage = updatedMsgs[updatedMsgs.length - 1]
|
|
88
|
+
const previousMessage = updatedMsgs[updatedMsgs.length - 1];
|
|
56
89
|
if (
|
|
57
|
-
previousMessage &&
|
|
58
90
|
previousMessage._getType() === 'human' &&
|
|
59
91
|
Array.isArray(previousMessage.content) &&
|
|
60
92
|
'type' in previousMessage.content[0] &&
|
|
61
93
|
previousMessage.content[0].type === 'tool_result'
|
|
62
94
|
) {
|
|
63
95
|
// If the previous message was a tool result, we merge this tool message into it.
|
|
64
|
-
previousMessage.content.push({
|
|
96
|
+
(previousMessage.content as MessageContentComplex[]).push({
|
|
65
97
|
type: 'tool_result',
|
|
66
98
|
content: message.content,
|
|
67
99
|
tool_use_id: (message as ToolMessage).tool_call_id,
|
|
@@ -114,8 +146,203 @@ export function _convertLangChainToolCallToAnthropic(
|
|
|
114
146
|
};
|
|
115
147
|
}
|
|
116
148
|
|
|
117
|
-
|
|
118
|
-
|
|
149
|
+
const standardContentBlockConverter: StandardContentBlockConverter<{
|
|
150
|
+
text: AnthropicTextBlockParam;
|
|
151
|
+
image: AnthropicImageBlockParam;
|
|
152
|
+
file: AnthropicDocumentBlockParam;
|
|
153
|
+
}> = {
|
|
154
|
+
providerName: 'anthropic',
|
|
155
|
+
|
|
156
|
+
fromStandardTextBlock(block: StandardTextBlock): AnthropicTextBlockParam {
|
|
157
|
+
return {
|
|
158
|
+
type: 'text',
|
|
159
|
+
text: block.text,
|
|
160
|
+
...('citations' in (block.metadata ?? {})
|
|
161
|
+
? { citations: block.metadata!.citations }
|
|
162
|
+
: {}),
|
|
163
|
+
...('cache_control' in (block.metadata ?? {})
|
|
164
|
+
? { cache_control: block.metadata!.cache_control }
|
|
165
|
+
: {}),
|
|
166
|
+
} as AnthropicTextBlockParam;
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
fromStandardImageBlock(block: StandardImageBlock): AnthropicImageBlockParam {
|
|
170
|
+
if (block.source_type === 'url') {
|
|
171
|
+
const data = parseBase64DataUrl({
|
|
172
|
+
dataUrl: block.url,
|
|
173
|
+
asTypedArray: false,
|
|
174
|
+
});
|
|
175
|
+
if (data) {
|
|
176
|
+
return {
|
|
177
|
+
type: 'image',
|
|
178
|
+
source: {
|
|
179
|
+
type: 'base64',
|
|
180
|
+
data: data.data,
|
|
181
|
+
media_type: data.mime_type,
|
|
182
|
+
},
|
|
183
|
+
...('cache_control' in (block.metadata ?? {})
|
|
184
|
+
? { cache_control: block.metadata!.cache_control }
|
|
185
|
+
: {}),
|
|
186
|
+
} as AnthropicImageBlockParam;
|
|
187
|
+
} else {
|
|
188
|
+
return {
|
|
189
|
+
type: 'image',
|
|
190
|
+
source: {
|
|
191
|
+
type: 'url',
|
|
192
|
+
url: block.url,
|
|
193
|
+
media_type: block.mime_type ?? '',
|
|
194
|
+
},
|
|
195
|
+
...('cache_control' in (block.metadata ?? {})
|
|
196
|
+
? { cache_control: block.metadata!.cache_control }
|
|
197
|
+
: {}),
|
|
198
|
+
} as AnthropicImageBlockParam;
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
if (block.source_type === 'base64') {
|
|
202
|
+
return {
|
|
203
|
+
type: 'image',
|
|
204
|
+
source: {
|
|
205
|
+
type: 'base64',
|
|
206
|
+
data: block.data,
|
|
207
|
+
media_type: block.mime_type ?? '',
|
|
208
|
+
},
|
|
209
|
+
...('cache_control' in (block.metadata ?? {})
|
|
210
|
+
? { cache_control: block.metadata!.cache_control }
|
|
211
|
+
: {}),
|
|
212
|
+
} as AnthropicImageBlockParam;
|
|
213
|
+
} else {
|
|
214
|
+
throw new Error(`Unsupported image source type: ${block.source_type}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
fromStandardFileBlock(block: StandardFileBlock): AnthropicDocumentBlockParam {
|
|
220
|
+
const mime_type = (block.mime_type ?? '').split(';')[0];
|
|
221
|
+
|
|
222
|
+
if (block.source_type === 'url') {
|
|
223
|
+
if (mime_type === 'application/pdf' || mime_type === '') {
|
|
224
|
+
return {
|
|
225
|
+
type: 'document',
|
|
226
|
+
source: {
|
|
227
|
+
type: 'url',
|
|
228
|
+
url: block.url,
|
|
229
|
+
media_type: block.mime_type ?? '',
|
|
230
|
+
},
|
|
231
|
+
...('cache_control' in (block.metadata ?? {})
|
|
232
|
+
? { cache_control: block.metadata!.cache_control }
|
|
233
|
+
: {}),
|
|
234
|
+
...('citations' in (block.metadata ?? {})
|
|
235
|
+
? { citations: block.metadata!.citations }
|
|
236
|
+
: {}),
|
|
237
|
+
...('context' in (block.metadata ?? {})
|
|
238
|
+
? { context: block.metadata!.context }
|
|
239
|
+
: {}),
|
|
240
|
+
...('title' in (block.metadata ?? {})
|
|
241
|
+
? { title: block.metadata!.title }
|
|
242
|
+
: {}),
|
|
243
|
+
} as AnthropicDocumentBlockParam;
|
|
244
|
+
}
|
|
245
|
+
throw new Error(
|
|
246
|
+
`Unsupported file mime type for file url source: ${block.mime_type}`
|
|
247
|
+
);
|
|
248
|
+
} else if (block.source_type === 'text') {
|
|
249
|
+
if (mime_type === 'text/plain' || mime_type === '') {
|
|
250
|
+
return {
|
|
251
|
+
type: 'document',
|
|
252
|
+
source: {
|
|
253
|
+
type: 'text',
|
|
254
|
+
data: block.text,
|
|
255
|
+
media_type: block.mime_type ?? '',
|
|
256
|
+
},
|
|
257
|
+
...('cache_control' in (block.metadata ?? {})
|
|
258
|
+
? { cache_control: block.metadata!.cache_control }
|
|
259
|
+
: {}),
|
|
260
|
+
...('citations' in (block.metadata ?? {})
|
|
261
|
+
? { citations: block.metadata!.citations }
|
|
262
|
+
: {}),
|
|
263
|
+
...('context' in (block.metadata ?? {})
|
|
264
|
+
? { context: block.metadata!.context }
|
|
265
|
+
: {}),
|
|
266
|
+
...('title' in (block.metadata ?? {})
|
|
267
|
+
? { title: block.metadata!.title }
|
|
268
|
+
: {}),
|
|
269
|
+
} as AnthropicDocumentBlockParam;
|
|
270
|
+
} else {
|
|
271
|
+
throw new Error(
|
|
272
|
+
`Unsupported file mime type for file text source: ${block.mime_type}`
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
} else if (block.source_type === 'base64') {
|
|
276
|
+
if (mime_type === 'application/pdf' || mime_type === '') {
|
|
277
|
+
return {
|
|
278
|
+
type: 'document',
|
|
279
|
+
source: {
|
|
280
|
+
type: 'base64',
|
|
281
|
+
data: block.data,
|
|
282
|
+
media_type: 'application/pdf',
|
|
283
|
+
},
|
|
284
|
+
...('cache_control' in (block.metadata ?? {})
|
|
285
|
+
? { cache_control: block.metadata!.cache_control }
|
|
286
|
+
: {}),
|
|
287
|
+
...('citations' in (block.metadata ?? {})
|
|
288
|
+
? { citations: block.metadata!.citations }
|
|
289
|
+
: {}),
|
|
290
|
+
...('context' in (block.metadata ?? {})
|
|
291
|
+
? { context: block.metadata!.context }
|
|
292
|
+
: {}),
|
|
293
|
+
...('title' in (block.metadata ?? {})
|
|
294
|
+
? { title: block.metadata!.title }
|
|
295
|
+
: {}),
|
|
296
|
+
} as AnthropicDocumentBlockParam;
|
|
297
|
+
} else if (
|
|
298
|
+
['image/jpeg', 'image/png', 'image/gif', 'image/webp'].includes(
|
|
299
|
+
mime_type
|
|
300
|
+
)
|
|
301
|
+
) {
|
|
302
|
+
return {
|
|
303
|
+
type: 'document',
|
|
304
|
+
source: {
|
|
305
|
+
type: 'content',
|
|
306
|
+
content: [
|
|
307
|
+
{
|
|
308
|
+
type: 'image',
|
|
309
|
+
source: {
|
|
310
|
+
type: 'base64',
|
|
311
|
+
data: block.data,
|
|
312
|
+
media_type: mime_type as
|
|
313
|
+
| 'image/jpeg'
|
|
314
|
+
| 'image/png'
|
|
315
|
+
| 'image/gif'
|
|
316
|
+
| 'image/webp',
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
],
|
|
320
|
+
},
|
|
321
|
+
...('cache_control' in (block.metadata ?? {})
|
|
322
|
+
? { cache_control: block.metadata!.cache_control }
|
|
323
|
+
: {}),
|
|
324
|
+
...('citations' in (block.metadata ?? {})
|
|
325
|
+
? { citations: block.metadata!.citations }
|
|
326
|
+
: {}),
|
|
327
|
+
...('context' in (block.metadata ?? {})
|
|
328
|
+
? { context: block.metadata!.context }
|
|
329
|
+
: {}),
|
|
330
|
+
...('title' in (block.metadata ?? {})
|
|
331
|
+
? { title: block.metadata!.title }
|
|
332
|
+
: {}),
|
|
333
|
+
} as AnthropicDocumentBlockParam;
|
|
334
|
+
} else {
|
|
335
|
+
throw new Error(
|
|
336
|
+
`Unsupported file mime type for file base64 source: ${block.mime_type}`
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
} else {
|
|
340
|
+
throw new Error(`Unsupported file source type: ${block.source_type}`);
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
function _formatContent(content: MessageContent) {
|
|
119
346
|
const toolTypes = ['tool_use', 'tool_result', 'input_json_delta'];
|
|
120
347
|
const textTypes = ['text', 'text_delta'];
|
|
121
348
|
|
|
@@ -123,6 +350,13 @@ function _formatContent(content: MessageContent): string | Record<string, any>[]
|
|
|
123
350
|
return content;
|
|
124
351
|
} else {
|
|
125
352
|
const contentBlocks = content.map((contentPart) => {
|
|
353
|
+
if (isDataContentBlock(contentPart)) {
|
|
354
|
+
return convertToProviderContentBlock(
|
|
355
|
+
contentPart,
|
|
356
|
+
standardContentBlockConverter
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
126
360
|
const cacheControl =
|
|
127
361
|
'cache_control' in contentPart ? contentPart.cache_control : undefined;
|
|
128
362
|
|
|
@@ -138,6 +372,8 @@ function _formatContent(content: MessageContent): string | Record<string, any>[]
|
|
|
138
372
|
source,
|
|
139
373
|
...(cacheControl ? { cache_control: cacheControl } : {}),
|
|
140
374
|
};
|
|
375
|
+
} else if (isAnthropicImageBlockParam(contentPart)) {
|
|
376
|
+
return contentPart;
|
|
141
377
|
} else if (contentPart.type === 'document') {
|
|
142
378
|
// PDF
|
|
143
379
|
return {
|
|
@@ -160,7 +396,7 @@ function _formatContent(content: MessageContent): string | Record<string, any>[]
|
|
|
160
396
|
};
|
|
161
397
|
return block;
|
|
162
398
|
} else if (
|
|
163
|
-
textTypes.find((t) => t === contentPart.type)
|
|
399
|
+
textTypes.find((t) => t === contentPart.type) &&
|
|
164
400
|
'text' in contentPart
|
|
165
401
|
) {
|
|
166
402
|
// Assuming contentPart is of type MessageContentText here
|
|
@@ -169,7 +405,7 @@ function _formatContent(content: MessageContent): string | Record<string, any>[]
|
|
|
169
405
|
text: contentPart.text,
|
|
170
406
|
...(cacheControl ? { cache_control: cacheControl } : {}),
|
|
171
407
|
};
|
|
172
|
-
} else if (toolTypes.find((t) => t === contentPart.type)
|
|
408
|
+
} else if (toolTypes.find((t) => t === contentPart.type)) {
|
|
173
409
|
const contentPartCopy = { ...contentPart };
|
|
174
410
|
if ('index' in contentPartCopy) {
|
|
175
411
|
// Anthropic does not support passing the index field here, so we remove it.
|
|
@@ -184,10 +420,12 @@ function _formatContent(content: MessageContent): string | Record<string, any>[]
|
|
|
184
420
|
|
|
185
421
|
if ('input' in contentPartCopy) {
|
|
186
422
|
// Anthropic tool use inputs should be valid objects, when applicable.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
423
|
+
if (typeof contentPartCopy.input === 'string') {
|
|
424
|
+
try {
|
|
425
|
+
contentPartCopy.input = JSON.parse(contentPartCopy.input);
|
|
426
|
+
} catch {
|
|
427
|
+
contentPartCopy.input = {};
|
|
428
|
+
}
|
|
191
429
|
}
|
|
192
430
|
}
|
|
193
431
|
|
|
@@ -282,14 +520,14 @@ export function _convertMessagesToAnthropicPayload(
|
|
|
282
520
|
}
|
|
283
521
|
});
|
|
284
522
|
return {
|
|
285
|
-
messages: mergeMessages(formattedMessages
|
|
523
|
+
messages: mergeMessages(formattedMessages),
|
|
286
524
|
system,
|
|
287
525
|
} as AnthropicMessageCreateParams;
|
|
288
526
|
}
|
|
289
527
|
|
|
290
|
-
function mergeMessages(messages
|
|
528
|
+
function mergeMessages(messages: AnthropicMessageCreateParams['messages']) {
|
|
291
529
|
if (!messages || messages.length <= 1) {
|
|
292
|
-
return messages
|
|
530
|
+
return messages;
|
|
293
531
|
}
|
|
294
532
|
|
|
295
533
|
const result: AnthropicMessageCreateParams['messages'] = [];
|
|
@@ -327,7 +565,7 @@ function mergeMessages(messages?: AnthropicMessageCreateParams['messages']): Ant
|
|
|
327
565
|
return content;
|
|
328
566
|
};
|
|
329
567
|
|
|
330
|
-
const isToolResultMessage = (msg: (typeof messages)[0])
|
|
568
|
+
const isToolResultMessage = (msg: (typeof messages)[0]) => {
|
|
331
569
|
if (msg.role !== 'user') return false;
|
|
332
570
|
|
|
333
571
|
if (typeof msg.content === 'string') {
|
|
@@ -363,4 +601,4 @@ function mergeMessages(messages?: AnthropicMessageCreateParams['messages']): Ant
|
|
|
363
601
|
|
|
364
602
|
result.push(currentMessage);
|
|
365
603
|
return result;
|
|
366
|
-
}
|
|
604
|
+
}
|
|
@@ -4,29 +4,13 @@
|
|
|
4
4
|
import Anthropic from '@anthropic-ai/sdk';
|
|
5
5
|
import {
|
|
6
6
|
AIMessage,
|
|
7
|
-
UsageMetadata,
|
|
8
7
|
AIMessageChunk,
|
|
8
|
+
UsageMetadata,
|
|
9
9
|
} from '@langchain/core/messages';
|
|
10
10
|
import type { ToolCallChunk } from '@langchain/core/messages/tool';
|
|
11
|
-
import { ToolCall } from '@langchain/core/messages/tool';
|
|
12
11
|
import { ChatGeneration } from '@langchain/core/outputs';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
-
export function extractToolCalls(content: Record<string, any>[]): ToolCall[] {
|
|
17
|
-
const toolCalls: ToolCall[] = [];
|
|
18
|
-
for (const block of content) {
|
|
19
|
-
if (block.type === 'tool_use') {
|
|
20
|
-
toolCalls.push({
|
|
21
|
-
name: block.name,
|
|
22
|
-
args: block.input,
|
|
23
|
-
id: block.id,
|
|
24
|
-
type: 'tool_call',
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return toolCalls;
|
|
29
|
-
}
|
|
12
|
+
import { extractToolCalls } from './output_parsers';
|
|
13
|
+
import { AnthropicMessageResponse } from '../types';
|
|
30
14
|
|
|
31
15
|
export function _makeMessageChunkFromAnthropicEvent(
|
|
32
16
|
data: Anthropic.Messages.RawMessageStreamEvent,
|
|
@@ -231,7 +215,6 @@ export function _makeMessageChunkFromAnthropicEvent(
|
|
|
231
215
|
}),
|
|
232
216
|
};
|
|
233
217
|
}
|
|
234
|
-
|
|
235
218
|
return null;
|
|
236
219
|
}
|
|
237
220
|
|
|
@@ -284,4 +267,4 @@ export function anthropicResponseToChatMessages(
|
|
|
284
267
|
];
|
|
285
268
|
return generations;
|
|
286
269
|
}
|
|
287
|
-
}
|
|
270
|
+
}
|