@langchain/anthropic 0.3.19 → 0.3.21

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.
@@ -81,9 +81,8 @@ function extractToken(chunk) {
81
81
  *
82
82
  * ```typescript
83
83
  * // When calling `.bind`, call options should be passed via the first argument
84
- * const llmWithArgsBound = llm.bind({
84
+ * const llmWithArgsBound = llm.bindTools([...]).withConfig({
85
85
  * stop: ["\n"],
86
- * tools: [...],
87
86
  * });
88
87
  *
89
88
  * // When calling `.bindTools`, call options should be passed via the second argument
@@ -651,7 +650,7 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
651
650
  });
652
651
  }
653
652
  bindTools(tools, kwargs) {
654
- return this.bind({
653
+ return this.withConfig({
655
654
  tools: this.formatStructuredToolToAnthropic(tools),
656
655
  ...kwargs,
657
656
  });
@@ -925,7 +924,7 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
925
924
  "generated. Consider disabling `thinking` or adjust your prompt to ensure " +
926
925
  "the tool is called.";
927
926
  console.warn(thinkingAdmonition);
928
- llm = this.bind({
927
+ llm = this.withConfig({
929
928
  tools,
930
929
  });
931
930
  const raiseIfNoToolCalls = (message) => {
@@ -937,7 +936,7 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
937
936
  llm = llm.pipe(raiseIfNoToolCalls);
938
937
  }
939
938
  else {
940
- llm = this.bind({
939
+ llm = this.withConfig({
941
940
  tools,
942
941
  tool_choice: {
943
942
  type: "tool",
@@ -117,9 +117,8 @@ type Kwargs = Record<string, any>;
117
117
  *
118
118
  * ```typescript
119
119
  * // When calling `.bind`, call options should be passed via the first argument
120
- * const llmWithArgsBound = llm.bind({
120
+ * const llmWithArgsBound = llm.bindTools([...]).withConfig({
121
121
  * stop: ["\n"],
122
- * tools: [...],
123
122
  * });
124
123
  *
125
124
  * // When calling `.bindTools`, call options should be passed via the second argument
@@ -78,9 +78,8 @@ function extractToken(chunk) {
78
78
  *
79
79
  * ```typescript
80
80
  * // When calling `.bind`, call options should be passed via the first argument
81
- * const llmWithArgsBound = llm.bind({
81
+ * const llmWithArgsBound = llm.bindTools([...]).withConfig({
82
82
  * stop: ["\n"],
83
- * tools: [...],
84
83
  * });
85
84
  *
86
85
  * // When calling `.bindTools`, call options should be passed via the second argument
@@ -648,7 +647,7 @@ export class ChatAnthropicMessages extends BaseChatModel {
648
647
  });
649
648
  }
650
649
  bindTools(tools, kwargs) {
651
- return this.bind({
650
+ return this.withConfig({
652
651
  tools: this.formatStructuredToolToAnthropic(tools),
653
652
  ...kwargs,
654
653
  });
@@ -922,7 +921,7 @@ export class ChatAnthropicMessages extends BaseChatModel {
922
921
  "generated. Consider disabling `thinking` or adjust your prompt to ensure " +
923
922
  "the tool is called.";
924
923
  console.warn(thinkingAdmonition);
925
- llm = this.bind({
924
+ llm = this.withConfig({
926
925
  tools,
927
926
  });
928
927
  const raiseIfNoToolCalls = (message) => {
@@ -934,7 +933,7 @@ export class ChatAnthropicMessages extends BaseChatModel {
934
933
  llm = llm.pipe(raiseIfNoToolCalls);
935
934
  }
936
935
  else {
937
- llm = this.bind({
936
+ llm = this.withConfig({
938
937
  tools,
939
938
  tool_choice: {
940
939
  type: "tool",
@@ -270,7 +270,7 @@ class ChatAnthropicTools extends chat_models_1.BaseChatModel {
270
270
  keyName: functionName,
271
271
  });
272
272
  }
273
- const llm = this.bind({
273
+ const llm = this.withConfig({
274
274
  tools,
275
275
  tool_choice: force
276
276
  ? {
@@ -267,7 +267,7 @@ export class ChatAnthropicTools extends BaseChatModel {
267
267
  keyName: functionName,
268
268
  });
269
269
  }
270
- const llm = this.bind({
270
+ const llm = this.withConfig({
271
271
  tools,
272
272
  tool_choice: force
273
273
  ? {
package/dist/types.cjs CHANGED
@@ -1,2 +1,49 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isAnthropicImageBlockParam = void 0;
4
+ function isAnthropicImageBlockParam(block) {
5
+ if (block == null) {
6
+ return false;
7
+ }
8
+ if (typeof block !== "object") {
9
+ return false;
10
+ }
11
+ if (!("type" in block) || block.type !== "image") {
12
+ return false;
13
+ }
14
+ if (!("source" in block) || typeof block.source !== "object") {
15
+ return false;
16
+ }
17
+ if (block.source == null) {
18
+ return false;
19
+ }
20
+ if (!("type" in block.source)) {
21
+ return false;
22
+ }
23
+ if (block.source.type === "base64") {
24
+ if (!("media_type" in block.source)) {
25
+ return false;
26
+ }
27
+ if (typeof block.source.media_type !== "string") {
28
+ return false;
29
+ }
30
+ if (!("data" in block.source)) {
31
+ return false;
32
+ }
33
+ if (typeof block.source.data !== "string") {
34
+ return false;
35
+ }
36
+ return true;
37
+ }
38
+ if (block.source.type === "url") {
39
+ if (!("url" in block.source)) {
40
+ return false;
41
+ }
42
+ if (typeof block.source.url !== "string") {
43
+ return false;
44
+ }
45
+ return true;
46
+ }
47
+ return false;
48
+ }
49
+ exports.isAnthropicImageBlockParam = isAnthropicImageBlockParam;
package/dist/types.d.ts CHANGED
@@ -25,3 +25,4 @@ export type AnthropicToolResultBlockParam = Anthropic.Messages.ToolResultBlockPa
25
25
  export type AnthropicDocumentBlockParam = Anthropic.Messages.DocumentBlockParam;
26
26
  export type AnthropicThinkingBlockParam = Anthropic.Messages.ThinkingBlockParam;
27
27
  export type AnthropicRedactedThinkingBlockParam = Anthropic.Messages.RedactedThinkingBlockParam;
28
+ export declare function isAnthropicImageBlockParam(block: unknown): block is AnthropicImageBlockParam;
package/dist/types.js CHANGED
@@ -1 +1,45 @@
1
- export {};
1
+ export function isAnthropicImageBlockParam(block) {
2
+ if (block == null) {
3
+ return false;
4
+ }
5
+ if (typeof block !== "object") {
6
+ return false;
7
+ }
8
+ if (!("type" in block) || block.type !== "image") {
9
+ return false;
10
+ }
11
+ if (!("source" in block) || typeof block.source !== "object") {
12
+ return false;
13
+ }
14
+ if (block.source == null) {
15
+ return false;
16
+ }
17
+ if (!("type" in block.source)) {
18
+ return false;
19
+ }
20
+ if (block.source.type === "base64") {
21
+ if (!("media_type" in block.source)) {
22
+ return false;
23
+ }
24
+ if (typeof block.source.media_type !== "string") {
25
+ return false;
26
+ }
27
+ if (!("data" in block.source)) {
28
+ return false;
29
+ }
30
+ if (typeof block.source.data !== "string") {
31
+ return false;
32
+ }
33
+ return true;
34
+ }
35
+ if (block.source.type === "url") {
36
+ if (!("url" in block.source)) {
37
+ return false;
38
+ }
39
+ if (typeof block.source.url !== "string") {
40
+ return false;
41
+ }
42
+ return true;
43
+ }
44
+ return false;
45
+ }
@@ -5,21 +5,38 @@ exports._convertMessagesToAnthropicPayload = exports._convertLangChainToolCallTo
5
5
  * This util file contains functions for converting LangChain messages to Anthropic messages.
6
6
  */
7
7
  const messages_1 = require("@langchain/core/messages");
8
+ const types_js_1 = require("../types.cjs");
8
9
  function _formatImage(imageUrl) {
9
- const regex = /^data:(image\/.+);base64,(.+)$/;
10
- const match = imageUrl.match(regex);
11
- if (match === null) {
10
+ const parsed = (0, messages_1.parseBase64DataUrl)({ dataUrl: imageUrl });
11
+ if (parsed) {
12
+ return {
13
+ type: "base64",
14
+ media_type: parsed.mime_type,
15
+ data: parsed.data,
16
+ };
17
+ }
18
+ let parsedUrl;
19
+ try {
20
+ parsedUrl = new URL(imageUrl);
21
+ }
22
+ catch {
12
23
  throw new Error([
13
- "Anthropic only supports base64-encoded images currently.",
24
+ `Malformed image URL: ${JSON.stringify(imageUrl)}. Content blocks of type 'image_url' must be a valid http, https, or base64-encoded data URL.`,
14
25
  "Example: data:image/png;base64,/9j/4AAQSk...",
26
+ "Example: https://example.com/image.jpg",
15
27
  ].join("\n\n"));
16
28
  }
17
- return {
18
- type: "base64",
19
- media_type: match[1] ?? "",
20
- data: match[2] ?? "",
21
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
- };
29
+ if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") {
30
+ return {
31
+ type: "url",
32
+ url: imageUrl,
33
+ };
34
+ }
35
+ throw new Error([
36
+ `Invalid image URL protocol: ${JSON.stringify(parsedUrl.protocol)}. Anthropic only supports images as http, https, or base64-encoded data URLs on 'image_url' content blocks.`,
37
+ "Example: data:image/png;base64,/9j/4AAQSk...",
38
+ "Example: https://example.com/image.jpg",
39
+ ].join("\n\n"));
23
40
  }
24
41
  function _ensureMessageContents(messages) {
25
42
  // Merge runs of human/tool messages into single human messages with content blocks.
@@ -57,7 +74,10 @@ function _ensureMessageContents(messages) {
57
74
  content: [
58
75
  {
59
76
  type: "tool_result",
60
- content: _formatContent(message.content),
77
+ // rare case: message.content could be undefined
78
+ ...(message.content != null
79
+ ? { content: _formatContent(message.content) }
80
+ : {}),
61
81
  tool_use_id: message.tool_call_id,
62
82
  },
63
83
  ],
@@ -82,6 +102,188 @@ function _convertLangChainToolCallToAnthropic(toolCall) {
82
102
  };
83
103
  }
84
104
  exports._convertLangChainToolCallToAnthropic = _convertLangChainToolCallToAnthropic;
105
+ const standardContentBlockConverter = {
106
+ providerName: "anthropic",
107
+ fromStandardTextBlock(block) {
108
+ return {
109
+ type: "text",
110
+ text: block.text,
111
+ ...("citations" in (block.metadata ?? {})
112
+ ? { citations: block.metadata.citations }
113
+ : {}),
114
+ ...("cache_control" in (block.metadata ?? {})
115
+ ? { cache_control: block.metadata.cache_control }
116
+ : {}),
117
+ };
118
+ },
119
+ fromStandardImageBlock(block) {
120
+ if (block.source_type === "url") {
121
+ const data = (0, messages_1.parseBase64DataUrl)({
122
+ dataUrl: block.url,
123
+ asTypedArray: false,
124
+ });
125
+ if (data) {
126
+ return {
127
+ type: "image",
128
+ source: {
129
+ type: "base64",
130
+ data: data.data,
131
+ media_type: data.mime_type,
132
+ },
133
+ ...("cache_control" in (block.metadata ?? {})
134
+ ? { cache_control: block.metadata.cache_control }
135
+ : {}),
136
+ };
137
+ }
138
+ else {
139
+ return {
140
+ type: "image",
141
+ source: {
142
+ type: "url",
143
+ url: block.url,
144
+ media_type: block.mime_type ?? "",
145
+ },
146
+ ...("cache_control" in (block.metadata ?? {})
147
+ ? { cache_control: block.metadata.cache_control }
148
+ : {}),
149
+ };
150
+ }
151
+ }
152
+ else {
153
+ if (block.source_type === "base64") {
154
+ return {
155
+ type: "image",
156
+ source: {
157
+ type: "base64",
158
+ data: block.data,
159
+ media_type: block.mime_type ?? "",
160
+ },
161
+ ...("cache_control" in (block.metadata ?? {})
162
+ ? { cache_control: block.metadata.cache_control }
163
+ : {}),
164
+ };
165
+ }
166
+ else {
167
+ throw new Error(`Unsupported image source type: ${block.source_type}`);
168
+ }
169
+ }
170
+ },
171
+ fromStandardFileBlock(block) {
172
+ const mime_type = (block.mime_type ?? "").split(";")[0];
173
+ if (block.source_type === "url") {
174
+ if (mime_type === "application/pdf" || mime_type === "") {
175
+ return {
176
+ type: "document",
177
+ source: {
178
+ type: "url",
179
+ url: block.url,
180
+ media_type: block.mime_type ?? "",
181
+ },
182
+ ...("cache_control" in (block.metadata ?? {})
183
+ ? { cache_control: block.metadata.cache_control }
184
+ : {}),
185
+ ...("citations" in (block.metadata ?? {})
186
+ ? { citations: block.metadata.citations }
187
+ : {}),
188
+ ...("context" in (block.metadata ?? {})
189
+ ? { context: block.metadata.context }
190
+ : {}),
191
+ ...("title" in (block.metadata ?? {})
192
+ ? { title: block.metadata.title }
193
+ : {}),
194
+ };
195
+ }
196
+ throw new Error(`Unsupported file mime type for file url source: ${block.mime_type}`);
197
+ }
198
+ else if (block.source_type === "text") {
199
+ if (mime_type === "text/plain" || mime_type === "") {
200
+ return {
201
+ type: "document",
202
+ source: {
203
+ type: "text",
204
+ data: block.text,
205
+ media_type: block.mime_type ?? "",
206
+ },
207
+ ...("cache_control" in (block.metadata ?? {})
208
+ ? { cache_control: block.metadata.cache_control }
209
+ : {}),
210
+ ...("citations" in (block.metadata ?? {})
211
+ ? { citations: block.metadata.citations }
212
+ : {}),
213
+ ...("context" in (block.metadata ?? {})
214
+ ? { context: block.metadata.context }
215
+ : {}),
216
+ ...("title" in (block.metadata ?? {})
217
+ ? { title: block.metadata.title }
218
+ : {}),
219
+ };
220
+ }
221
+ else {
222
+ throw new Error(`Unsupported file mime type for file text source: ${block.mime_type}`);
223
+ }
224
+ }
225
+ else if (block.source_type === "base64") {
226
+ if (mime_type === "application/pdf" || mime_type === "") {
227
+ return {
228
+ type: "document",
229
+ source: {
230
+ type: "base64",
231
+ data: block.data,
232
+ media_type: "application/pdf",
233
+ },
234
+ ...("cache_control" in (block.metadata ?? {})
235
+ ? { cache_control: block.metadata.cache_control }
236
+ : {}),
237
+ ...("citations" in (block.metadata ?? {})
238
+ ? { citations: block.metadata.citations }
239
+ : {}),
240
+ ...("context" in (block.metadata ?? {})
241
+ ? { context: block.metadata.context }
242
+ : {}),
243
+ ...("title" in (block.metadata ?? {})
244
+ ? { title: block.metadata.title }
245
+ : {}),
246
+ };
247
+ }
248
+ else if (["image/jpeg", "image/png", "image/gif", "image/webp"].includes(mime_type)) {
249
+ return {
250
+ type: "document",
251
+ source: {
252
+ type: "content",
253
+ content: [
254
+ {
255
+ type: "image",
256
+ source: {
257
+ type: "base64",
258
+ data: block.data,
259
+ media_type: mime_type,
260
+ },
261
+ },
262
+ ],
263
+ },
264
+ ...("cache_control" in (block.metadata ?? {})
265
+ ? { cache_control: block.metadata.cache_control }
266
+ : {}),
267
+ ...("citations" in (block.metadata ?? {})
268
+ ? { citations: block.metadata.citations }
269
+ : {}),
270
+ ...("context" in (block.metadata ?? {})
271
+ ? { context: block.metadata.context }
272
+ : {}),
273
+ ...("title" in (block.metadata ?? {})
274
+ ? { title: block.metadata.title }
275
+ : {}),
276
+ };
277
+ }
278
+ else {
279
+ throw new Error(`Unsupported file mime type for file base64 source: ${block.mime_type}`);
280
+ }
281
+ }
282
+ else {
283
+ throw new Error(`Unsupported file source type: ${block.source_type}`);
284
+ }
285
+ },
286
+ };
85
287
  function _formatContent(content) {
86
288
  const toolTypes = ["tool_use", "tool_result", "input_json_delta"];
87
289
  const textTypes = ["text", "text_delta"];
@@ -90,6 +292,9 @@ function _formatContent(content) {
90
292
  }
91
293
  else {
92
294
  const contentBlocks = content.map((contentPart) => {
295
+ if ((0, messages_1.isDataContentBlock)(contentPart)) {
296
+ return (0, messages_1.convertToProviderContentBlock)(contentPart, standardContentBlockConverter);
297
+ }
93
298
  const cacheControl = "cache_control" in contentPart ? contentPart.cache_control : undefined;
94
299
  if (contentPart.type === "image_url") {
95
300
  let source;
@@ -105,6 +310,9 @@ function _formatContent(content) {
105
310
  ...(cacheControl ? { cache_control: cacheControl } : {}),
106
311
  };
107
312
  }
313
+ else if ((0, types_js_1.isAnthropicImageBlockParam)(contentPart)) {
314
+ return contentPart;
315
+ }
108
316
  else if (contentPart.type === "document") {
109
317
  // PDF
110
318
  return {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * This util file contains functions for converting LangChain messages to Anthropic messages.
3
3
  */
4
- import { BaseMessage } from "@langchain/core/messages";
4
+ import { type BaseMessage } from "@langchain/core/messages";
5
5
  import { ToolCall } from "@langchain/core/messages/tool";
6
6
  import { AnthropicMessageCreateParams, AnthropicToolResponse } from "../types.js";
7
7
  export declare function _convertLangChainToolCallToAnthropic(toolCall: ToolCall): AnthropicToolResponse;
@@ -1,22 +1,39 @@
1
1
  /**
2
2
  * This util file contains functions for converting LangChain messages to Anthropic messages.
3
3
  */
4
- import { HumanMessage, isAIMessage, } from "@langchain/core/messages";
4
+ import { HumanMessage, isAIMessage, isDataContentBlock, convertToProviderContentBlock, parseBase64DataUrl, } from "@langchain/core/messages";
5
+ import { isAnthropicImageBlockParam, } from "../types.js";
5
6
  function _formatImage(imageUrl) {
6
- const regex = /^data:(image\/.+);base64,(.+)$/;
7
- const match = imageUrl.match(regex);
8
- if (match === null) {
7
+ const parsed = parseBase64DataUrl({ dataUrl: imageUrl });
8
+ if (parsed) {
9
+ return {
10
+ type: "base64",
11
+ media_type: parsed.mime_type,
12
+ data: parsed.data,
13
+ };
14
+ }
15
+ let parsedUrl;
16
+ try {
17
+ parsedUrl = new URL(imageUrl);
18
+ }
19
+ catch {
9
20
  throw new Error([
10
- "Anthropic only supports base64-encoded images currently.",
21
+ `Malformed image URL: ${JSON.stringify(imageUrl)}. Content blocks of type 'image_url' must be a valid http, https, or base64-encoded data URL.`,
11
22
  "Example: data:image/png;base64,/9j/4AAQSk...",
23
+ "Example: https://example.com/image.jpg",
12
24
  ].join("\n\n"));
13
25
  }
14
- return {
15
- type: "base64",
16
- media_type: match[1] ?? "",
17
- data: match[2] ?? "",
18
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
- };
26
+ if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") {
27
+ return {
28
+ type: "url",
29
+ url: imageUrl,
30
+ };
31
+ }
32
+ throw new Error([
33
+ `Invalid image URL protocol: ${JSON.stringify(parsedUrl.protocol)}. Anthropic only supports images as http, https, or base64-encoded data URLs on 'image_url' content blocks.`,
34
+ "Example: data:image/png;base64,/9j/4AAQSk...",
35
+ "Example: https://example.com/image.jpg",
36
+ ].join("\n\n"));
20
37
  }
21
38
  function _ensureMessageContents(messages) {
22
39
  // Merge runs of human/tool messages into single human messages with content blocks.
@@ -54,7 +71,10 @@ function _ensureMessageContents(messages) {
54
71
  content: [
55
72
  {
56
73
  type: "tool_result",
57
- content: _formatContent(message.content),
74
+ // rare case: message.content could be undefined
75
+ ...(message.content != null
76
+ ? { content: _formatContent(message.content) }
77
+ : {}),
58
78
  tool_use_id: message.tool_call_id,
59
79
  },
60
80
  ],
@@ -78,6 +98,188 @@ export function _convertLangChainToolCallToAnthropic(toolCall) {
78
98
  input: toolCall.args,
79
99
  };
80
100
  }
101
+ const standardContentBlockConverter = {
102
+ providerName: "anthropic",
103
+ fromStandardTextBlock(block) {
104
+ return {
105
+ type: "text",
106
+ text: block.text,
107
+ ...("citations" in (block.metadata ?? {})
108
+ ? { citations: block.metadata.citations }
109
+ : {}),
110
+ ...("cache_control" in (block.metadata ?? {})
111
+ ? { cache_control: block.metadata.cache_control }
112
+ : {}),
113
+ };
114
+ },
115
+ fromStandardImageBlock(block) {
116
+ if (block.source_type === "url") {
117
+ const data = parseBase64DataUrl({
118
+ dataUrl: block.url,
119
+ asTypedArray: false,
120
+ });
121
+ if (data) {
122
+ return {
123
+ type: "image",
124
+ source: {
125
+ type: "base64",
126
+ data: data.data,
127
+ media_type: data.mime_type,
128
+ },
129
+ ...("cache_control" in (block.metadata ?? {})
130
+ ? { cache_control: block.metadata.cache_control }
131
+ : {}),
132
+ };
133
+ }
134
+ else {
135
+ return {
136
+ type: "image",
137
+ source: {
138
+ type: "url",
139
+ url: block.url,
140
+ media_type: block.mime_type ?? "",
141
+ },
142
+ ...("cache_control" in (block.metadata ?? {})
143
+ ? { cache_control: block.metadata.cache_control }
144
+ : {}),
145
+ };
146
+ }
147
+ }
148
+ else {
149
+ if (block.source_type === "base64") {
150
+ return {
151
+ type: "image",
152
+ source: {
153
+ type: "base64",
154
+ data: block.data,
155
+ media_type: block.mime_type ?? "",
156
+ },
157
+ ...("cache_control" in (block.metadata ?? {})
158
+ ? { cache_control: block.metadata.cache_control }
159
+ : {}),
160
+ };
161
+ }
162
+ else {
163
+ throw new Error(`Unsupported image source type: ${block.source_type}`);
164
+ }
165
+ }
166
+ },
167
+ fromStandardFileBlock(block) {
168
+ const mime_type = (block.mime_type ?? "").split(";")[0];
169
+ if (block.source_type === "url") {
170
+ if (mime_type === "application/pdf" || mime_type === "") {
171
+ return {
172
+ type: "document",
173
+ source: {
174
+ type: "url",
175
+ url: block.url,
176
+ media_type: block.mime_type ?? "",
177
+ },
178
+ ...("cache_control" in (block.metadata ?? {})
179
+ ? { cache_control: block.metadata.cache_control }
180
+ : {}),
181
+ ...("citations" in (block.metadata ?? {})
182
+ ? { citations: block.metadata.citations }
183
+ : {}),
184
+ ...("context" in (block.metadata ?? {})
185
+ ? { context: block.metadata.context }
186
+ : {}),
187
+ ...("title" in (block.metadata ?? {})
188
+ ? { title: block.metadata.title }
189
+ : {}),
190
+ };
191
+ }
192
+ throw new Error(`Unsupported file mime type for file url source: ${block.mime_type}`);
193
+ }
194
+ else if (block.source_type === "text") {
195
+ if (mime_type === "text/plain" || mime_type === "") {
196
+ return {
197
+ type: "document",
198
+ source: {
199
+ type: "text",
200
+ data: block.text,
201
+ media_type: block.mime_type ?? "",
202
+ },
203
+ ...("cache_control" in (block.metadata ?? {})
204
+ ? { cache_control: block.metadata.cache_control }
205
+ : {}),
206
+ ...("citations" in (block.metadata ?? {})
207
+ ? { citations: block.metadata.citations }
208
+ : {}),
209
+ ...("context" in (block.metadata ?? {})
210
+ ? { context: block.metadata.context }
211
+ : {}),
212
+ ...("title" in (block.metadata ?? {})
213
+ ? { title: block.metadata.title }
214
+ : {}),
215
+ };
216
+ }
217
+ else {
218
+ throw new Error(`Unsupported file mime type for file text source: ${block.mime_type}`);
219
+ }
220
+ }
221
+ else if (block.source_type === "base64") {
222
+ if (mime_type === "application/pdf" || mime_type === "") {
223
+ return {
224
+ type: "document",
225
+ source: {
226
+ type: "base64",
227
+ data: block.data,
228
+ media_type: "application/pdf",
229
+ },
230
+ ...("cache_control" in (block.metadata ?? {})
231
+ ? { cache_control: block.metadata.cache_control }
232
+ : {}),
233
+ ...("citations" in (block.metadata ?? {})
234
+ ? { citations: block.metadata.citations }
235
+ : {}),
236
+ ...("context" in (block.metadata ?? {})
237
+ ? { context: block.metadata.context }
238
+ : {}),
239
+ ...("title" in (block.metadata ?? {})
240
+ ? { title: block.metadata.title }
241
+ : {}),
242
+ };
243
+ }
244
+ else if (["image/jpeg", "image/png", "image/gif", "image/webp"].includes(mime_type)) {
245
+ return {
246
+ type: "document",
247
+ source: {
248
+ type: "content",
249
+ content: [
250
+ {
251
+ type: "image",
252
+ source: {
253
+ type: "base64",
254
+ data: block.data,
255
+ media_type: mime_type,
256
+ },
257
+ },
258
+ ],
259
+ },
260
+ ...("cache_control" in (block.metadata ?? {})
261
+ ? { cache_control: block.metadata.cache_control }
262
+ : {}),
263
+ ...("citations" in (block.metadata ?? {})
264
+ ? { citations: block.metadata.citations }
265
+ : {}),
266
+ ...("context" in (block.metadata ?? {})
267
+ ? { context: block.metadata.context }
268
+ : {}),
269
+ ...("title" in (block.metadata ?? {})
270
+ ? { title: block.metadata.title }
271
+ : {}),
272
+ };
273
+ }
274
+ else {
275
+ throw new Error(`Unsupported file mime type for file base64 source: ${block.mime_type}`);
276
+ }
277
+ }
278
+ else {
279
+ throw new Error(`Unsupported file source type: ${block.source_type}`);
280
+ }
281
+ },
282
+ };
81
283
  function _formatContent(content) {
82
284
  const toolTypes = ["tool_use", "tool_result", "input_json_delta"];
83
285
  const textTypes = ["text", "text_delta"];
@@ -86,6 +288,9 @@ function _formatContent(content) {
86
288
  }
87
289
  else {
88
290
  const contentBlocks = content.map((contentPart) => {
291
+ if (isDataContentBlock(contentPart)) {
292
+ return convertToProviderContentBlock(contentPart, standardContentBlockConverter);
293
+ }
89
294
  const cacheControl = "cache_control" in contentPart ? contentPart.cache_control : undefined;
90
295
  if (contentPart.type === "image_url") {
91
296
  let source;
@@ -101,6 +306,9 @@ function _formatContent(content) {
101
306
  ...(cacheControl ? { cache_control: cacheControl } : {}),
102
307
  };
103
308
  }
309
+ else if (isAnthropicImageBlockParam(contentPart)) {
310
+ return contentPart;
311
+ }
104
312
  else if (contentPart.type === "document") {
105
313
  // PDF
106
314
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/anthropic",
3
- "version": "0.3.19",
3
+ "version": "0.3.21",
4
4
  "description": "Anthropic integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -35,7 +35,7 @@
35
35
  "author": "LangChain",
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
- "@anthropic-ai/sdk": "^0.37.0",
38
+ "@anthropic-ai/sdk": "^0.39.0",
39
39
  "fast-xml-parser": "^4.4.1",
40
40
  "zod": "^3.22.4",
41
41
  "zod-to-json-schema": "^3.22.4"