@langchain/google-genai 0.2.9 → 0.2.11

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/README.md CHANGED
@@ -50,6 +50,7 @@ Then initialize
50
50
 
51
51
  ```typescript
52
52
  import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
53
+ import { HumanMessage } from "@langchain/core/messages";
53
54
 
54
55
  const model = new ChatGoogleGenerativeAI({
55
56
  modelName: "gemini-pro",
@@ -27,13 +27,12 @@ const tools_js_1 = require("./utils/tools.cjs");
27
27
  * ## [Runtime args](https://api.js.langchain.com/interfaces/langchain_google_genai.GoogleGenerativeAIChatCallOptions.html)
28
28
  *
29
29
  * Runtime args can be passed as the second argument to any of the base runnable methods `.invoke`. `.stream`, `.batch`, etc.
30
- * They can also be passed via `.bind`, or the second arg in `.bindTools`, like shown in the examples below:
30
+ * They can also be passed via `.withConfig`, or the second arg in `.bindTools`, like shown in the examples below:
31
31
  *
32
32
  * ```typescript
33
- * // When calling `.bind`, call options should be passed via the first argument
34
- * const llmWithArgsBound = llm.bind({
33
+ * // When calling `.withConfig`, call options should be passed via the first argument
34
+ * const llmWithArgsBound = llm.withConfig({
35
35
  * stop: ["\n"],
36
- * tools: [...],
37
36
  * });
38
37
  *
39
38
  * // When calling `.bindTools`, call options should be passed via the second argument
@@ -598,7 +597,10 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
598
597
  return "googlegenerativeai";
599
598
  }
600
599
  bindTools(tools, kwargs) {
601
- return this.bind({ tools: (0, tools_js_1.convertToolsToGenAI)(tools)?.tools, ...kwargs });
600
+ return this.withConfig({
601
+ tools: (0, tools_js_1.convertToolsToGenAI)(tools)?.tools,
602
+ ...kwargs,
603
+ });
602
604
  }
603
605
  invocationParams(options) {
604
606
  const toolsAndConfig = options?.tools?.length
@@ -668,7 +670,10 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
668
670
  const generationResult = (0, common_js_1.mapGenerateContentResultToChatResult)(res.response, {
669
671
  usageMetadata,
670
672
  });
671
- await runManager?.handleLLMNewToken(generationResult.generations[0].text ?? "");
673
+ // may not have generations in output if there was a refusal for safety reasons, malformed function call, etc.
674
+ if (generationResult.generations?.length > 0) {
675
+ await runManager?.handleLLMNewToken(generationResult.generations[0]?.text ?? "");
676
+ }
672
677
  return generationResult;
673
678
  }
674
679
  async *_streamResponseChunks(messages, options, runManager) {
@@ -755,7 +760,7 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
755
760
  if (method === "functionCalling") {
756
761
  let functionName = name ?? "extract";
757
762
  let tools;
758
- if ((0, types_1.isZodSchema)(schema)) {
763
+ if ((0, types_1.isInteropZodSchema)(schema)) {
759
764
  const jsonSchema = (0, zod_to_genai_parameters_js_1.schemaToGenerativeAIParameters)(schema);
760
765
  tools = [
761
766
  {
@@ -800,14 +805,13 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
800
805
  keyName: functionName,
801
806
  });
802
807
  }
803
- llm = this.bind({
804
- tools,
805
- tool_choice: functionName,
808
+ llm = this.bindTools(tools).withConfig({
809
+ allowedFunctionNames: [functionName],
806
810
  });
807
811
  }
808
812
  else {
809
813
  const jsonSchema = (0, zod_to_genai_parameters_js_1.schemaToGenerativeAIParameters)(schema);
810
- llm = this.bind({
814
+ llm = this.withConfig({
811
815
  responseSchema: jsonSchema,
812
816
  });
813
817
  outputParser = new output_parsers_1.JsonOutputParser();
@@ -5,7 +5,7 @@ import { ChatGenerationChunk, ChatResult } from "@langchain/core/outputs";
5
5
  import { BaseChatModel, type BaseChatModelCallOptions, type LangSmithParams, type BaseChatModelParams } from "@langchain/core/language_models/chat_models";
6
6
  import { BaseLanguageModelInput, StructuredOutputMethodOptions } from "@langchain/core/language_models/base";
7
7
  import { Runnable } from "@langchain/core/runnables";
8
- import type { z } from "zod";
8
+ import { InteropZodType } from "@langchain/core/utils/types";
9
9
  import { GoogleGenerativeAIToolType } from "./types.js";
10
10
  export type BaseMessageExamplePair = {
11
11
  input: BaseMessage;
@@ -71,7 +71,7 @@ export interface GoogleGenerativeAIChatInput extends BaseChatModelParams, Pick<G
71
71
  * Top-k changes how the model selects tokens for output.
72
72
  *
73
73
  * A top-k of 1 means the selected token is the most probable among
74
- * all tokens in the models vocabulary (also called greedy decoding),
74
+ * all tokens in the model's vocabulary (also called greedy decoding),
75
75
  * while a top-k of 3 means that the next token is selected from
76
76
  * among the 3 most probable tokens (using temperature).
77
77
  *
@@ -139,13 +139,12 @@ export interface GoogleGenerativeAIChatInput extends BaseChatModelParams, Pick<G
139
139
  * ## [Runtime args](https://api.js.langchain.com/interfaces/langchain_google_genai.GoogleGenerativeAIChatCallOptions.html)
140
140
  *
141
141
  * Runtime args can be passed as the second argument to any of the base runnable methods `.invoke`. `.stream`, `.batch`, etc.
142
- * They can also be passed via `.bind`, or the second arg in `.bindTools`, like shown in the examples below:
142
+ * They can also be passed via `.withConfig`, or the second arg in `.bindTools`, like shown in the examples below:
143
143
  *
144
144
  * ```typescript
145
- * // When calling `.bind`, call options should be passed via the first argument
146
- * const llmWithArgsBound = llm.bind({
145
+ * // When calling `.withConfig`, call options should be passed via the first argument
146
+ * const llmWithArgsBound = llm.withConfig({
147
147
  * stop: ["\n"],
148
- * tools: [...],
149
148
  * });
150
149
  *
151
150
  * // When calling `.bindTools`, call options should be passed via the second argument
@@ -535,8 +534,8 @@ export declare class ChatGoogleGenerativeAI extends BaseChatModel<GoogleGenerati
535
534
  _generate(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): Promise<ChatResult>;
536
535
  _streamResponseChunks(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): AsyncGenerator<ChatGenerationChunk>;
537
536
  completionWithRetry(request: string | GenerateContentRequest | (string | GenerativeAIPart)[], options?: this["ParsedCallOptions"]): Promise<import("@google/generative-ai").GenerateContentResult>;
538
- withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: z.ZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<false>): Runnable<BaseLanguageModelInput, RunOutput>;
539
- withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: z.ZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<true>): Runnable<BaseLanguageModelInput, {
537
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<false>): Runnable<BaseLanguageModelInput, RunOutput>;
538
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<true>): Runnable<BaseLanguageModelInput, {
540
539
  raw: BaseMessage;
541
540
  parsed: RunOutput;
542
541
  }>;
@@ -2,7 +2,7 @@ import { GoogleGenerativeAI as GenerativeAI, } from "@google/generative-ai";
2
2
  import { getEnvironmentVariable } from "@langchain/core/utils/env";
3
3
  import { BaseChatModel, } from "@langchain/core/language_models/chat_models";
4
4
  import { RunnablePassthrough, RunnableSequence, } from "@langchain/core/runnables";
5
- import { isZodSchema } from "@langchain/core/utils/types";
5
+ import { isInteropZodSchema, } from "@langchain/core/utils/types";
6
6
  import { JsonOutputParser, } from "@langchain/core/output_parsers";
7
7
  import { schemaToGenerativeAIParameters, removeAdditionalProperties, } from "./utils/zod_to_genai_parameters.js";
8
8
  import { convertBaseMessagesToContent, convertResponseContentToChatGenerationChunk, mapGenerateContentResultToChatResult, } from "./utils/common.js";
@@ -24,13 +24,12 @@ import { convertToolsToGenAI } from "./utils/tools.js";
24
24
  * ## [Runtime args](https://api.js.langchain.com/interfaces/langchain_google_genai.GoogleGenerativeAIChatCallOptions.html)
25
25
  *
26
26
  * Runtime args can be passed as the second argument to any of the base runnable methods `.invoke`. `.stream`, `.batch`, etc.
27
- * They can also be passed via `.bind`, or the second arg in `.bindTools`, like shown in the examples below:
27
+ * They can also be passed via `.withConfig`, or the second arg in `.bindTools`, like shown in the examples below:
28
28
  *
29
29
  * ```typescript
30
- * // When calling `.bind`, call options should be passed via the first argument
31
- * const llmWithArgsBound = llm.bind({
30
+ * // When calling `.withConfig`, call options should be passed via the first argument
31
+ * const llmWithArgsBound = llm.withConfig({
32
32
  * stop: ["\n"],
33
- * tools: [...],
34
33
  * });
35
34
  *
36
35
  * // When calling `.bindTools`, call options should be passed via the second argument
@@ -595,7 +594,10 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
595
594
  return "googlegenerativeai";
596
595
  }
597
596
  bindTools(tools, kwargs) {
598
- return this.bind({ tools: convertToolsToGenAI(tools)?.tools, ...kwargs });
597
+ return this.withConfig({
598
+ tools: convertToolsToGenAI(tools)?.tools,
599
+ ...kwargs,
600
+ });
599
601
  }
600
602
  invocationParams(options) {
601
603
  const toolsAndConfig = options?.tools?.length
@@ -665,7 +667,10 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
665
667
  const generationResult = mapGenerateContentResultToChatResult(res.response, {
666
668
  usageMetadata,
667
669
  });
668
- await runManager?.handleLLMNewToken(generationResult.generations[0].text ?? "");
670
+ // may not have generations in output if there was a refusal for safety reasons, malformed function call, etc.
671
+ if (generationResult.generations?.length > 0) {
672
+ await runManager?.handleLLMNewToken(generationResult.generations[0]?.text ?? "");
673
+ }
669
674
  return generationResult;
670
675
  }
671
676
  async *_streamResponseChunks(messages, options, runManager) {
@@ -752,7 +757,7 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
752
757
  if (method === "functionCalling") {
753
758
  let functionName = name ?? "extract";
754
759
  let tools;
755
- if (isZodSchema(schema)) {
760
+ if (isInteropZodSchema(schema)) {
756
761
  const jsonSchema = schemaToGenerativeAIParameters(schema);
757
762
  tools = [
758
763
  {
@@ -797,14 +802,13 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
797
802
  keyName: functionName,
798
803
  });
799
804
  }
800
- llm = this.bind({
801
- tools,
802
- tool_choice: functionName,
805
+ llm = this.bindTools(tools).withConfig({
806
+ allowedFunctionNames: [functionName],
803
807
  });
804
808
  }
805
809
  else {
806
810
  const jsonSchema = schemaToGenerativeAIParameters(schema);
807
- llm = this.bind({
811
+ llm = this.withConfig({
808
812
  responseSchema: jsonSchema,
809
813
  });
810
814
  outputParser = new JsonOutputParser();
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GoogleGenerativeAIToolsOutputParser = void 0;
4
4
  const output_parsers_1 = require("@langchain/core/output_parsers");
5
+ const types_1 = require("@langchain/core/utils/types");
5
6
  class GoogleGenerativeAIToolsOutputParser extends output_parsers_1.BaseLLMOutputParser {
6
7
  static lc_name() {
7
8
  return "GoogleGenerativeAIToolsOutputParser";
@@ -48,12 +49,12 @@ class GoogleGenerativeAIToolsOutputParser extends output_parsers_1.BaseLLMOutput
48
49
  if (this.zodSchema === undefined) {
49
50
  return result;
50
51
  }
51
- const zodParsedResult = await this.zodSchema.safeParseAsync(result);
52
+ const zodParsedResult = await (0, types_1.interopSafeParseAsync)(this.zodSchema, result);
52
53
  if (zodParsedResult.success) {
53
54
  return zodParsedResult.data;
54
55
  }
55
56
  else {
56
- throw new output_parsers_1.OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(zodParsedResult.error.errors)}`, JSON.stringify(result, null, 2));
57
+ throw new output_parsers_1.OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(zodParsedResult.error.issues)}`, JSON.stringify(result, null, 2));
57
58
  }
58
59
  }
59
60
  async parseResult(generations) {
@@ -1,8 +1,8 @@
1
- import type { z } from "zod";
2
1
  import { BaseLLMOutputParser } from "@langchain/core/output_parsers";
3
- import { JsonOutputKeyToolsParserParams } from "@langchain/core/output_parsers/openai_tools";
4
2
  import { ChatGeneration } from "@langchain/core/outputs";
5
- interface GoogleGenerativeAIToolsOutputParserParams<T extends Record<string, any>> extends JsonOutputKeyToolsParserParams<T> {
3
+ import { InteropZodType } from "@langchain/core/utils/types";
4
+ import { JsonOutputKeyToolsParserParamsInterop } from "@langchain/core/output_parsers/openai_tools";
5
+ interface GoogleGenerativeAIToolsOutputParserParams<T extends Record<string, any>> extends JsonOutputKeyToolsParserParamsInterop<T> {
6
6
  }
7
7
  export declare class GoogleGenerativeAIToolsOutputParser<T extends Record<string, any> = Record<string, any>> extends BaseLLMOutputParser<T> {
8
8
  static lc_name(): string;
@@ -12,7 +12,7 @@ export declare class GoogleGenerativeAIToolsOutputParser<T extends Record<string
12
12
  keyName: string;
13
13
  /** Whether to return only the first tool call. */
14
14
  returnSingle: boolean;
15
- zodSchema?: z.ZodType<T>;
15
+ zodSchema?: InteropZodType<T>;
16
16
  constructor(params: GoogleGenerativeAIToolsOutputParserParams<T>);
17
17
  protected _validateResult(result: unknown): Promise<T>;
18
18
  parseResult(generations: ChatGeneration[]): Promise<T>;
@@ -1,4 +1,5 @@
1
1
  import { BaseLLMOutputParser, OutputParserException, } from "@langchain/core/output_parsers";
2
+ import { interopSafeParseAsync, } from "@langchain/core/utils/types";
2
3
  export class GoogleGenerativeAIToolsOutputParser extends BaseLLMOutputParser {
3
4
  static lc_name() {
4
5
  return "GoogleGenerativeAIToolsOutputParser";
@@ -45,12 +46,12 @@ export class GoogleGenerativeAIToolsOutputParser extends BaseLLMOutputParser {
45
46
  if (this.zodSchema === undefined) {
46
47
  return result;
47
48
  }
48
- const zodParsedResult = await this.zodSchema.safeParseAsync(result);
49
+ const zodParsedResult = await interopSafeParseAsync(this.zodSchema, result);
49
50
  if (zodParsedResult.success) {
50
51
  return zodParsedResult.data;
51
52
  }
52
53
  else {
53
- throw new OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(zodParsedResult.error.errors)}`, JSON.stringify(result, null, 2));
54
+ throw new OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(zodParsedResult.error.issues)}`, JSON.stringify(result, null, 2));
54
55
  }
55
56
  }
56
57
  async parseResult(generations) {
@@ -78,6 +78,200 @@ function inferToolNameFromPreviousMessages(message, previousMessages) {
78
78
  return toolCall.id === message.tool_call_id;
79
79
  })?.name;
80
80
  }
81
+ function _getStandardContentBlockConverter(isMultimodalModel) {
82
+ const standardContentBlockConverter = {
83
+ providerName: "Google Gemini",
84
+ fromStandardTextBlock(block) {
85
+ return {
86
+ text: block.text,
87
+ };
88
+ },
89
+ fromStandardImageBlock(block) {
90
+ if (!isMultimodalModel) {
91
+ throw new Error("This model does not support images");
92
+ }
93
+ if (block.source_type === "url") {
94
+ const data = (0, messages_1.parseBase64DataUrl)({ dataUrl: block.url });
95
+ if (data) {
96
+ return {
97
+ inlineData: {
98
+ mimeType: data.mime_type,
99
+ data: data.data,
100
+ },
101
+ };
102
+ }
103
+ else {
104
+ return {
105
+ fileData: {
106
+ mimeType: block.mime_type ?? "",
107
+ fileUri: block.url,
108
+ },
109
+ };
110
+ }
111
+ }
112
+ if (block.source_type === "base64") {
113
+ return {
114
+ inlineData: {
115
+ mimeType: block.mime_type ?? "",
116
+ data: block.data,
117
+ },
118
+ };
119
+ }
120
+ throw new Error(`Unsupported source type: ${block.source_type}`);
121
+ },
122
+ fromStandardAudioBlock(block) {
123
+ if (!isMultimodalModel) {
124
+ throw new Error("This model does not support audio");
125
+ }
126
+ if (block.source_type === "url") {
127
+ const data = (0, messages_1.parseBase64DataUrl)({ dataUrl: block.url });
128
+ if (data) {
129
+ return {
130
+ inlineData: {
131
+ mimeType: data.mime_type,
132
+ data: data.data,
133
+ },
134
+ };
135
+ }
136
+ else {
137
+ return {
138
+ fileData: {
139
+ mimeType: block.mime_type ?? "",
140
+ fileUri: block.url,
141
+ },
142
+ };
143
+ }
144
+ }
145
+ if (block.source_type === "base64") {
146
+ return {
147
+ inlineData: {
148
+ mimeType: block.mime_type ?? "",
149
+ data: block.data,
150
+ },
151
+ };
152
+ }
153
+ throw new Error(`Unsupported source type: ${block.source_type}`);
154
+ },
155
+ fromStandardFileBlock(block) {
156
+ if (!isMultimodalModel) {
157
+ throw new Error("This model does not support files");
158
+ }
159
+ if (block.source_type === "text") {
160
+ return {
161
+ text: block.text,
162
+ };
163
+ }
164
+ if (block.source_type === "url") {
165
+ const data = (0, messages_1.parseBase64DataUrl)({ dataUrl: block.url });
166
+ if (data) {
167
+ return {
168
+ inlineData: {
169
+ mimeType: data.mime_type,
170
+ data: data.data,
171
+ },
172
+ };
173
+ }
174
+ else {
175
+ return {
176
+ fileData: {
177
+ mimeType: block.mime_type ?? "",
178
+ fileUri: block.url,
179
+ },
180
+ };
181
+ }
182
+ }
183
+ if (block.source_type === "base64") {
184
+ return {
185
+ inlineData: {
186
+ mimeType: block.mime_type ?? "",
187
+ data: block.data,
188
+ },
189
+ };
190
+ }
191
+ throw new Error(`Unsupported source type: ${block.source_type}`);
192
+ },
193
+ };
194
+ return standardContentBlockConverter;
195
+ }
196
+ function _convertLangChainContentToPart(content, isMultimodalModel) {
197
+ if ((0, messages_1.isDataContentBlock)(content)) {
198
+ return (0, messages_1.convertToProviderContentBlock)(content, _getStandardContentBlockConverter(isMultimodalModel));
199
+ }
200
+ if (content.type === "text") {
201
+ return { text: content.text };
202
+ }
203
+ else if (content.type === "executableCode") {
204
+ return { executableCode: content.executableCode };
205
+ }
206
+ else if (content.type === "codeExecutionResult") {
207
+ return { codeExecutionResult: content.codeExecutionResult };
208
+ }
209
+ else if (content.type === "image_url") {
210
+ if (!isMultimodalModel) {
211
+ throw new Error(`This model does not support images`);
212
+ }
213
+ let source;
214
+ if (typeof content.image_url === "string") {
215
+ source = content.image_url;
216
+ }
217
+ else if (typeof content.image_url === "object" &&
218
+ "url" in content.image_url) {
219
+ source = content.image_url.url;
220
+ }
221
+ else {
222
+ throw new Error("Please provide image as base64 encoded data URL");
223
+ }
224
+ const [dm, data] = source.split(",");
225
+ if (!dm.startsWith("data:")) {
226
+ throw new Error("Please provide image as base64 encoded data URL");
227
+ }
228
+ const [mimeType, encoding] = dm.replace(/^data:/, "").split(";");
229
+ if (encoding !== "base64") {
230
+ throw new Error("Please provide image as base64 encoded data URL");
231
+ }
232
+ return {
233
+ inlineData: {
234
+ data,
235
+ mimeType,
236
+ },
237
+ };
238
+ }
239
+ else if (content.type === "media") {
240
+ return messageContentMedia(content);
241
+ }
242
+ else if (content.type === "tool_use") {
243
+ return {
244
+ functionCall: {
245
+ name: content.name,
246
+ args: content.input,
247
+ },
248
+ };
249
+ }
250
+ else if (content.type?.includes("/") &&
251
+ // Ensure it's a single slash.
252
+ content.type.split("/").length === 2 &&
253
+ "data" in content &&
254
+ typeof content.data === "string") {
255
+ return {
256
+ inlineData: {
257
+ mimeType: content.type,
258
+ data: content.data,
259
+ },
260
+ };
261
+ }
262
+ else if ("functionCall" in content) {
263
+ // No action needed here — function calls will be added later from message.tool_calls
264
+ return undefined;
265
+ }
266
+ else {
267
+ if ("type" in content) {
268
+ throw new Error(`Unknown content type ${content.type}`);
269
+ }
270
+ else {
271
+ throw new Error(`Unknown content ${JSON.stringify(content)}`);
272
+ }
273
+ }
274
+ }
81
275
  function convertMessageContentToParts(message, isMultimodalModel, previousMessages) {
82
276
  if ((0, messages_1.isToolMessage)(message)) {
83
277
  const messageName = message.name ??
@@ -85,13 +279,29 @@ function convertMessageContentToParts(message, isMultimodalModel, previousMessag
85
279
  if (messageName === undefined) {
86
280
  throw new Error(`Google requires a tool name for each tool call response, and we could not infer a called tool name for ToolMessage "${message.id}" from your passed messages. Please populate a "name" field on that ToolMessage explicitly.`);
87
281
  }
282
+ const result = Array.isArray(message.content)
283
+ ? message.content
284
+ .map((c) => _convertLangChainContentToPart(c, isMultimodalModel))
285
+ .filter((p) => p !== undefined)
286
+ : message.content;
287
+ if (message.status === "error") {
288
+ return [
289
+ {
290
+ functionResponse: {
291
+ name: messageName,
292
+ // The API expects an object with an `error` field if the function call fails.
293
+ // `error` must be a valid object (not a string or array), so we wrap `message.content` here
294
+ response: { error: { details: result } },
295
+ },
296
+ },
297
+ ];
298
+ }
88
299
  return [
89
300
  {
90
301
  functionResponse: {
91
302
  name: messageName,
92
- response: typeof message.content === "string"
93
- ? { result: message.content }
94
- : message.content,
303
+ // again, can't have a string or array value for `response`, so we wrap it as an object here
304
+ response: { result },
95
305
  },
96
306
  },
97
307
  ];
@@ -102,80 +312,9 @@ function convertMessageContentToParts(message, isMultimodalModel, previousMessag
102
312
  messageParts.push({ text: message.content });
103
313
  }
104
314
  if (Array.isArray(message.content)) {
105
- message.content.forEach((c) => {
106
- if (c.type === "text") {
107
- messageParts.push({ text: c.text });
108
- }
109
- else if (c.type === "executableCode") {
110
- messageParts.push({ executableCode: c.executableCode });
111
- }
112
- else if (c.type === "codeExecutionResult") {
113
- messageParts.push({ codeExecutionResult: c.codeExecutionResult });
114
- }
115
- else if (c.type === "image_url") {
116
- if (!isMultimodalModel) {
117
- throw new Error(`This model does not support images`);
118
- }
119
- let source;
120
- if (typeof c.image_url === "string") {
121
- source = c.image_url;
122
- }
123
- else if (typeof c.image_url === "object" && "url" in c.image_url) {
124
- source = c.image_url.url;
125
- }
126
- else {
127
- throw new Error("Please provide image as base64 encoded data URL");
128
- }
129
- const [dm, data] = source.split(",");
130
- if (!dm.startsWith("data:")) {
131
- throw new Error("Please provide image as base64 encoded data URL");
132
- }
133
- const [mimeType, encoding] = dm.replace(/^data:/, "").split(";");
134
- if (encoding !== "base64") {
135
- throw new Error("Please provide image as base64 encoded data URL");
136
- }
137
- messageParts.push({
138
- inlineData: {
139
- data,
140
- mimeType,
141
- },
142
- });
143
- }
144
- else if (c.type === "media") {
145
- messageParts.push(messageContentMedia(c));
146
- }
147
- else if (c.type === "tool_use") {
148
- functionCalls.push({
149
- functionCall: {
150
- name: c.name,
151
- args: c.input,
152
- },
153
- });
154
- }
155
- else if (c.type?.includes("/") &&
156
- // Ensure it's a single slash.
157
- c.type.split("/").length === 2 &&
158
- "data" in c &&
159
- typeof c.data === "string") {
160
- messageParts.push({
161
- inlineData: {
162
- mimeType: c.type,
163
- data: c.data,
164
- },
165
- });
166
- }
167
- else if ("functionCall" in c) {
168
- // No action needed here — function calls will be added later from message.tool_calls
169
- }
170
- else {
171
- if ("type" in c) {
172
- throw new Error(`Unknown content type ${c.type}`);
173
- }
174
- else {
175
- throw new Error(`Unknown content ${JSON.stringify(c)}`);
176
- }
177
- }
178
- });
315
+ messageParts.push(...message.content
316
+ .map((c) => _convertLangChainContentToPart(c, isMultimodalModel))
317
+ .filter((p) => p !== undefined));
179
318
  }
180
319
  if ((0, messages_1.isAIMessage)(message) && message.tool_calls?.length) {
181
320
  functionCalls = message.tool_calls.map((tc) => {
@@ -251,10 +390,13 @@ function mapGenerateContentResultToChatResult(response, extra) {
251
390
  const [candidate] = response.candidates;
252
391
  const { content: candidateContent, ...generationInfo } = candidate;
253
392
  let content;
254
- if (candidateContent?.parts.length === 1 && candidateContent.parts[0].text) {
393
+ if (Array.isArray(candidateContent?.parts) &&
394
+ candidateContent.parts.length === 1 &&
395
+ candidateContent.parts[0].text) {
255
396
  content = candidateContent.parts[0].text;
256
397
  }
257
- else {
398
+ else if (Array.isArray(candidateContent?.parts) &&
399
+ candidateContent.parts.length > 0) {
258
400
  content = candidateContent.parts.map((p) => {
259
401
  if ("text" in p) {
260
402
  return {
@@ -277,17 +419,22 @@ function mapGenerateContentResultToChatResult(response, extra) {
277
419
  return p;
278
420
  });
279
421
  }
422
+ else {
423
+ // no content returned - likely due to abnormal stop reason, e.g. malformed function call
424
+ content = [];
425
+ }
280
426
  let text = "";
281
427
  if (typeof content === "string") {
282
428
  text = content;
283
429
  }
284
- else if ("text" in content[0]) {
285
- text = content[0].text;
430
+ else if (Array.isArray(content) && content.length > 0) {
431
+ const block = content.find((b) => "text" in b);
432
+ text = block?.text ?? text;
286
433
  }
287
434
  const generation = {
288
435
  text,
289
436
  message: new messages_1.AIMessage({
290
- content,
437
+ content: content ?? "",
291
438
  tool_calls: functionCalls?.map((fc) => {
292
439
  return {
293
440
  ...fc,
@@ -323,11 +470,11 @@ function convertResponseContentToChatGenerationChunk(response, extra) {
323
470
  const { content: candidateContent, ...generationInfo } = candidate;
324
471
  let content;
325
472
  // Checks if some parts do not have text. If false, it means that the content is a string.
326
- if (candidateContent?.parts &&
473
+ if (Array.isArray(candidateContent?.parts) &&
327
474
  candidateContent.parts.every((p) => "text" in p)) {
328
475
  content = candidateContent.parts.map((p) => p.text).join("");
329
476
  }
330
- else if (candidateContent.parts) {
477
+ else if (Array.isArray(candidateContent?.parts)) {
331
478
  content = candidateContent.parts.map((p) => {
332
479
  if ("text" in p) {
333
480
  return {
@@ -350,12 +497,17 @@ function convertResponseContentToChatGenerationChunk(response, extra) {
350
497
  return p;
351
498
  });
352
499
  }
500
+ else {
501
+ // no content returned - likely due to abnormal stop reason, e.g. malformed function call
502
+ content = [];
503
+ }
353
504
  let text = "";
354
505
  if (content && typeof content === "string") {
355
506
  text = content;
356
507
  }
357
- else if (content && typeof content === "object" && "text" in content[0]) {
358
- text = content[0].text;
508
+ else if (Array.isArray(content)) {
509
+ const block = content.find((b) => "text" in b);
510
+ text = block?.text ?? "";
359
511
  }
360
512
  const toolCallChunks = [];
361
513
  if (functionCalls) {
@@ -1,4 +1,4 @@
1
- import { AIMessage, AIMessageChunk, ChatMessage, isAIMessage, isBaseMessage, isToolMessage, } from "@langchain/core/messages";
1
+ import { AIMessage, AIMessageChunk, ChatMessage, isAIMessage, isBaseMessage, isToolMessage, parseBase64DataUrl, convertToProviderContentBlock, isDataContentBlock, } from "@langchain/core/messages";
2
2
  import { ChatGenerationChunk, } from "@langchain/core/outputs";
3
3
  import { isLangChainTool } from "@langchain/core/utils/function_calling";
4
4
  import { isOpenAITool } from "@langchain/core/language_models/base";
@@ -73,6 +73,200 @@ function inferToolNameFromPreviousMessages(message, previousMessages) {
73
73
  return toolCall.id === message.tool_call_id;
74
74
  })?.name;
75
75
  }
76
+ function _getStandardContentBlockConverter(isMultimodalModel) {
77
+ const standardContentBlockConverter = {
78
+ providerName: "Google Gemini",
79
+ fromStandardTextBlock(block) {
80
+ return {
81
+ text: block.text,
82
+ };
83
+ },
84
+ fromStandardImageBlock(block) {
85
+ if (!isMultimodalModel) {
86
+ throw new Error("This model does not support images");
87
+ }
88
+ if (block.source_type === "url") {
89
+ const data = parseBase64DataUrl({ dataUrl: block.url });
90
+ if (data) {
91
+ return {
92
+ inlineData: {
93
+ mimeType: data.mime_type,
94
+ data: data.data,
95
+ },
96
+ };
97
+ }
98
+ else {
99
+ return {
100
+ fileData: {
101
+ mimeType: block.mime_type ?? "",
102
+ fileUri: block.url,
103
+ },
104
+ };
105
+ }
106
+ }
107
+ if (block.source_type === "base64") {
108
+ return {
109
+ inlineData: {
110
+ mimeType: block.mime_type ?? "",
111
+ data: block.data,
112
+ },
113
+ };
114
+ }
115
+ throw new Error(`Unsupported source type: ${block.source_type}`);
116
+ },
117
+ fromStandardAudioBlock(block) {
118
+ if (!isMultimodalModel) {
119
+ throw new Error("This model does not support audio");
120
+ }
121
+ if (block.source_type === "url") {
122
+ const data = parseBase64DataUrl({ dataUrl: block.url });
123
+ if (data) {
124
+ return {
125
+ inlineData: {
126
+ mimeType: data.mime_type,
127
+ data: data.data,
128
+ },
129
+ };
130
+ }
131
+ else {
132
+ return {
133
+ fileData: {
134
+ mimeType: block.mime_type ?? "",
135
+ fileUri: block.url,
136
+ },
137
+ };
138
+ }
139
+ }
140
+ if (block.source_type === "base64") {
141
+ return {
142
+ inlineData: {
143
+ mimeType: block.mime_type ?? "",
144
+ data: block.data,
145
+ },
146
+ };
147
+ }
148
+ throw new Error(`Unsupported source type: ${block.source_type}`);
149
+ },
150
+ fromStandardFileBlock(block) {
151
+ if (!isMultimodalModel) {
152
+ throw new Error("This model does not support files");
153
+ }
154
+ if (block.source_type === "text") {
155
+ return {
156
+ text: block.text,
157
+ };
158
+ }
159
+ if (block.source_type === "url") {
160
+ const data = parseBase64DataUrl({ dataUrl: block.url });
161
+ if (data) {
162
+ return {
163
+ inlineData: {
164
+ mimeType: data.mime_type,
165
+ data: data.data,
166
+ },
167
+ };
168
+ }
169
+ else {
170
+ return {
171
+ fileData: {
172
+ mimeType: block.mime_type ?? "",
173
+ fileUri: block.url,
174
+ },
175
+ };
176
+ }
177
+ }
178
+ if (block.source_type === "base64") {
179
+ return {
180
+ inlineData: {
181
+ mimeType: block.mime_type ?? "",
182
+ data: block.data,
183
+ },
184
+ };
185
+ }
186
+ throw new Error(`Unsupported source type: ${block.source_type}`);
187
+ },
188
+ };
189
+ return standardContentBlockConverter;
190
+ }
191
+ function _convertLangChainContentToPart(content, isMultimodalModel) {
192
+ if (isDataContentBlock(content)) {
193
+ return convertToProviderContentBlock(content, _getStandardContentBlockConverter(isMultimodalModel));
194
+ }
195
+ if (content.type === "text") {
196
+ return { text: content.text };
197
+ }
198
+ else if (content.type === "executableCode") {
199
+ return { executableCode: content.executableCode };
200
+ }
201
+ else if (content.type === "codeExecutionResult") {
202
+ return { codeExecutionResult: content.codeExecutionResult };
203
+ }
204
+ else if (content.type === "image_url") {
205
+ if (!isMultimodalModel) {
206
+ throw new Error(`This model does not support images`);
207
+ }
208
+ let source;
209
+ if (typeof content.image_url === "string") {
210
+ source = content.image_url;
211
+ }
212
+ else if (typeof content.image_url === "object" &&
213
+ "url" in content.image_url) {
214
+ source = content.image_url.url;
215
+ }
216
+ else {
217
+ throw new Error("Please provide image as base64 encoded data URL");
218
+ }
219
+ const [dm, data] = source.split(",");
220
+ if (!dm.startsWith("data:")) {
221
+ throw new Error("Please provide image as base64 encoded data URL");
222
+ }
223
+ const [mimeType, encoding] = dm.replace(/^data:/, "").split(";");
224
+ if (encoding !== "base64") {
225
+ throw new Error("Please provide image as base64 encoded data URL");
226
+ }
227
+ return {
228
+ inlineData: {
229
+ data,
230
+ mimeType,
231
+ },
232
+ };
233
+ }
234
+ else if (content.type === "media") {
235
+ return messageContentMedia(content);
236
+ }
237
+ else if (content.type === "tool_use") {
238
+ return {
239
+ functionCall: {
240
+ name: content.name,
241
+ args: content.input,
242
+ },
243
+ };
244
+ }
245
+ else if (content.type?.includes("/") &&
246
+ // Ensure it's a single slash.
247
+ content.type.split("/").length === 2 &&
248
+ "data" in content &&
249
+ typeof content.data === "string") {
250
+ return {
251
+ inlineData: {
252
+ mimeType: content.type,
253
+ data: content.data,
254
+ },
255
+ };
256
+ }
257
+ else if ("functionCall" in content) {
258
+ // No action needed here — function calls will be added later from message.tool_calls
259
+ return undefined;
260
+ }
261
+ else {
262
+ if ("type" in content) {
263
+ throw new Error(`Unknown content type ${content.type}`);
264
+ }
265
+ else {
266
+ throw new Error(`Unknown content ${JSON.stringify(content)}`);
267
+ }
268
+ }
269
+ }
76
270
  export function convertMessageContentToParts(message, isMultimodalModel, previousMessages) {
77
271
  if (isToolMessage(message)) {
78
272
  const messageName = message.name ??
@@ -80,13 +274,29 @@ export function convertMessageContentToParts(message, isMultimodalModel, previou
80
274
  if (messageName === undefined) {
81
275
  throw new Error(`Google requires a tool name for each tool call response, and we could not infer a called tool name for ToolMessage "${message.id}" from your passed messages. Please populate a "name" field on that ToolMessage explicitly.`);
82
276
  }
277
+ const result = Array.isArray(message.content)
278
+ ? message.content
279
+ .map((c) => _convertLangChainContentToPart(c, isMultimodalModel))
280
+ .filter((p) => p !== undefined)
281
+ : message.content;
282
+ if (message.status === "error") {
283
+ return [
284
+ {
285
+ functionResponse: {
286
+ name: messageName,
287
+ // The API expects an object with an `error` field if the function call fails.
288
+ // `error` must be a valid object (not a string or array), so we wrap `message.content` here
289
+ response: { error: { details: result } },
290
+ },
291
+ },
292
+ ];
293
+ }
83
294
  return [
84
295
  {
85
296
  functionResponse: {
86
297
  name: messageName,
87
- response: typeof message.content === "string"
88
- ? { result: message.content }
89
- : message.content,
298
+ // again, can't have a string or array value for `response`, so we wrap it as an object here
299
+ response: { result },
90
300
  },
91
301
  },
92
302
  ];
@@ -97,80 +307,9 @@ export function convertMessageContentToParts(message, isMultimodalModel, previou
97
307
  messageParts.push({ text: message.content });
98
308
  }
99
309
  if (Array.isArray(message.content)) {
100
- message.content.forEach((c) => {
101
- if (c.type === "text") {
102
- messageParts.push({ text: c.text });
103
- }
104
- else if (c.type === "executableCode") {
105
- messageParts.push({ executableCode: c.executableCode });
106
- }
107
- else if (c.type === "codeExecutionResult") {
108
- messageParts.push({ codeExecutionResult: c.codeExecutionResult });
109
- }
110
- else if (c.type === "image_url") {
111
- if (!isMultimodalModel) {
112
- throw new Error(`This model does not support images`);
113
- }
114
- let source;
115
- if (typeof c.image_url === "string") {
116
- source = c.image_url;
117
- }
118
- else if (typeof c.image_url === "object" && "url" in c.image_url) {
119
- source = c.image_url.url;
120
- }
121
- else {
122
- throw new Error("Please provide image as base64 encoded data URL");
123
- }
124
- const [dm, data] = source.split(",");
125
- if (!dm.startsWith("data:")) {
126
- throw new Error("Please provide image as base64 encoded data URL");
127
- }
128
- const [mimeType, encoding] = dm.replace(/^data:/, "").split(";");
129
- if (encoding !== "base64") {
130
- throw new Error("Please provide image as base64 encoded data URL");
131
- }
132
- messageParts.push({
133
- inlineData: {
134
- data,
135
- mimeType,
136
- },
137
- });
138
- }
139
- else if (c.type === "media") {
140
- messageParts.push(messageContentMedia(c));
141
- }
142
- else if (c.type === "tool_use") {
143
- functionCalls.push({
144
- functionCall: {
145
- name: c.name,
146
- args: c.input,
147
- },
148
- });
149
- }
150
- else if (c.type?.includes("/") &&
151
- // Ensure it's a single slash.
152
- c.type.split("/").length === 2 &&
153
- "data" in c &&
154
- typeof c.data === "string") {
155
- messageParts.push({
156
- inlineData: {
157
- mimeType: c.type,
158
- data: c.data,
159
- },
160
- });
161
- }
162
- else if ("functionCall" in c) {
163
- // No action needed here — function calls will be added later from message.tool_calls
164
- }
165
- else {
166
- if ("type" in c) {
167
- throw new Error(`Unknown content type ${c.type}`);
168
- }
169
- else {
170
- throw new Error(`Unknown content ${JSON.stringify(c)}`);
171
- }
172
- }
173
- });
310
+ messageParts.push(...message.content
311
+ .map((c) => _convertLangChainContentToPart(c, isMultimodalModel))
312
+ .filter((p) => p !== undefined));
174
313
  }
175
314
  if (isAIMessage(message) && message.tool_calls?.length) {
176
315
  functionCalls = message.tool_calls.map((tc) => {
@@ -244,10 +383,13 @@ export function mapGenerateContentResultToChatResult(response, extra) {
244
383
  const [candidate] = response.candidates;
245
384
  const { content: candidateContent, ...generationInfo } = candidate;
246
385
  let content;
247
- if (candidateContent?.parts.length === 1 && candidateContent.parts[0].text) {
386
+ if (Array.isArray(candidateContent?.parts) &&
387
+ candidateContent.parts.length === 1 &&
388
+ candidateContent.parts[0].text) {
248
389
  content = candidateContent.parts[0].text;
249
390
  }
250
- else {
391
+ else if (Array.isArray(candidateContent?.parts) &&
392
+ candidateContent.parts.length > 0) {
251
393
  content = candidateContent.parts.map((p) => {
252
394
  if ("text" in p) {
253
395
  return {
@@ -270,17 +412,22 @@ export function mapGenerateContentResultToChatResult(response, extra) {
270
412
  return p;
271
413
  });
272
414
  }
415
+ else {
416
+ // no content returned - likely due to abnormal stop reason, e.g. malformed function call
417
+ content = [];
418
+ }
273
419
  let text = "";
274
420
  if (typeof content === "string") {
275
421
  text = content;
276
422
  }
277
- else if ("text" in content[0]) {
278
- text = content[0].text;
423
+ else if (Array.isArray(content) && content.length > 0) {
424
+ const block = content.find((b) => "text" in b);
425
+ text = block?.text ?? text;
279
426
  }
280
427
  const generation = {
281
428
  text,
282
429
  message: new AIMessage({
283
- content,
430
+ content: content ?? "",
284
431
  tool_calls: functionCalls?.map((fc) => {
285
432
  return {
286
433
  ...fc,
@@ -315,11 +462,11 @@ export function convertResponseContentToChatGenerationChunk(response, extra) {
315
462
  const { content: candidateContent, ...generationInfo } = candidate;
316
463
  let content;
317
464
  // Checks if some parts do not have text. If false, it means that the content is a string.
318
- if (candidateContent?.parts &&
465
+ if (Array.isArray(candidateContent?.parts) &&
319
466
  candidateContent.parts.every((p) => "text" in p)) {
320
467
  content = candidateContent.parts.map((p) => p.text).join("");
321
468
  }
322
- else if (candidateContent.parts) {
469
+ else if (Array.isArray(candidateContent?.parts)) {
323
470
  content = candidateContent.parts.map((p) => {
324
471
  if ("text" in p) {
325
472
  return {
@@ -342,12 +489,17 @@ export function convertResponseContentToChatGenerationChunk(response, extra) {
342
489
  return p;
343
490
  });
344
491
  }
492
+ else {
493
+ // no content returned - likely due to abnormal stop reason, e.g. malformed function call
494
+ content = [];
495
+ }
345
496
  let text = "";
346
497
  if (content && typeof content === "string") {
347
498
  text = content;
348
499
  }
349
- else if (content && typeof content === "object" && "text" in content[0]) {
350
- text = content[0].text;
500
+ else if (Array.isArray(content)) {
501
+ const block = content.find((b) => "text" in b);
502
+ text = block?.text ?? "";
351
503
  }
352
504
  const toolCallChunks = [];
353
505
  if (functionCalls) {
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.jsonSchemaToGeminiParameters = exports.schemaToGenerativeAIParameters = exports.removeAdditionalProperties = void 0;
5
5
  const types_1 = require("@langchain/core/utils/types");
6
- const zod_to_json_schema_1 = require("zod-to-json-schema");
6
+ const json_schema_1 = require("@langchain/core/utils/json_schema");
7
7
  function removeAdditionalProperties(
8
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
9
  obj) {
@@ -36,7 +36,7 @@ exports.removeAdditionalProperties = removeAdditionalProperties;
36
36
  function schemaToGenerativeAIParameters(schema) {
37
37
  // GenerativeAI doesn't accept either the $schema or additionalProperties
38
38
  // attributes, so we need to explicitly remove them.
39
- const jsonSchema = removeAdditionalProperties((0, types_1.isZodSchema)(schema) ? (0, zod_to_json_schema_1.zodToJsonSchema)(schema) : schema);
39
+ const jsonSchema = removeAdditionalProperties((0, types_1.isInteropZodSchema)(schema) ? (0, json_schema_1.toJsonSchema)(schema) : schema);
40
40
  const { $schema, ...rest } = jsonSchema;
41
41
  return rest;
42
42
  }
@@ -1,6 +1,6 @@
1
- import type { z } from "zod";
2
1
  import { type FunctionDeclarationSchema as GenerativeAIFunctionDeclarationSchema, type SchemaType as FunctionDeclarationSchemaType } from "@google/generative-ai";
3
- import { type JsonSchema7Type } from "zod-to-json-schema";
2
+ import { InteropZodType } from "@langchain/core/utils/types";
3
+ import { type JsonSchema7Type } from "@langchain/core/utils/json_schema";
4
4
  export interface GenerativeAIJsonSchema extends Record<string, unknown> {
5
5
  properties?: Record<string, GenerativeAIJsonSchema>;
6
6
  type: FunctionDeclarationSchemaType;
@@ -10,5 +10,5 @@ export interface GenerativeAIJsonSchemaDirty extends GenerativeAIJsonSchema {
10
10
  additionalProperties?: boolean;
11
11
  }
12
12
  export declare function removeAdditionalProperties(obj: Record<string, any>): GenerativeAIJsonSchema;
13
- export declare function schemaToGenerativeAIParameters<RunOutput extends Record<string, any> = Record<string, any>>(schema: z.ZodType<RunOutput> | z.ZodEffects<z.ZodType<RunOutput>> | JsonSchema7Type): GenerativeAIFunctionDeclarationSchema;
13
+ export declare function schemaToGenerativeAIParameters<RunOutput extends Record<string, any> = Record<string, any>>(schema: InteropZodType<RunOutput> | JsonSchema7Type): GenerativeAIFunctionDeclarationSchema;
14
14
  export declare function jsonSchemaToGeminiParameters(schema: Record<string, any>): GenerativeAIFunctionDeclarationSchema;
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
- import { isZodSchema } from "@langchain/core/utils/types";
3
- import { zodToJsonSchema } from "zod-to-json-schema";
2
+ import { isInteropZodSchema, } from "@langchain/core/utils/types";
3
+ import { toJsonSchema, } from "@langchain/core/utils/json_schema";
4
4
  export function removeAdditionalProperties(
5
5
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
6
  obj) {
@@ -32,7 +32,7 @@ obj) {
32
32
  export function schemaToGenerativeAIParameters(schema) {
33
33
  // GenerativeAI doesn't accept either the $schema or additionalProperties
34
34
  // attributes, so we need to explicitly remove them.
35
- const jsonSchema = removeAdditionalProperties(isZodSchema(schema) ? zodToJsonSchema(schema) : schema);
35
+ const jsonSchema = removeAdditionalProperties(isInteropZodSchema(schema) ? toJsonSchema(schema) : schema);
36
36
  const { $schema, ...rest } = jsonSchema;
37
37
  return rest;
38
38
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/google-genai",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "description": "Google Generative AI integration for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -36,15 +36,14 @@
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
38
  "@google/generative-ai": "^0.24.0",
39
- "uuid": "^11.1.0",
40
- "zod-to-json-schema": "^3.22.4"
39
+ "uuid": "^11.1.0"
41
40
  },
42
41
  "peerDependencies": {
43
- "@langchain/core": ">=0.3.55 <0.4.0"
42
+ "@langchain/core": ">=0.3.58 <0.4.0"
44
43
  },
45
44
  "devDependencies": {
46
45
  "@jest/globals": "^29.5.0",
47
- "@langchain/core": "0.3.55",
46
+ "@langchain/core": "workspace:*",
48
47
  "@langchain/scripts": ">=0.1.0 <0.2.0",
49
48
  "@langchain/standard-tests": "0.0.0",
50
49
  "@swc/core": "^1.3.90",
@@ -68,7 +67,7 @@
68
67
  "rollup": "^4.5.2",
69
68
  "ts-jest": "^29.1.0",
70
69
  "typescript": "<5.2.0",
71
- "zod": "^3.22.4"
70
+ "zod": "^3.25.32"
72
71
  },
73
72
  "publishConfig": {
74
73
  "access": "public"
@@ -92,4 +91,4 @@
92
91
  "index.d.ts",
93
92
  "index.d.cts"
94
93
  ]
95
- }
94
+ }