@intrvls/langchain-google-genai 3.0.0-alpha.0

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/index.cjs ADDED
@@ -0,0 +1,1880 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _google_genai = require("@google/genai");
3
+ let _langchain_core_utils_env = require("@langchain/core/utils/env");
4
+ let _langchain_core_language_models_chat_models = require("@langchain/core/language_models/chat_models");
5
+ let _langchain_core_utils_types = require("@langchain/core/utils/types");
6
+ let _langchain_core_utils_json_schema = require("@langchain/core/utils/json_schema");
7
+ let _langchain_core_utils_standard_schema = require("@langchain/core/utils/standard_schema");
8
+ let _langchain_core_messages = require("@langchain/core/messages");
9
+ let _langchain_core_outputs = require("@langchain/core/outputs");
10
+ let _langchain_core_utils_function_calling = require("@langchain/core/utils/function_calling");
11
+ let _langchain_core_language_models_base = require("@langchain/core/language_models/base");
12
+ let uuid = require("uuid");
13
+ let _langchain_core_output_parsers = require("@langchain/core/output_parsers");
14
+ let _langchain_core_language_models_structured_output = require("@langchain/core/language_models/structured_output");
15
+ let _langchain_core_embeddings = require("@langchain/core/embeddings");
16
+ let _langchain_core_utils_chunk_array = require("@langchain/core/utils/chunk_array");
17
+ //#region src/utils/zod_to_genai_parameters.ts
18
+ function removeAdditionalProperties(obj) {
19
+ if (typeof obj === "object" && obj !== null) {
20
+ const newObj = { ...obj };
21
+ if ("additionalProperties" in newObj) delete newObj.additionalProperties;
22
+ if ("$schema" in newObj) delete newObj.$schema;
23
+ if ("strict" in newObj) delete newObj.strict;
24
+ for (const key in newObj) if (key in newObj) {
25
+ if (Array.isArray(newObj[key])) newObj[key] = newObj[key].map(removeAdditionalProperties);
26
+ else if (typeof newObj[key] === "object" && newObj[key] !== null) newObj[key] = removeAdditionalProperties(newObj[key]);
27
+ }
28
+ return newObj;
29
+ }
30
+ return obj;
31
+ }
32
+ function schemaToGenerativeAIParameters(schema) {
33
+ const { $schema, ...rest } = removeAdditionalProperties((0, _langchain_core_utils_types.isInteropZodSchema)(schema) || (0, _langchain_core_utils_standard_schema.isSerializableSchema)(schema) ? (0, _langchain_core_utils_json_schema.toJsonSchema)(schema) : schema);
34
+ return rest;
35
+ }
36
+ function jsonSchemaToGeminiParameters(schema) {
37
+ const { $schema, ...rest } = removeAdditionalProperties(schema);
38
+ return rest;
39
+ }
40
+ //#endregion
41
+ //#region src/utils/validate_schema.ts
42
+ function assertNoEmptyStringEnums(schema, toolName, path = []) {
43
+ if (schema == null || typeof schema !== "object") return;
44
+ const obj = schema;
45
+ if (Array.isArray(obj.enum)) {
46
+ if (obj.enum.some((v) => v === "")) {
47
+ const pathStr = path.length ? ` at path "${path.join(".")}"` : "";
48
+ const toolStr = toolName ? ` in tool "${toolName}"` : "";
49
+ throw new Error(`Invalid enum: empty string not allowed${toolStr}${pathStr}. Gemini API rejects empty strings in enums.`);
50
+ }
51
+ }
52
+ if (obj.type === "object" && obj.properties && typeof obj.properties === "object") for (const [prop, child] of Object.entries(obj.properties)) assertNoEmptyStringEnums(child, toolName, [...path, prop]);
53
+ if (obj.items) assertNoEmptyStringEnums(obj.items, toolName, [...path, "[]"]);
54
+ for (const k of [
55
+ "anyOf",
56
+ "oneOf",
57
+ "allOf"
58
+ ]) {
59
+ const arr = obj[k];
60
+ if (Array.isArray(arr)) arr.forEach((child, i) => assertNoEmptyStringEnums(child, toolName, [...path, `${k}[${i}]`]));
61
+ }
62
+ if (obj.additionalProperties && typeof obj.additionalProperties === "object") assertNoEmptyStringEnums(obj.additionalProperties, toolName, [...path, "additionalProperties"]);
63
+ }
64
+ //#endregion
65
+ //#region src/utils/common.ts
66
+ const _FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY = "__gemini_function_call_thought_signatures__";
67
+ const DUMMY_SIGNATURE = "ErYCCrMCAdHtim9kOoOkrPiCNVsmlpMIKd7ZMxgiFbVQOkgp7nlLcDMzVsZwIzvuT7nQROivoXA72ccC2lSDvR0Gh7dkWaGuj7ctv6t7ZceHnecx0QYa+ix8tYpRfjhyWozQ49lWiws6+YGjCt10KRTyWsZ2h6O7iHTYJwKIRwGUHRKy/qK/6kFxJm5ML00gLq4D8s5Z6DBpp2ZlR+uF4G8jJgeWQgyHWVdx2wGYElaceVAc66tZdPQRdOHpWtgYSI1YdaXgVI8KHY3/EfNc2YqqMIulvkDBAnuMhkAjV9xmBa54Tq+ih3Im4+r3DzqhGqYdsSkhS0kZMwte4Hjs65dZzCw9lANxIqYi1DJ639WNPYihp/DCJCos7o+/EeSPJaio5sgWDyUnMGkY1atsJZ+m7pj7DD5tvQ==";
68
+ const iife = (fn) => fn();
69
+ function getMessageAuthor(message) {
70
+ if (_langchain_core_messages.ChatMessage.isInstance(message)) return message.role;
71
+ return message.type;
72
+ }
73
+ /**
74
+ * Maps a message type to a Google Generative AI chat author.
75
+ * @param message The message to map.
76
+ * @param model The model to use for mapping.
77
+ * @returns The message type mapped to a Google Generative AI chat author.
78
+ */
79
+ function convertAuthorToRole(author) {
80
+ switch (author) {
81
+ /**
82
+ * Note: Gemini currently is not supporting system messages
83
+ * we will convert them to human messages and merge with following
84
+ * */
85
+ case "supervisor":
86
+ case "ai":
87
+ case "model": return "model";
88
+ case "system": return "system";
89
+ case "human": return "user";
90
+ case "tool":
91
+ case "function": return "function";
92
+ default: throw new Error(`Unknown / unsupported author: ${author}`);
93
+ }
94
+ }
95
+ function messageContentMedia(content) {
96
+ if ("mimeType" in content && "data" in content) return { inlineData: {
97
+ mimeType: content.mimeType,
98
+ data: content.data
99
+ } };
100
+ if ("mimeType" in content && "fileUri" in content) return { fileData: {
101
+ mimeType: content.mimeType,
102
+ fileUri: content.fileUri
103
+ } };
104
+ throw new Error("Invalid media content");
105
+ }
106
+ function inferToolNameFromPreviousMessages(message, previousMessages) {
107
+ return previousMessages.map((msg) => {
108
+ if ((0, _langchain_core_messages.isAIMessage)(msg)) return msg.tool_calls ?? [];
109
+ return [];
110
+ }).flat().find((toolCall) => {
111
+ return toolCall.id === message.tool_call_id;
112
+ })?.name;
113
+ }
114
+ /**
115
+ * Converts a ContentBlock.Multimodal block (image, video, audio, file)
116
+ * to the appropriate Google Generative AI Part format.
117
+ *
118
+ * Handles three data record variants:
119
+ * - DataRecordBase64: has `data` property → InlineDataPart
120
+ * - DataRecordUrl: has `url` property → FileDataPart (or InlineDataPart for data: URLs)
121
+ * - DataRecordFileId: has `fileId` property → not directly supported, throws
122
+ */
123
+ function _multimodalContentBlockToPart(block, defaultMimeType) {
124
+ if ("data" in block && block.data !== void 0) {
125
+ const data = block.data instanceof Uint8Array ? btoa(String.fromCharCode(...block.data)) : block.data;
126
+ return { inlineData: {
127
+ mimeType: block.mimeType || defaultMimeType,
128
+ data
129
+ } };
130
+ }
131
+ if ("url" in block && block.url !== void 0) {
132
+ const parsed = (0, _langchain_core_messages.parseBase64DataUrl)({ dataUrl: block.url });
133
+ if (parsed) return { inlineData: {
134
+ mimeType: parsed.mime_type,
135
+ data: parsed.data
136
+ } };
137
+ return { fileData: {
138
+ mimeType: block.mimeType || defaultMimeType,
139
+ fileUri: block.url
140
+ } };
141
+ }
142
+ if ("fileId" in block && block.fileId !== void 0) throw new Error("ContentBlock.Multimodal fileId is not supported by Google Generative AI. Use a URL or base64 data instead.");
143
+ throw new Error(`Invalid multimodal content block: must have "data", "url", or "fileId" property. Received: ${JSON.stringify(block)}`);
144
+ }
145
+ function _getStandardContentBlockConverter(isMultimodalModel) {
146
+ return {
147
+ providerName: "Google Gemini",
148
+ fromStandardTextBlock(block) {
149
+ return { text: block.text };
150
+ },
151
+ fromStandardImageBlock(block) {
152
+ if (!isMultimodalModel) throw new Error("This model does not support images");
153
+ if (block.source_type === "url") {
154
+ const data = (0, _langchain_core_messages.parseBase64DataUrl)({ dataUrl: block.url });
155
+ if (data) return { inlineData: {
156
+ mimeType: data.mime_type,
157
+ data: data.data
158
+ } };
159
+ else return { fileData: {
160
+ mimeType: block.mime_type ?? "",
161
+ fileUri: block.url
162
+ } };
163
+ }
164
+ if (block.source_type === "base64") return { inlineData: {
165
+ mimeType: block.mime_type ?? "",
166
+ data: block.data
167
+ } };
168
+ throw new Error(`Unsupported source type: ${block.source_type}`);
169
+ },
170
+ fromStandardAudioBlock(block) {
171
+ if (!isMultimodalModel) throw new Error("This model does not support audio");
172
+ if (block.source_type === "url") {
173
+ const data = (0, _langchain_core_messages.parseBase64DataUrl)({ dataUrl: block.url });
174
+ if (data) return { inlineData: {
175
+ mimeType: data.mime_type,
176
+ data: data.data
177
+ } };
178
+ else return { fileData: {
179
+ mimeType: block.mime_type ?? "",
180
+ fileUri: block.url
181
+ } };
182
+ }
183
+ if (block.source_type === "base64") return { inlineData: {
184
+ mimeType: block.mime_type ?? "",
185
+ data: block.data
186
+ } };
187
+ throw new Error(`Unsupported source type: ${block.source_type}`);
188
+ },
189
+ fromStandardFileBlock(block) {
190
+ if (!isMultimodalModel) throw new Error("This model does not support files");
191
+ if (block.source_type === "text") return { text: block.text };
192
+ if (block.source_type === "url") {
193
+ const data = (0, _langchain_core_messages.parseBase64DataUrl)({ dataUrl: block.url });
194
+ if (data) return { inlineData: {
195
+ mimeType: data.mime_type,
196
+ data: data.data
197
+ } };
198
+ else return { fileData: {
199
+ mimeType: block.mime_type ?? "",
200
+ fileUri: block.url
201
+ } };
202
+ }
203
+ if (block.source_type === "base64") return { inlineData: {
204
+ mimeType: block.mime_type ?? "",
205
+ data: block.data
206
+ } };
207
+ throw new Error(`Unsupported source type: ${block.source_type}`);
208
+ }
209
+ };
210
+ }
211
+ function _convertLangChainContentToPart(content, isMultimodalModel) {
212
+ if ((0, _langchain_core_messages.isDataContentBlock)(content)) return (0, _langchain_core_messages.convertToProviderContentBlock)(content, _getStandardContentBlockConverter(isMultimodalModel));
213
+ if (content.type === "text") return { text: content.text };
214
+ else if (content.type === "executableCode") return { executableCode: content.executableCode };
215
+ else if (content.type === "codeExecutionResult") return { codeExecutionResult: content.codeExecutionResult };
216
+ else if (content.type === "image_url") {
217
+ if (!isMultimodalModel) throw new Error(`This model does not support images`);
218
+ let source;
219
+ if (typeof content.image_url === "string") source = content.image_url;
220
+ else if (typeof content.image_url === "object" && "url" in content.image_url) source = content.image_url.url;
221
+ else throw new Error("Please provide image as base64 encoded data URL");
222
+ const [dm, data] = source.split(",");
223
+ if (!dm.startsWith("data:")) throw new Error("Please provide image as base64 encoded data URL");
224
+ const [mimeType, encoding] = dm.replace(/^data:/, "").split(";");
225
+ if (encoding !== "base64") throw new Error("Please provide image as base64 encoded data URL");
226
+ return { inlineData: {
227
+ data,
228
+ mimeType
229
+ } };
230
+ } else if (content.type === "media") return messageContentMedia(content);
231
+ else if (content.type === "image") return _multimodalContentBlockToPart(content, "image/png");
232
+ else if (content.type === "video") return _multimodalContentBlockToPart(content, "video/mp4");
233
+ else if (content.type === "audio") return _multimodalContentBlockToPart(content, "audio/mpeg");
234
+ else if (content.type === "file") return _multimodalContentBlockToPart(content, "application/octet-stream");
235
+ else if (content.type === "text-plain") {
236
+ if ("text" in content && typeof content.text === "string") return { text: content.text };
237
+ return _multimodalContentBlockToPart(content, "text/plain");
238
+ } else if (content.type === "tool_use") return { functionCall: {
239
+ name: content.name,
240
+ args: content.input
241
+ } };
242
+ else if (content.type === "tool_call") return { functionCall: {
243
+ name: content.name,
244
+ args: content.args
245
+ } };
246
+ else if (content.type?.includes("/") && content.type.split("/").length === 2 && "data" in content && typeof content.data === "string") return { inlineData: {
247
+ mimeType: content.type,
248
+ data: content.data
249
+ } };
250
+ else if (content.type === "thinking") {
251
+ const thinkingContent = content;
252
+ return {
253
+ text: thinkingContent.thinking,
254
+ thought: true,
255
+ ...thinkingContent.signature ? { thoughtSignature: thinkingContent.signature } : {}
256
+ };
257
+ } else if ("functionCall" in content) return;
258
+ else if ("type" in content) throw new Error(`Unknown content type ${content.type}`);
259
+ else throw new Error(`Unknown content ${JSON.stringify(content)}`);
260
+ }
261
+ function convertMessageContentToParts(message, isMultimodalModel, previousMessages, model) {
262
+ if ((0, _langchain_core_messages.isToolMessage)(message)) {
263
+ const messageName = message.name ?? inferToolNameFromPreviousMessages(message, previousMessages);
264
+ if (messageName === void 0) 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.`);
265
+ const result = Array.isArray(message.content) ? message.content.map((c) => _convertLangChainContentToPart(c, isMultimodalModel)).filter((p) => p !== void 0) : message.content;
266
+ if (message.status === "error") return [{ functionResponse: {
267
+ name: messageName,
268
+ response: { error: { details: result } }
269
+ } }];
270
+ return [{ functionResponse: {
271
+ name: messageName,
272
+ response: { result }
273
+ } }];
274
+ }
275
+ let functionCalls = [];
276
+ const messageParts = [];
277
+ if (typeof message.content === "string" && message.content) messageParts.push({ text: message.content });
278
+ if (Array.isArray(message.content)) messageParts.push(...message.content.map((c) => _convertLangChainContentToPart(c, isMultimodalModel)).filter((p) => p !== void 0));
279
+ const functionThoughtSignatures = message.additional_kwargs?.[_FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY];
280
+ if ((0, _langchain_core_messages.isAIMessage)(message) && message.tool_calls?.length) functionCalls = message.tool_calls.map((tc) => {
281
+ const thoughtSignature = iife(() => {
282
+ if (tc.id) {
283
+ const signature = functionThoughtSignatures?.[tc.id];
284
+ if (signature) return signature;
285
+ }
286
+ if (model?.includes("gemini-3")) return DUMMY_SIGNATURE;
287
+ return "";
288
+ });
289
+ return {
290
+ functionCall: {
291
+ name: tc.name,
292
+ args: tc.args
293
+ },
294
+ ...thoughtSignature ? { thoughtSignature } : {}
295
+ };
296
+ });
297
+ return [...messageParts, ...functionCalls];
298
+ }
299
+ function convertBaseMessagesToContent(messages, isMultimodalModel, convertSystemMessageToHumanContent = false, model) {
300
+ return messages.reduce((acc, message, index) => {
301
+ if (!(0, _langchain_core_messages.isBaseMessage)(message)) throw new Error("Unsupported message input");
302
+ const author = getMessageAuthor(message);
303
+ if (author === "system" && index !== 0) throw new Error("System message should be the first one");
304
+ const role = convertAuthorToRole(author);
305
+ const prevContent = acc.content[acc.content.length];
306
+ if (!acc.mergeWithPreviousContent && prevContent && prevContent.role === role) throw new Error("Google Generative AI requires alternate messages between authors");
307
+ const parts = convertMessageContentToParts(message, isMultimodalModel, messages.slice(0, index), model);
308
+ if (acc.mergeWithPreviousContent) {
309
+ const prevContent = acc.content[acc.content.length - 1];
310
+ if (!prevContent) throw new Error("There was a problem parsing your system message. Please try a prompt without one.");
311
+ prevContent.parts = [...prevContent.parts ?? [], ...parts];
312
+ return {
313
+ mergeWithPreviousContent: false,
314
+ content: acc.content
315
+ };
316
+ }
317
+ let actualRole = role;
318
+ if (actualRole === "function" || actualRole === "system" && !convertSystemMessageToHumanContent) actualRole = "user";
319
+ const content = {
320
+ role: actualRole,
321
+ parts
322
+ };
323
+ return {
324
+ mergeWithPreviousContent: author === "system" && !convertSystemMessageToHumanContent,
325
+ content: [...acc.content, content]
326
+ };
327
+ }, {
328
+ content: [],
329
+ mergeWithPreviousContent: false
330
+ }).content;
331
+ }
332
+ function mapGenerateContentResultToChatResult(response, extra) {
333
+ if (!response.candidates || response.candidates.length === 0 || !response.candidates[0]) return {
334
+ generations: [],
335
+ llmOutput: { filters: response.promptFeedback }
336
+ };
337
+ const [candidate] = response.candidates;
338
+ const { content: candidateContent, ...generationInfo } = candidate;
339
+ const functionCalls = candidateContent?.parts?.reduce((acc, p) => {
340
+ if ("functionCall" in p && p.functionCall) acc.push({
341
+ ...p,
342
+ id: "id" in p.functionCall && typeof p.functionCall.id === "string" ? p.functionCall.id : (0, uuid.v4)()
343
+ });
344
+ return acc;
345
+ }, []);
346
+ let content;
347
+ const parts = candidateContent?.parts;
348
+ if (Array.isArray(parts) && parts.length === 1 && "text" in parts[0] && parts[0].text && !parts[0].thought) content = parts[0].text;
349
+ else if (Array.isArray(parts) && parts.length > 0) content = parts.map((p) => {
350
+ if (p.thought && "text" in p && p.text) return {
351
+ type: "thinking",
352
+ thinking: p.text,
353
+ ...p.thoughtSignature ? { signature: p.thoughtSignature } : {}
354
+ };
355
+ else if ("text" in p) return {
356
+ type: "text",
357
+ text: p.text
358
+ };
359
+ else if ("inlineData" in p) return {
360
+ type: "inlineData",
361
+ inlineData: p.inlineData
362
+ };
363
+ else if ("functionCall" in p) return {
364
+ type: "functionCall",
365
+ functionCall: p.functionCall
366
+ };
367
+ else if ("functionResponse" in p) return {
368
+ type: "functionResponse",
369
+ functionResponse: p.functionResponse
370
+ };
371
+ else if ("fileData" in p) return {
372
+ type: "fileData",
373
+ fileData: p.fileData
374
+ };
375
+ else if ("executableCode" in p) return {
376
+ type: "executableCode",
377
+ executableCode: p.executableCode
378
+ };
379
+ else if ("codeExecutionResult" in p) return {
380
+ type: "codeExecutionResult",
381
+ codeExecutionResult: p.codeExecutionResult
382
+ };
383
+ return p;
384
+ });
385
+ else content = [];
386
+ const functionThoughtSignatures = functionCalls?.reduce((acc, fc) => {
387
+ if ("thoughtSignature" in fc && typeof fc.thoughtSignature === "string") acc[fc.id] = fc.thoughtSignature;
388
+ return acc;
389
+ }, {});
390
+ let text = "";
391
+ if (typeof content === "string") text = content;
392
+ else if (Array.isArray(content) && content.length > 0) text = content.find((b) => "text" in b)?.text ?? text;
393
+ return {
394
+ generations: [{
395
+ text,
396
+ message: new _langchain_core_messages.AIMessage({
397
+ content: content ?? "",
398
+ tool_calls: functionCalls?.map((fc) => ({
399
+ type: "tool_call",
400
+ id: fc.id,
401
+ name: fc.functionCall?.name ?? "",
402
+ args: fc.functionCall?.args ?? {}
403
+ })),
404
+ additional_kwargs: {
405
+ ...generationInfo,
406
+ [_FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY]: functionThoughtSignatures
407
+ },
408
+ response_metadata: { model_provider: "google-genai" },
409
+ usage_metadata: extra?.usageMetadata
410
+ }),
411
+ generationInfo
412
+ }],
413
+ llmOutput: { tokenUsage: {
414
+ promptTokens: extra?.usageMetadata?.input_tokens,
415
+ completionTokens: extra?.usageMetadata?.output_tokens,
416
+ totalTokens: extra?.usageMetadata?.total_tokens
417
+ } }
418
+ };
419
+ }
420
+ function convertResponseContentToChatGenerationChunk(response, extra) {
421
+ if (!response.candidates || response.candidates.length === 0) return null;
422
+ const [candidate] = response.candidates;
423
+ const { content: candidateContent, ...generationInfo } = candidate;
424
+ const functionCalls = candidateContent?.parts?.reduce((acc, p) => {
425
+ if ("functionCall" in p && p.functionCall) acc.push({
426
+ ...p,
427
+ id: "id" in p.functionCall && typeof p.functionCall.id === "string" ? p.functionCall.id : (0, uuid.v4)()
428
+ });
429
+ return acc;
430
+ }, []);
431
+ let content;
432
+ const streamParts = candidateContent?.parts;
433
+ if (Array.isArray(streamParts) && streamParts.every((p) => "text" in p && !p.thought)) content = streamParts.map((p) => p.text).join("");
434
+ else if (Array.isArray(streamParts)) content = streamParts.map((p) => {
435
+ if (p.thought && "text" in p && p.text) return {
436
+ type: "thinking",
437
+ thinking: p.text,
438
+ ...p.thoughtSignature ? { signature: p.thoughtSignature } : {}
439
+ };
440
+ else if ("text" in p) return {
441
+ type: "text",
442
+ text: p.text
443
+ };
444
+ else if ("inlineData" in p) return {
445
+ type: "inlineData",
446
+ inlineData: p.inlineData
447
+ };
448
+ else if ("functionCall" in p) return {
449
+ type: "functionCall",
450
+ functionCall: p.functionCall
451
+ };
452
+ else if ("functionResponse" in p) return {
453
+ type: "functionResponse",
454
+ functionResponse: p.functionResponse
455
+ };
456
+ else if ("fileData" in p) return {
457
+ type: "fileData",
458
+ fileData: p.fileData
459
+ };
460
+ else if ("executableCode" in p) return {
461
+ type: "executableCode",
462
+ executableCode: p.executableCode
463
+ };
464
+ else if ("codeExecutionResult" in p) return {
465
+ type: "codeExecutionResult",
466
+ codeExecutionResult: p.codeExecutionResult
467
+ };
468
+ return p;
469
+ });
470
+ else content = [];
471
+ let text = "";
472
+ if (content && typeof content === "string") text = content;
473
+ else if (Array.isArray(content)) text = content.find((b) => "text" in b)?.text ?? "";
474
+ const toolCallChunks = [];
475
+ if (functionCalls) toolCallChunks.push(...functionCalls.map((fc) => ({
476
+ type: "tool_call_chunk",
477
+ id: fc.id,
478
+ name: fc.functionCall?.name,
479
+ args: JSON.stringify(fc.functionCall?.args)
480
+ })));
481
+ const functionThoughtSignatures = functionCalls?.reduce((acc, fc) => {
482
+ if ("thoughtSignature" in fc && typeof fc.thoughtSignature === "string") acc[fc.id] = fc.thoughtSignature;
483
+ return acc;
484
+ }, {});
485
+ return new _langchain_core_outputs.ChatGenerationChunk({
486
+ text,
487
+ message: new _langchain_core_messages.AIMessageChunk({
488
+ content: content || "",
489
+ name: !candidateContent ? void 0 : candidateContent.role,
490
+ tool_call_chunks: toolCallChunks,
491
+ additional_kwargs: { [_FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY]: functionThoughtSignatures },
492
+ response_metadata: { model_provider: "google-genai" },
493
+ usage_metadata: extra.usageMetadata
494
+ }),
495
+ generationInfo
496
+ });
497
+ }
498
+ function convertToGenerativeAITools(tools) {
499
+ if (tools.every((tool) => "functionDeclarations" in tool && Array.isArray(tool.functionDeclarations))) return tools;
500
+ return [{ functionDeclarations: tools.map((tool) => {
501
+ if ((0, _langchain_core_utils_function_calling.isLangChainTool)(tool)) {
502
+ const jsonSchema = schemaToGenerativeAIParameters(tool.schema);
503
+ if (jsonSchema.type === "object" && Object.keys(jsonSchema.properties ?? {}).length === 0) return {
504
+ name: tool.name,
505
+ description: tool.description
506
+ };
507
+ assertNoEmptyStringEnums(jsonSchema, tool.name);
508
+ return {
509
+ name: tool.name,
510
+ description: tool.description,
511
+ parameters: jsonSchema
512
+ };
513
+ }
514
+ if ((0, _langchain_core_language_models_base.isOpenAITool)(tool)) {
515
+ const params = jsonSchemaToGeminiParameters(tool.function.parameters);
516
+ assertNoEmptyStringEnums(params, tool.function.name);
517
+ return {
518
+ name: tool.function.name,
519
+ description: tool.function.description ?? `A function available to call.`,
520
+ parameters: params
521
+ };
522
+ }
523
+ return tool;
524
+ }) }];
525
+ }
526
+ function convertUsageMetadata(usageMetadata, model) {
527
+ const reasoningTokens = usageMetadata?.thoughtsTokenCount ?? 0;
528
+ const output = {
529
+ input_tokens: usageMetadata?.promptTokenCount ?? 0,
530
+ output_tokens: (usageMetadata?.candidatesTokenCount ?? 0) + reasoningTokens,
531
+ total_tokens: usageMetadata?.totalTokenCount ?? 0
532
+ };
533
+ if (reasoningTokens) output.output_token_details = {
534
+ ...output.output_token_details,
535
+ reasoning: reasoningTokens
536
+ };
537
+ if (usageMetadata?.cachedContentTokenCount) {
538
+ output.input_token_details ??= {};
539
+ output.input_token_details.cache_read = usageMetadata.cachedContentTokenCount;
540
+ }
541
+ if (model.startsWith("gemini-3") && model.includes("pro")) {
542
+ const over200k = Math.max(0, (usageMetadata?.promptTokenCount ?? 0) - 2e5);
543
+ const cachedOver200k = Math.max(0, (usageMetadata?.cachedContentTokenCount ?? 0) - 2e5);
544
+ if (over200k) output.input_token_details = {
545
+ ...output.input_token_details,
546
+ over_200k: over200k
547
+ };
548
+ if (cachedOver200k) output.input_token_details = {
549
+ ...output.input_token_details,
550
+ cache_read_over_200k: cachedOver200k
551
+ };
552
+ }
553
+ return output;
554
+ }
555
+ //#endregion
556
+ //#region src/output_parsers.ts
557
+ var GoogleGenerativeAIToolsOutputParser = class extends _langchain_core_output_parsers.BaseLLMOutputParser {
558
+ static lc_name() {
559
+ return "GoogleGenerativeAIToolsOutputParser";
560
+ }
561
+ lc_namespace = [
562
+ "langchain",
563
+ "google_genai",
564
+ "output_parsers"
565
+ ];
566
+ returnId = false;
567
+ /** The type of tool calls to return. */
568
+ keyName;
569
+ /** Whether to return only the first tool call. */
570
+ returnSingle = false;
571
+ zodSchema;
572
+ serializableSchema;
573
+ constructor(params) {
574
+ super(params);
575
+ this.keyName = params.keyName;
576
+ this.returnSingle = params.returnSingle ?? this.returnSingle;
577
+ this.zodSchema = params.zodSchema;
578
+ this.serializableSchema = params.serializableSchema;
579
+ }
580
+ async _validateResult(result) {
581
+ if (this.serializableSchema !== void 0) {
582
+ const validated = await this.serializableSchema["~standard"].validate(result);
583
+ if (validated.issues) throw new _langchain_core_output_parsers.OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(validated.issues)}`, JSON.stringify(result, null, 2));
584
+ return validated.value;
585
+ }
586
+ if (this.zodSchema === void 0) return result;
587
+ const zodParsedResult = await (0, _langchain_core_utils_types.interopSafeParseAsync)(this.zodSchema, result);
588
+ if (zodParsedResult.success) return zodParsedResult.data;
589
+ else throw new _langchain_core_output_parsers.OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(zodParsedResult.error.issues)}`, JSON.stringify(result, null, 2));
590
+ }
591
+ async parseResult(generations) {
592
+ const tools = generations.flatMap((generation) => {
593
+ const { message } = generation;
594
+ if (!("tool_calls" in message) || !Array.isArray(message.tool_calls)) return [];
595
+ return message.tool_calls;
596
+ });
597
+ if (tools[0] === void 0) throw new Error("No parseable tool calls provided to GoogleGenerativeAIToolsOutputParser.");
598
+ const [tool] = tools;
599
+ return await this._validateResult(tool.args);
600
+ }
601
+ };
602
+ //#endregion
603
+ //#region src/utils/tools.ts
604
+ function convertToolsToGenAI(tools, extra) {
605
+ const genAITools = processTools(tools);
606
+ return {
607
+ tools: genAITools,
608
+ toolConfig: createToolConfig(genAITools, extra)
609
+ };
610
+ }
611
+ function processTools(tools) {
612
+ let functionDeclarationTools = [];
613
+ const genAITools = [];
614
+ tools.forEach((tool) => {
615
+ if ((0, _langchain_core_utils_function_calling.isLangChainTool)(tool)) {
616
+ const [convertedTool] = convertToGenerativeAITools([tool]);
617
+ if (convertedTool.functionDeclarations) functionDeclarationTools.push(...convertedTool.functionDeclarations);
618
+ } else if ((0, _langchain_core_language_models_base.isOpenAITool)(tool)) {
619
+ const { functionDeclarations } = convertOpenAIToolToGenAI(tool);
620
+ if (functionDeclarations) functionDeclarationTools.push(...functionDeclarations);
621
+ else throw new Error("Failed to convert OpenAI structured tool to GenerativeAI tool");
622
+ } else genAITools.push(normalizeGenAITool(tool));
623
+ });
624
+ if (genAITools.find((t) => "functionDeclarations" in t)) return genAITools.map((tool) => {
625
+ if (functionDeclarationTools?.length > 0 && "functionDeclarations" in tool) {
626
+ const newTool = { functionDeclarations: [...tool.functionDeclarations || [], ...functionDeclarationTools] };
627
+ functionDeclarationTools = [];
628
+ return newTool;
629
+ }
630
+ return tool;
631
+ });
632
+ return [...genAITools, ...functionDeclarationTools.length > 0 ? [{ functionDeclarations: functionDeclarationTools }] : []];
633
+ }
634
+ /**
635
+ * Current Gemini models (2.x and newer) removed the legacy
636
+ * `googleSearchRetrieval` tool (with its `dynamicRetrievalConfig`) and reject
637
+ * it with `google_search_retrieval is not supported. Please use google_search
638
+ * tool instead.`. Transparently rewrite it to the `googleSearch` tool so
639
+ * existing code keeps working against the newest models.
640
+ */
641
+ function normalizeGenAITool(tool) {
642
+ if (tool && "googleSearchRetrieval" in tool && !("googleSearch" in tool)) {
643
+ const { googleSearchRetrieval, ...rest } = tool;
644
+ return {
645
+ ...rest,
646
+ googleSearch: {}
647
+ };
648
+ }
649
+ return tool;
650
+ }
651
+ function convertOpenAIToolToGenAI(tool) {
652
+ return { functionDeclarations: [{
653
+ name: tool.function.name,
654
+ description: tool.function.description,
655
+ parameters: removeAdditionalProperties(tool.function.parameters)
656
+ }] };
657
+ }
658
+ function createToolConfig(genAITools, extra) {
659
+ if (!genAITools.length || !extra) return void 0;
660
+ const { toolChoice, allowedFunctionNames } = extra;
661
+ const modeMap = {
662
+ any: _google_genai.FunctionCallingConfigMode.ANY,
663
+ auto: _google_genai.FunctionCallingConfigMode.AUTO,
664
+ none: _google_genai.FunctionCallingConfigMode.NONE
665
+ };
666
+ if (toolChoice && [
667
+ "any",
668
+ "auto",
669
+ "none"
670
+ ].includes(toolChoice)) return { functionCallingConfig: {
671
+ mode: modeMap[toolChoice] ?? _google_genai.FunctionCallingConfigMode.MODE_UNSPECIFIED,
672
+ allowedFunctionNames
673
+ } };
674
+ if (typeof toolChoice === "string" || allowedFunctionNames) return { functionCallingConfig: {
675
+ mode: _google_genai.FunctionCallingConfigMode.ANY,
676
+ allowedFunctionNames: [...allowedFunctionNames ?? [], ...toolChoice && typeof toolChoice === "string" ? [toolChoice] : []]
677
+ } };
678
+ }
679
+ //#endregion
680
+ //#region src/profiles.ts
681
+ const PROFILES = {
682
+ "gemini-embedding-001": {
683
+ maxInputTokens: 2048,
684
+ imageInputs: false,
685
+ audioInputs: false,
686
+ pdfInputs: false,
687
+ videoInputs: false,
688
+ maxOutputTokens: 3072,
689
+ reasoningOutput: false,
690
+ imageOutputs: false,
691
+ audioOutputs: false,
692
+ videoOutputs: false,
693
+ toolCalling: false,
694
+ structuredOutput: false
695
+ },
696
+ "gemini-2.5-flash-lite-preview-09-2025": {
697
+ maxInputTokens: 1048576,
698
+ imageInputs: true,
699
+ audioInputs: true,
700
+ pdfInputs: true,
701
+ videoInputs: true,
702
+ maxOutputTokens: 65536,
703
+ reasoningOutput: true,
704
+ imageOutputs: false,
705
+ audioOutputs: false,
706
+ videoOutputs: false,
707
+ toolCalling: true,
708
+ structuredOutput: true
709
+ },
710
+ "gemini-2.5-pro-preview-06-05": {
711
+ maxInputTokens: 1048576,
712
+ imageInputs: true,
713
+ audioInputs: true,
714
+ pdfInputs: true,
715
+ videoInputs: true,
716
+ maxOutputTokens: 65536,
717
+ reasoningOutput: true,
718
+ imageOutputs: false,
719
+ audioOutputs: false,
720
+ videoOutputs: false,
721
+ toolCalling: true,
722
+ structuredOutput: true
723
+ },
724
+ "gemini-2.5-flash-preview-04-17": {
725
+ maxInputTokens: 1048576,
726
+ imageInputs: true,
727
+ audioInputs: true,
728
+ pdfInputs: true,
729
+ videoInputs: true,
730
+ maxOutputTokens: 65536,
731
+ reasoningOutput: true,
732
+ imageOutputs: false,
733
+ audioOutputs: false,
734
+ videoOutputs: false,
735
+ toolCalling: true,
736
+ structuredOutput: false
737
+ },
738
+ "gemini-2.5-flash-preview-09-2025": {
739
+ maxInputTokens: 1048576,
740
+ imageInputs: true,
741
+ audioInputs: true,
742
+ pdfInputs: true,
743
+ videoInputs: true,
744
+ maxOutputTokens: 65536,
745
+ reasoningOutput: true,
746
+ imageOutputs: false,
747
+ audioOutputs: false,
748
+ videoOutputs: false,
749
+ toolCalling: true,
750
+ structuredOutput: true
751
+ },
752
+ "gemini-2.5-pro-preview-05-06": {
753
+ maxInputTokens: 1048576,
754
+ imageInputs: true,
755
+ audioInputs: true,
756
+ pdfInputs: true,
757
+ videoInputs: true,
758
+ maxOutputTokens: 65536,
759
+ reasoningOutput: true,
760
+ imageOutputs: false,
761
+ audioOutputs: false,
762
+ videoOutputs: false,
763
+ toolCalling: true,
764
+ structuredOutput: true
765
+ },
766
+ "gemini-2.5-flash-preview-05-20": {
767
+ maxInputTokens: 1048576,
768
+ imageInputs: true,
769
+ audioInputs: true,
770
+ pdfInputs: true,
771
+ videoInputs: true,
772
+ maxOutputTokens: 65536,
773
+ reasoningOutput: true,
774
+ imageOutputs: false,
775
+ audioOutputs: false,
776
+ videoOutputs: false,
777
+ toolCalling: true,
778
+ structuredOutput: true
779
+ },
780
+ "gemini-2.5-flash": {
781
+ maxInputTokens: 1048576,
782
+ imageInputs: true,
783
+ audioInputs: true,
784
+ pdfInputs: true,
785
+ videoInputs: true,
786
+ maxOutputTokens: 65536,
787
+ reasoningOutput: true,
788
+ imageOutputs: false,
789
+ audioOutputs: false,
790
+ videoOutputs: false,
791
+ toolCalling: true,
792
+ structuredOutput: true
793
+ },
794
+ "gemini-live-2.5-flash": {
795
+ maxInputTokens: 128e3,
796
+ imageInputs: true,
797
+ audioInputs: true,
798
+ pdfInputs: false,
799
+ videoInputs: true,
800
+ maxOutputTokens: 8e3,
801
+ reasoningOutput: true,
802
+ imageOutputs: false,
803
+ audioOutputs: true,
804
+ videoOutputs: false,
805
+ toolCalling: true,
806
+ structuredOutput: false
807
+ },
808
+ "gemini-3-flash-preview": {
809
+ maxInputTokens: 1048576,
810
+ imageInputs: true,
811
+ audioInputs: true,
812
+ pdfInputs: true,
813
+ videoInputs: true,
814
+ maxOutputTokens: 65536,
815
+ reasoningOutput: true,
816
+ imageOutputs: false,
817
+ audioOutputs: false,
818
+ videoOutputs: false,
819
+ toolCalling: true,
820
+ structuredOutput: true
821
+ },
822
+ "gemini-3.5-flash": {
823
+ maxInputTokens: 1048576,
824
+ imageInputs: true,
825
+ audioInputs: true,
826
+ pdfInputs: true,
827
+ videoInputs: true,
828
+ maxOutputTokens: 65536,
829
+ reasoningOutput: true,
830
+ imageOutputs: false,
831
+ audioOutputs: false,
832
+ videoOutputs: false,
833
+ toolCalling: true,
834
+ structuredOutput: true
835
+ },
836
+ "gemini-3.1-pro-preview": {
837
+ maxInputTokens: 1048576,
838
+ imageInputs: true,
839
+ audioInputs: true,
840
+ pdfInputs: true,
841
+ videoInputs: true,
842
+ maxOutputTokens: 65536,
843
+ reasoningOutput: true,
844
+ imageOutputs: false,
845
+ audioOutputs: false,
846
+ videoOutputs: false,
847
+ toolCalling: true,
848
+ structuredOutput: true
849
+ },
850
+ "gemini-3.1-flash-lite": {
851
+ maxInputTokens: 1048576,
852
+ imageInputs: true,
853
+ audioInputs: true,
854
+ pdfInputs: true,
855
+ videoInputs: true,
856
+ maxOutputTokens: 65536,
857
+ reasoningOutput: true,
858
+ imageOutputs: false,
859
+ audioOutputs: false,
860
+ videoOutputs: false,
861
+ toolCalling: true,
862
+ structuredOutput: true
863
+ },
864
+ "gemini-3.1-flash-lite-preview": {
865
+ maxInputTokens: 1048576,
866
+ imageInputs: true,
867
+ audioInputs: true,
868
+ pdfInputs: true,
869
+ videoInputs: true,
870
+ maxOutputTokens: 65536,
871
+ reasoningOutput: true,
872
+ imageOutputs: false,
873
+ audioOutputs: false,
874
+ videoOutputs: false,
875
+ toolCalling: true,
876
+ structuredOutput: true
877
+ },
878
+ "gemini-pro-latest": {
879
+ maxInputTokens: 1048576,
880
+ imageInputs: true,
881
+ audioInputs: true,
882
+ pdfInputs: true,
883
+ videoInputs: true,
884
+ maxOutputTokens: 65536,
885
+ reasoningOutput: true,
886
+ imageOutputs: false,
887
+ audioOutputs: false,
888
+ videoOutputs: false,
889
+ toolCalling: true,
890
+ structuredOutput: true
891
+ },
892
+ "gemini-live-2.5-flash-preview-native-audio": {
893
+ maxInputTokens: 131072,
894
+ imageInputs: false,
895
+ audioInputs: true,
896
+ pdfInputs: false,
897
+ videoInputs: true,
898
+ maxOutputTokens: 65536,
899
+ reasoningOutput: true,
900
+ imageOutputs: false,
901
+ audioOutputs: true,
902
+ videoOutputs: false,
903
+ toolCalling: true,
904
+ structuredOutput: false
905
+ },
906
+ "gemini-2.5-flash-lite": {
907
+ maxInputTokens: 1048576,
908
+ imageInputs: true,
909
+ audioInputs: true,
910
+ pdfInputs: true,
911
+ videoInputs: true,
912
+ maxOutputTokens: 65536,
913
+ reasoningOutput: true,
914
+ imageOutputs: false,
915
+ audioOutputs: false,
916
+ videoOutputs: false,
917
+ toolCalling: true,
918
+ structuredOutput: true
919
+ },
920
+ "gemini-2.5-flash-preview-tts": {
921
+ maxInputTokens: 8e3,
922
+ imageInputs: false,
923
+ audioInputs: false,
924
+ pdfInputs: false,
925
+ videoInputs: false,
926
+ maxOutputTokens: 16e3,
927
+ reasoningOutput: false,
928
+ imageOutputs: false,
929
+ audioOutputs: true,
930
+ videoOutputs: false,
931
+ toolCalling: false,
932
+ structuredOutput: false
933
+ },
934
+ "gemini-flash-latest": {
935
+ maxInputTokens: 1048576,
936
+ imageInputs: true,
937
+ audioInputs: true,
938
+ pdfInputs: true,
939
+ videoInputs: true,
940
+ maxOutputTokens: 65536,
941
+ reasoningOutput: true,
942
+ imageOutputs: false,
943
+ audioOutputs: false,
944
+ videoOutputs: false,
945
+ toolCalling: true,
946
+ structuredOutput: true
947
+ },
948
+ "gemini-2.5-flash-lite-preview-06-17": {
949
+ maxInputTokens: 1048576,
950
+ imageInputs: true,
951
+ audioInputs: true,
952
+ pdfInputs: true,
953
+ videoInputs: true,
954
+ maxOutputTokens: 65536,
955
+ reasoningOutput: true,
956
+ imageOutputs: false,
957
+ audioOutputs: false,
958
+ videoOutputs: false,
959
+ toolCalling: true,
960
+ structuredOutput: false
961
+ },
962
+ "gemini-2.5-flash-image": {
963
+ maxInputTokens: 32768,
964
+ imageInputs: true,
965
+ audioInputs: false,
966
+ pdfInputs: false,
967
+ videoInputs: false,
968
+ maxOutputTokens: 32768,
969
+ reasoningOutput: true,
970
+ imageOutputs: true,
971
+ audioOutputs: false,
972
+ videoOutputs: false,
973
+ toolCalling: false,
974
+ structuredOutput: false
975
+ },
976
+ "gemini-2.5-pro-preview-tts": {
977
+ maxInputTokens: 8e3,
978
+ imageInputs: false,
979
+ audioInputs: false,
980
+ pdfInputs: false,
981
+ videoInputs: false,
982
+ maxOutputTokens: 16e3,
983
+ reasoningOutput: false,
984
+ imageOutputs: false,
985
+ audioOutputs: true,
986
+ videoOutputs: false,
987
+ toolCalling: false,
988
+ structuredOutput: false
989
+ },
990
+ "gemini-2.5-flash-image-preview": {
991
+ maxInputTokens: 32768,
992
+ imageInputs: true,
993
+ audioInputs: false,
994
+ pdfInputs: false,
995
+ videoInputs: false,
996
+ maxOutputTokens: 32768,
997
+ reasoningOutput: true,
998
+ imageOutputs: true,
999
+ audioOutputs: false,
1000
+ videoOutputs: false,
1001
+ toolCalling: false,
1002
+ structuredOutput: false
1003
+ },
1004
+ "gemini-1.5-flash-8b": {
1005
+ maxInputTokens: 1e6,
1006
+ imageInputs: true,
1007
+ audioInputs: true,
1008
+ pdfInputs: false,
1009
+ videoInputs: true,
1010
+ maxOutputTokens: 8192,
1011
+ reasoningOutput: false,
1012
+ imageOutputs: false,
1013
+ audioOutputs: false,
1014
+ videoOutputs: false,
1015
+ toolCalling: true,
1016
+ structuredOutput: false
1017
+ },
1018
+ "gemini-3-pro-preview": {
1019
+ maxInputTokens: 1e6,
1020
+ imageInputs: true,
1021
+ audioInputs: true,
1022
+ pdfInputs: true,
1023
+ videoInputs: true,
1024
+ maxOutputTokens: 64e3,
1025
+ reasoningOutput: true,
1026
+ imageOutputs: false,
1027
+ audioOutputs: false,
1028
+ videoOutputs: false,
1029
+ toolCalling: true,
1030
+ structuredOutput: true
1031
+ },
1032
+ "gemini-2.0-flash-lite": {
1033
+ maxInputTokens: 1048576,
1034
+ imageInputs: true,
1035
+ audioInputs: true,
1036
+ pdfInputs: true,
1037
+ videoInputs: true,
1038
+ maxOutputTokens: 8192,
1039
+ reasoningOutput: false,
1040
+ imageOutputs: false,
1041
+ audioOutputs: false,
1042
+ videoOutputs: false,
1043
+ toolCalling: true,
1044
+ structuredOutput: true
1045
+ },
1046
+ "gemini-1.5-flash": {
1047
+ maxInputTokens: 1e6,
1048
+ imageInputs: true,
1049
+ audioInputs: true,
1050
+ pdfInputs: false,
1051
+ videoInputs: true,
1052
+ maxOutputTokens: 8192,
1053
+ reasoningOutput: false,
1054
+ imageOutputs: false,
1055
+ audioOutputs: false,
1056
+ videoOutputs: false,
1057
+ toolCalling: true,
1058
+ structuredOutput: false
1059
+ },
1060
+ "gemini-flash-lite-latest": {
1061
+ maxInputTokens: 1048576,
1062
+ imageInputs: true,
1063
+ audioInputs: true,
1064
+ pdfInputs: true,
1065
+ videoInputs: true,
1066
+ maxOutputTokens: 65536,
1067
+ reasoningOutput: true,
1068
+ imageOutputs: false,
1069
+ audioOutputs: false,
1070
+ videoOutputs: false,
1071
+ toolCalling: true,
1072
+ structuredOutput: true
1073
+ },
1074
+ "gemini-2.5-pro": {
1075
+ maxInputTokens: 1048576,
1076
+ imageInputs: true,
1077
+ audioInputs: true,
1078
+ pdfInputs: true,
1079
+ videoInputs: true,
1080
+ maxOutputTokens: 65536,
1081
+ reasoningOutput: true,
1082
+ imageOutputs: false,
1083
+ audioOutputs: false,
1084
+ videoOutputs: false,
1085
+ toolCalling: true,
1086
+ structuredOutput: true
1087
+ },
1088
+ "gemini-2.0-flash": {
1089
+ maxInputTokens: 1048576,
1090
+ imageInputs: true,
1091
+ audioInputs: true,
1092
+ pdfInputs: true,
1093
+ videoInputs: true,
1094
+ maxOutputTokens: 8192,
1095
+ reasoningOutput: false,
1096
+ imageOutputs: false,
1097
+ audioOutputs: false,
1098
+ videoOutputs: false,
1099
+ toolCalling: true,
1100
+ structuredOutput: true
1101
+ },
1102
+ "gemini-1.5-pro": {
1103
+ maxInputTokens: 1e6,
1104
+ imageInputs: true,
1105
+ audioInputs: true,
1106
+ pdfInputs: false,
1107
+ videoInputs: true,
1108
+ maxOutputTokens: 8192,
1109
+ reasoningOutput: false,
1110
+ imageOutputs: false,
1111
+ audioOutputs: false,
1112
+ videoOutputs: false,
1113
+ toolCalling: true,
1114
+ structuredOutput: false
1115
+ }
1116
+ };
1117
+ //#endregion
1118
+ //#region src/chat_models.ts
1119
+ /**
1120
+ * Google Generative AI chat model integration.
1121
+ *
1122
+ * Setup:
1123
+ * Install `@intrvls/langchain-google-genai` and set an environment variable named `GOOGLE_API_KEY`.
1124
+ *
1125
+ * ```bash
1126
+ * npm install @intrvls/langchain-google-genai
1127
+ * export GOOGLE_API_KEY="your-api-key"
1128
+ * ```
1129
+ *
1130
+ * ## [Constructor args](https://api.js.langchain.com/classes/langchain_google_genai.ChatGoogleGenerativeAI.html#constructor)
1131
+ *
1132
+ * ## [Runtime args](https://api.js.langchain.com/interfaces/langchain_google_genai.GoogleGenerativeAIChatCallOptions.html)
1133
+ *
1134
+ * Runtime args can be passed as the second argument to any of the base runnable methods `.invoke`. `.stream`, `.batch`, etc.
1135
+ * They can also be passed via `.withConfig`, or the second arg in `.bindTools`, like shown in the examples below:
1136
+ *
1137
+ * ```typescript
1138
+ * // When calling `.withConfig`, call options should be passed via the first argument
1139
+ * const llmWithArgsBound = llm.withConfig({
1140
+ * stop: ["\n"],
1141
+ * });
1142
+ *
1143
+ * // When calling `.bindTools`, call options should be passed via the second argument
1144
+ * const llmWithTools = llm.bindTools(
1145
+ * [...],
1146
+ * {
1147
+ * stop: ["\n"],
1148
+ * }
1149
+ * );
1150
+ * ```
1151
+ *
1152
+ * ## Examples
1153
+ *
1154
+ * <details open>
1155
+ * <summary><strong>Instantiate</strong></summary>
1156
+ *
1157
+ * ```typescript
1158
+ * import { ChatGoogleGenerativeAI } from '@intrvls/langchain-google-genai';
1159
+ *
1160
+ * const llm = new ChatGoogleGenerativeAI({
1161
+ * model: "gemini-3.5-flash",
1162
+ * temperature: 0,
1163
+ * maxRetries: 2,
1164
+ * // apiKey: "...",
1165
+ * // other params...
1166
+ * });
1167
+ * ```
1168
+ * </details>
1169
+ *
1170
+ * <br />
1171
+ *
1172
+ * <details>
1173
+ * <summary><strong>Invoking</strong></summary>
1174
+ *
1175
+ * ```typescript
1176
+ * const input = `Translate "I love programming" into French.`;
1177
+ *
1178
+ * // Models also accept a list of chat messages or a formatted prompt
1179
+ * const result = await llm.invoke(input);
1180
+ * console.log(result);
1181
+ * ```
1182
+ *
1183
+ * ```txt
1184
+ * AIMessage {
1185
+ * "content": "There are a few ways to translate \"I love programming\" into French, depending on the level of formality and nuance you want to convey:\n\n**Formal:**\n\n* **J'aime la programmation.** (This is the most literal and formal translation.)\n\n**Informal:**\n\n* **J'adore programmer.** (This is a more enthusiastic and informal translation.)\n* **J'aime beaucoup programmer.** (This is a slightly less enthusiastic but still informal translation.)\n\n**More specific:**\n\n* **J'aime beaucoup coder.** (This specifically refers to writing code.)\n* **J'aime beaucoup développer des logiciels.** (This specifically refers to developing software.)\n\nThe best translation will depend on the context and your intended audience. \n",
1186
+ * "response_metadata": {
1187
+ * "finishReason": "STOP",
1188
+ * "index": 0,
1189
+ * "safetyRatings": [
1190
+ * {
1191
+ * "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
1192
+ * "probability": "NEGLIGIBLE"
1193
+ * },
1194
+ * {
1195
+ * "category": "HARM_CATEGORY_HATE_SPEECH",
1196
+ * "probability": "NEGLIGIBLE"
1197
+ * },
1198
+ * {
1199
+ * "category": "HARM_CATEGORY_HARASSMENT",
1200
+ * "probability": "NEGLIGIBLE"
1201
+ * },
1202
+ * {
1203
+ * "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
1204
+ * "probability": "NEGLIGIBLE"
1205
+ * }
1206
+ * ]
1207
+ * },
1208
+ * "usage_metadata": {
1209
+ * "input_tokens": 10,
1210
+ * "output_tokens": 149,
1211
+ * "total_tokens": 159
1212
+ * }
1213
+ * }
1214
+ * ```
1215
+ * </details>
1216
+ *
1217
+ * <br />
1218
+ *
1219
+ * <details>
1220
+ * <summary><strong>Streaming Chunks</strong></summary>
1221
+ *
1222
+ * ```typescript
1223
+ * for await (const chunk of await llm.stream(input)) {
1224
+ * console.log(chunk);
1225
+ * }
1226
+ * ```
1227
+ *
1228
+ * ```txt
1229
+ * AIMessageChunk {
1230
+ * "content": "There",
1231
+ * "response_metadata": {
1232
+ * "index": 0
1233
+ * }
1234
+ * "usage_metadata": {
1235
+ * "input_tokens": 10,
1236
+ * "output_tokens": 1,
1237
+ * "total_tokens": 11
1238
+ * }
1239
+ * }
1240
+ * AIMessageChunk {
1241
+ * "content": " are a few ways to translate \"I love programming\" into French, depending on",
1242
+ * }
1243
+ * AIMessageChunk {
1244
+ * "content": " the level of formality and nuance you want to convey:\n\n**Formal:**\n\n",
1245
+ * }
1246
+ * AIMessageChunk {
1247
+ * "content": "* **J'aime la programmation.** (This is the most literal and formal translation.)\n\n**Informal:**\n\n* **J'adore programmer.** (This",
1248
+ * }
1249
+ * AIMessageChunk {
1250
+ * "content": " is a more enthusiastic and informal translation.)\n* **J'aime beaucoup programmer.** (This is a slightly less enthusiastic but still informal translation.)\n\n**More",
1251
+ * }
1252
+ * AIMessageChunk {
1253
+ * "content": " specific:**\n\n* **J'aime beaucoup coder.** (This specifically refers to writing code.)\n* **J'aime beaucoup développer des logiciels.** (This specifically refers to developing software.)\n\nThe best translation will depend on the context and",
1254
+ * }
1255
+ * AIMessageChunk {
1256
+ * "content": " your intended audience. \n",
1257
+ * }
1258
+ * ```
1259
+ * </details>
1260
+ *
1261
+ * <br />
1262
+ *
1263
+ * <details>
1264
+ * <summary><strong>Aggregate Streamed Chunks</strong></summary>
1265
+ *
1266
+ * ```typescript
1267
+ * import { AIMessageChunk } from '@langchain/core/messages';
1268
+ * import { concat } from '@langchain/core/utils/stream';
1269
+ *
1270
+ * const stream = await llm.stream(input);
1271
+ * let full: AIMessageChunk | undefined;
1272
+ * for await (const chunk of stream) {
1273
+ * full = !full ? chunk : concat(full, chunk);
1274
+ * }
1275
+ * console.log(full);
1276
+ * ```
1277
+ *
1278
+ * ```txt
1279
+ * AIMessageChunk {
1280
+ * "content": "There are a few ways to translate \"I love programming\" into French, depending on the level of formality and nuance you want to convey:\n\n**Formal:**\n\n* **J'aime la programmation.** (This is the most literal and formal translation.)\n\n**Informal:**\n\n* **J'adore programmer.** (This is a more enthusiastic and informal translation.)\n* **J'aime beaucoup programmer.** (This is a slightly less enthusiastic but still informal translation.)\n\n**More specific:**\n\n* **J'aime beaucoup coder.** (This specifically refers to writing code.)\n* **J'aime beaucoup développer des logiciels.** (This specifically refers to developing software.)\n\nThe best translation will depend on the context and your intended audience. \n",
1281
+ * "usage_metadata": {
1282
+ * "input_tokens": 10,
1283
+ * "output_tokens": 277,
1284
+ * "total_tokens": 287
1285
+ * }
1286
+ * }
1287
+ * ```
1288
+ * </details>
1289
+ *
1290
+ * <br />
1291
+ *
1292
+ * <details>
1293
+ * <summary><strong>Bind tools</strong></summary>
1294
+ *
1295
+ * ```typescript
1296
+ * import { z } from 'zod';
1297
+ *
1298
+ * const GetWeather = {
1299
+ * name: "GetWeather",
1300
+ * description: "Get the current weather in a given location",
1301
+ * schema: z.object({
1302
+ * location: z.string().describe("The city and state, e.g. San Francisco, CA")
1303
+ * }),
1304
+ * }
1305
+ *
1306
+ * const GetPopulation = {
1307
+ * name: "GetPopulation",
1308
+ * description: "Get the current population in a given location",
1309
+ * schema: z.object({
1310
+ * location: z.string().describe("The city and state, e.g. San Francisco, CA")
1311
+ * }),
1312
+ * }
1313
+ *
1314
+ * const llmWithTools = llm.bindTools([GetWeather, GetPopulation]);
1315
+ * const aiMsg = await llmWithTools.invoke(
1316
+ * "Which city is hotter today and which is bigger: LA or NY?"
1317
+ * );
1318
+ * console.log(aiMsg.tool_calls);
1319
+ * ```
1320
+ *
1321
+ * ```txt
1322
+ * [
1323
+ * {
1324
+ * name: 'GetWeather',
1325
+ * args: { location: 'Los Angeles, CA' },
1326
+ * type: 'tool_call'
1327
+ * },
1328
+ * {
1329
+ * name: 'GetWeather',
1330
+ * args: { location: 'New York, NY' },
1331
+ * type: 'tool_call'
1332
+ * },
1333
+ * {
1334
+ * name: 'GetPopulation',
1335
+ * args: { location: 'Los Angeles, CA' },
1336
+ * type: 'tool_call'
1337
+ * },
1338
+ * {
1339
+ * name: 'GetPopulation',
1340
+ * args: { location: 'New York, NY' },
1341
+ * type: 'tool_call'
1342
+ * }
1343
+ * ]
1344
+ * ```
1345
+ * </details>
1346
+ *
1347
+ * <br />
1348
+ *
1349
+ * <details>
1350
+ * <summary><strong>Structured Output</strong></summary>
1351
+ *
1352
+ * ```typescript
1353
+ * const Joke = z.object({
1354
+ * setup: z.string().describe("The setup of the joke"),
1355
+ * punchline: z.string().describe("The punchline to the joke"),
1356
+ * rating: z.number().optional().describe("How funny the joke is, from 1 to 10")
1357
+ * }).describe('Joke to tell user.');
1358
+ *
1359
+ * const structuredLlm = llm.withStructuredOutput(Joke, { name: "Joke" });
1360
+ * const jokeResult = await structuredLlm.invoke("Tell me a joke about cats");
1361
+ * console.log(jokeResult);
1362
+ * ```
1363
+ *
1364
+ * ```txt
1365
+ * {
1366
+ * setup: "Why don\\'t cats play poker?",
1367
+ * punchline: "Why don\\'t cats play poker? Because they always have an ace up their sleeve!"
1368
+ * }
1369
+ * ```
1370
+ * </details>
1371
+ *
1372
+ * <br />
1373
+ *
1374
+ * <details>
1375
+ * <summary><strong>Multimodal</strong></summary>
1376
+ *
1377
+ * ```typescript
1378
+ * import { HumanMessage } from '@langchain/core/messages';
1379
+ *
1380
+ * const imageUrl = "https://example.com/image.jpg";
1381
+ * const imageData = await fetch(imageUrl).then(res => res.arrayBuffer());
1382
+ * const base64Image = Buffer.from(imageData).toString('base64');
1383
+ *
1384
+ * const message = new HumanMessage({
1385
+ * content: [
1386
+ * { type: "text", text: "describe the weather in this image" },
1387
+ * {
1388
+ * type: "image_url",
1389
+ * image_url: { url: `data:image/jpeg;base64,${base64Image}` },
1390
+ * },
1391
+ * ]
1392
+ * });
1393
+ *
1394
+ * const imageDescriptionAiMsg = await llm.invoke([message]);
1395
+ * console.log(imageDescriptionAiMsg.content);
1396
+ * ```
1397
+ *
1398
+ * ```txt
1399
+ * The weather in the image appears to be clear and sunny. The sky is mostly blue with a few scattered white clouds, indicating fair weather. The bright sunlight is casting shadows on the green, grassy hill, suggesting it is a pleasant day with good visibility. There are no signs of rain or stormy conditions.
1400
+ * ```
1401
+ * </details>
1402
+ *
1403
+ * <br />
1404
+ *
1405
+ * <details>
1406
+ * <summary><strong>Usage Metadata</strong></summary>
1407
+ *
1408
+ * ```typescript
1409
+ * const aiMsgForMetadata = await llm.invoke(input);
1410
+ * console.log(aiMsgForMetadata.usage_metadata);
1411
+ * ```
1412
+ *
1413
+ * ```txt
1414
+ * { input_tokens: 10, output_tokens: 149, total_tokens: 159 }
1415
+ * ```
1416
+ * </details>
1417
+ *
1418
+ * <br />
1419
+ *
1420
+ * <details>
1421
+ * <summary><strong>Response Metadata</strong></summary>
1422
+ *
1423
+ * ```typescript
1424
+ * const aiMsgForResponseMetadata = await llm.invoke(input);
1425
+ * console.log(aiMsgForResponseMetadata.response_metadata);
1426
+ * ```
1427
+ *
1428
+ * ```txt
1429
+ * {
1430
+ * finishReason: 'STOP',
1431
+ * index: 0,
1432
+ * safetyRatings: [
1433
+ * {
1434
+ * category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT',
1435
+ * probability: 'NEGLIGIBLE'
1436
+ * },
1437
+ * {
1438
+ * category: 'HARM_CATEGORY_HATE_SPEECH',
1439
+ * probability: 'NEGLIGIBLE'
1440
+ * },
1441
+ * { category: 'HARM_CATEGORY_HARASSMENT', probability: 'NEGLIGIBLE' },
1442
+ * {
1443
+ * category: 'HARM_CATEGORY_DANGEROUS_CONTENT',
1444
+ * probability: 'NEGLIGIBLE'
1445
+ * }
1446
+ * ]
1447
+ * }
1448
+ * ```
1449
+ * </details>
1450
+ *
1451
+ * <br />
1452
+ *
1453
+ * <details>
1454
+ * <summary><strong>Document Messages</strong></summary>
1455
+ *
1456
+ * This example will show you how to pass documents such as PDFs to Google
1457
+ * Generative AI through messages.
1458
+ *
1459
+ * ```typescript
1460
+ * const pdfPath = "/Users/my_user/Downloads/invoice.pdf";
1461
+ * const pdfBase64 = await fs.readFile(pdfPath, "base64");
1462
+ *
1463
+ * const response = await llm.invoke([
1464
+ * ["system", "Use the provided documents to answer the question"],
1465
+ * [
1466
+ * "user",
1467
+ * [
1468
+ * {
1469
+ * type: "application/pdf", // If the `type` field includes a single slash (`/`), it will be treated as inline data.
1470
+ * data: pdfBase64,
1471
+ * },
1472
+ * {
1473
+ * type: "text",
1474
+ * text: "Summarize the contents of this PDF",
1475
+ * },
1476
+ * ],
1477
+ * ],
1478
+ * ]);
1479
+ *
1480
+ * console.log(response.content);
1481
+ * ```
1482
+ *
1483
+ * ```txt
1484
+ * This is a billing invoice from Twitter Developers for X API Basic Access. The transaction date is January 7, 2025,
1485
+ * and the amount is $194.34, which has been paid. The subscription period is from January 7, 2025 21:02 to February 7, 2025 00:00 (UTC).
1486
+ * The tax is $0.00, with a tax rate of 0%. The total amount is $194.34. The payment was made using a Visa card ending in 7022,
1487
+ * expiring in 12/2026. The billing address is Brace Sproul, 1234 Main Street, San Francisco, CA, US 94103. The company being billed is
1488
+ * X Corp, located at 865 FM 1209 Building 2, Bastrop, TX, US 78602. Terms and conditions apply.
1489
+ * ```
1490
+ * </details>
1491
+ *
1492
+ * <br />
1493
+ */
1494
+ /**
1495
+ * Whether the given model id is Gemini 3 or a later major version. Strips an
1496
+ * optional `models/` prefix and reads the major version number, so
1497
+ * `gemini-3.1-pro-preview`, `gemini-3.5-flash`, and a future `gemini-4-*` all
1498
+ * return true, while `gemini-2.5-flash` returns false.
1499
+ */
1500
+ function isGemini3OrLater(model) {
1501
+ const match = model.toLowerCase().replace(/^models\//, "").match(/gemini-(\d+)/);
1502
+ return match ? Number(match[1]) >= 3 : false;
1503
+ }
1504
+ var ChatGoogleGenerativeAI = class extends _langchain_core_language_models_chat_models.BaseChatModel {
1505
+ static lc_name() {
1506
+ return "ChatGoogleGenerativeAI";
1507
+ }
1508
+ lc_serializable = true;
1509
+ get lc_secrets() {
1510
+ return { apiKey: "GOOGLE_API_KEY" };
1511
+ }
1512
+ lc_namespace = [
1513
+ "langchain",
1514
+ "chat_models",
1515
+ "google_genai"
1516
+ ];
1517
+ get lc_aliases() {
1518
+ return { apiKey: "google_api_key" };
1519
+ }
1520
+ model;
1521
+ temperature;
1522
+ maxOutputTokens;
1523
+ topP;
1524
+ topK;
1525
+ stopSequences = [];
1526
+ safetySettings;
1527
+ apiKey;
1528
+ streaming = false;
1529
+ json;
1530
+ streamUsage = true;
1531
+ convertSystemMessageToHumanContent;
1532
+ thinkingConfig;
1533
+ cachedContent;
1534
+ client;
1535
+ get _isMultimodalModel() {
1536
+ return this.model.includes("vision") || this.model.startsWith("gemini-1.5") || this.model.startsWith("gemini-2") || this.model.startsWith("gemma-3-") && !this.model.startsWith("gemma-3-1b") || this.model.startsWith("gemini-3");
1537
+ }
1538
+ constructor(modelOrFields, fieldsArg) {
1539
+ const fields = typeof modelOrFields === "string" ? {
1540
+ ...fieldsArg ?? {},
1541
+ model: modelOrFields
1542
+ } : modelOrFields;
1543
+ super(fields);
1544
+ this._addVersion("@intrvls/langchain-google-genai", "3.0.0-alpha.0");
1545
+ this.model = fields.model.replace(/^models\//, "");
1546
+ this.maxOutputTokens = fields.maxOutputTokens ?? this.maxOutputTokens;
1547
+ if (this.maxOutputTokens && this.maxOutputTokens < 0) throw new Error("`maxOutputTokens` must be a positive integer");
1548
+ this.temperature = fields.temperature ?? this.temperature;
1549
+ if (this.temperature && (this.temperature < 0 || this.temperature > 2)) throw new Error("`temperature` must be in the range of [0.0,2.0]");
1550
+ if (fields.temperature === void 0 && isGemini3OrLater(this.model)) this.temperature = 1;
1551
+ this.topP = fields.topP ?? this.topP;
1552
+ if (this.topP && this.topP < 0) throw new Error("`topP` must be a positive integer");
1553
+ if (this.topP && this.topP > 1) throw new Error("`topP` must be below 1.");
1554
+ this.topK = fields.topK ?? this.topK;
1555
+ if (this.topK && this.topK < 0) throw new Error("`topK` must be a positive integer");
1556
+ this.stopSequences = fields.stopSequences ?? this.stopSequences;
1557
+ this.apiKey = fields.apiKey ?? (0, _langchain_core_utils_env.getEnvironmentVariable)("GOOGLE_API_KEY") ?? (0, _langchain_core_utils_env.getEnvironmentVariable)("GEMINI_API_KEY");
1558
+ if (!this.apiKey) throw new Error("Please set an API key for Google GenerativeAI in the environment variable GOOGLE_API_KEY (or GEMINI_API_KEY) or in the `apiKey` field of the ChatGoogleGenerativeAI constructor");
1559
+ this.safetySettings = fields.safetySettings ?? this.safetySettings;
1560
+ if (this.safetySettings && this.safetySettings.length > 0) {
1561
+ if (new Set(this.safetySettings.map((s) => s.category)).size !== this.safetySettings.length) throw new Error("The categories in `safetySettings` array must be unique");
1562
+ }
1563
+ this.streaming = fields.streaming ?? this.streaming;
1564
+ this.json = fields.json;
1565
+ this.thinkingConfig = fields.thinkingConfig ?? this.thinkingConfig;
1566
+ this.cachedContent = fields.cachedContent ?? this.cachedContent;
1567
+ this.client = new _google_genai.GoogleGenAI({
1568
+ apiKey: this.apiKey,
1569
+ httpOptions: {
1570
+ apiVersion: fields.apiVersion,
1571
+ baseUrl: fields.baseUrl,
1572
+ headers: fields.customHeaders
1573
+ }
1574
+ });
1575
+ this.streamUsage = fields.streamUsage ?? this.streamUsage;
1576
+ }
1577
+ get useSystemInstruction() {
1578
+ return typeof this.convertSystemMessageToHumanContent === "boolean" ? !this.convertSystemMessageToHumanContent : this.computeUseSystemInstruction;
1579
+ }
1580
+ get computeUseSystemInstruction() {
1581
+ if (this.model === "gemini-1.0-pro-001") return false;
1582
+ else if (this.model.startsWith("gemini-pro-vision")) return false;
1583
+ else if (this.model.startsWith("gemini-1.0-pro-vision")) return false;
1584
+ else if (this.model === "gemini-pro") return false;
1585
+ return true;
1586
+ }
1587
+ getLsParams(options) {
1588
+ return {
1589
+ ls_provider: "google_genai",
1590
+ ls_model_name: this.model,
1591
+ ls_model_type: "chat",
1592
+ ls_temperature: this.temperature,
1593
+ ls_max_tokens: this.maxOutputTokens,
1594
+ ls_stop: options.stop
1595
+ };
1596
+ }
1597
+ _combineLLMOutput() {
1598
+ return [];
1599
+ }
1600
+ _llmType() {
1601
+ return "googlegenerativeai";
1602
+ }
1603
+ bindTools(tools, kwargs) {
1604
+ return this.withConfig({
1605
+ tools: convertToolsToGenAI(tools)?.tools,
1606
+ ...kwargs
1607
+ });
1608
+ }
1609
+ invocationParams(options) {
1610
+ const toolsAndConfig = options?.tools?.length ? convertToolsToGenAI(options.tools, {
1611
+ toolChoice: options.tool_choice,
1612
+ allowedFunctionNames: options.allowedFunctionNames
1613
+ }) : void 0;
1614
+ return {
1615
+ ...toolsAndConfig?.tools ? { tools: toolsAndConfig.tools } : {},
1616
+ ...toolsAndConfig?.toolConfig ? { toolConfig: toolsAndConfig.toolConfig } : {},
1617
+ ...this.safetySettings ? { safetySettings: this.safetySettings } : {},
1618
+ ...this.cachedContent ? { cachedContent: this.cachedContent } : {},
1619
+ stopSequences: this.stopSequences,
1620
+ maxOutputTokens: this.maxOutputTokens,
1621
+ temperature: this.temperature,
1622
+ topP: this.topP,
1623
+ topK: this.topK,
1624
+ ...this.json ? { responseMimeType: "application/json" } : {},
1625
+ ...this.thinkingConfig ? { thinkingConfig: this.thinkingConfig } : {},
1626
+ ...options?.responseSchema ? {
1627
+ responseSchema: options.responseSchema,
1628
+ responseMimeType: "application/json"
1629
+ } : {}
1630
+ };
1631
+ }
1632
+ _buildGenerateContentRequest(messages, options) {
1633
+ const prompt = convertBaseMessagesToContent(messages, this._isMultimodalModel, this.useSystemInstruction, this.model);
1634
+ let actualPrompt = prompt;
1635
+ let systemInstruction;
1636
+ if (prompt[0]?.role === "system") [systemInstruction, ...actualPrompt] = prompt;
1637
+ const config = this.invocationParams(options);
1638
+ return {
1639
+ model: this.model,
1640
+ contents: actualPrompt,
1641
+ config: {
1642
+ ...config,
1643
+ ...systemInstruction ? { systemInstruction } : {},
1644
+ ...options.signal ? { abortSignal: options.signal } : {}
1645
+ }
1646
+ };
1647
+ }
1648
+ async _generate(messages, options, runManager) {
1649
+ options.signal?.throwIfAborted();
1650
+ if (this.streaming) {
1651
+ const tokenUsage = {};
1652
+ const stream = this._streamResponseChunks(messages, options, runManager);
1653
+ const finalChunks = [];
1654
+ for await (const chunk of stream) {
1655
+ const index = chunk.generationInfo?.completion ?? 0;
1656
+ if (finalChunks[index] === void 0) finalChunks[index] = chunk;
1657
+ else finalChunks[index] = finalChunks[index].concat(chunk);
1658
+ }
1659
+ return {
1660
+ generations: finalChunks.filter((c) => c !== void 0),
1661
+ llmOutput: { estimatedTokenUsage: tokenUsage }
1662
+ };
1663
+ }
1664
+ const res = await this.completionWithRetry(this._buildGenerateContentRequest(messages, options));
1665
+ let usageMetadata;
1666
+ if (res.usageMetadata) usageMetadata = convertUsageMetadata(res.usageMetadata, this.model);
1667
+ const generationResult = mapGenerateContentResultToChatResult(res, { usageMetadata });
1668
+ if (generationResult.generations?.length > 0) await runManager?.handleLLMNewToken(generationResult.generations[0]?.text ?? "");
1669
+ return generationResult;
1670
+ }
1671
+ async *_streamResponseChunks(messages, options, runManager) {
1672
+ const request = this._buildGenerateContentRequest(messages, options);
1673
+ const stream = await this.caller.callWithOptions({ signal: options?.signal }, async () => {
1674
+ return this.client.models.generateContentStream(request);
1675
+ });
1676
+ let usageMetadata;
1677
+ let prevPromptTokenCount = 0;
1678
+ let prevCandidatesTokenCount = 0;
1679
+ let prevThoughtsTokenCount = 0;
1680
+ let prevTotalTokenCount = 0;
1681
+ let index = 0;
1682
+ for await (const response of stream) {
1683
+ if (options.signal?.aborted) return;
1684
+ if ("usageMetadata" in response && response.usageMetadata !== void 0 && this.streamUsage !== false && options.streamUsage !== false) {
1685
+ usageMetadata = convertUsageMetadata(response.usageMetadata, this.model);
1686
+ const newPromptTokenCount = response.usageMetadata.promptTokenCount ?? 0;
1687
+ usageMetadata.input_tokens = Math.max(0, newPromptTokenCount - prevPromptTokenCount);
1688
+ prevPromptTokenCount = newPromptTokenCount;
1689
+ const newCandidatesTokenCount = response.usageMetadata.candidatesTokenCount ?? 0;
1690
+ const candidatesDelta = Math.max(0, newCandidatesTokenCount - prevCandidatesTokenCount);
1691
+ prevCandidatesTokenCount = newCandidatesTokenCount;
1692
+ const newThoughtsTokenCount = response.usageMetadata.thoughtsTokenCount ?? 0;
1693
+ const reasoningDelta = Math.max(0, newThoughtsTokenCount - prevThoughtsTokenCount);
1694
+ prevThoughtsTokenCount = newThoughtsTokenCount;
1695
+ usageMetadata.output_tokens = candidatesDelta + reasoningDelta;
1696
+ usageMetadata.output_token_details = reasoningDelta ? {
1697
+ ...usageMetadata.output_token_details,
1698
+ reasoning: reasoningDelta
1699
+ } : usageMetadata.output_token_details;
1700
+ const newTotalTokenCount = response.usageMetadata.totalTokenCount ?? 0;
1701
+ usageMetadata.total_tokens = Math.max(0, newTotalTokenCount - prevTotalTokenCount);
1702
+ prevTotalTokenCount = newTotalTokenCount;
1703
+ }
1704
+ const chunk = convertResponseContentToChatGenerationChunk(response, {
1705
+ usageMetadata,
1706
+ index
1707
+ });
1708
+ index += 1;
1709
+ if (!chunk) continue;
1710
+ yield chunk;
1711
+ await runManager?.handleLLMNewToken(chunk.text ?? "");
1712
+ }
1713
+ }
1714
+ async completionWithRetry(request, options) {
1715
+ return this.caller.callWithOptions({ signal: options?.signal }, async () => {
1716
+ try {
1717
+ return await this.client.models.generateContent(request);
1718
+ } catch (e) {
1719
+ if (e.message?.includes("400 Bad Request")) e.status = 400;
1720
+ throw e;
1721
+ }
1722
+ });
1723
+ }
1724
+ /**
1725
+ * Return profiling information for the model.
1726
+ *
1727
+ * Provides information about the model's capabilities and constraints,
1728
+ * including token limits, multimodal support, and advanced features like
1729
+ * tool calling and structured output.
1730
+ *
1731
+ * @returns {ModelProfile} An object describing the model's capabilities and constraints
1732
+ *
1733
+ * @example
1734
+ * ```typescript
1735
+ * const model = new ChatGoogleGenerativeAI({ model: "gemini-2.5-flash" });
1736
+ * const profile = model.profile;
1737
+ * console.log(profile.maxInputTokens); // 1048576
1738
+ * console.log(profile.imageInputs); // true
1739
+ * ```
1740
+ */
1741
+ get profile() {
1742
+ return PROFILES[this.model] ?? {};
1743
+ }
1744
+ withStructuredOutput(outputSchema, config) {
1745
+ const schema = outputSchema;
1746
+ const name = config?.name;
1747
+ const method = config?.method;
1748
+ const includeRaw = config?.includeRaw;
1749
+ if (method === "jsonMode") throw new Error(`ChatGoogleGenerativeAI only supports "jsonSchema" or "functionCalling" as a method.`);
1750
+ let llm;
1751
+ let outputParser;
1752
+ if (method === "functionCalling") {
1753
+ let functionName = name ?? "extract";
1754
+ let geminiFunctionDeclaration;
1755
+ if ((0, _langchain_core_utils_types.isInteropZodSchema)(schema) || (0, _langchain_core_utils_standard_schema.isSerializableSchema)(schema)) {
1756
+ const jsonSchema = schemaToGenerativeAIParameters(schema);
1757
+ geminiFunctionDeclaration = {
1758
+ name: functionName,
1759
+ description: jsonSchema.description ?? "A function available to call.",
1760
+ parameters: jsonSchema
1761
+ };
1762
+ } else if (typeof schema.name === "string" && typeof schema.parameters === "object" && schema.parameters != null) {
1763
+ geminiFunctionDeclaration = schema;
1764
+ geminiFunctionDeclaration.parameters = removeAdditionalProperties(schema.parameters);
1765
+ functionName = schema.name;
1766
+ } else geminiFunctionDeclaration = {
1767
+ name: functionName,
1768
+ description: schema.description ?? "",
1769
+ parameters: removeAdditionalProperties(schema)
1770
+ };
1771
+ const tools = [{ functionDeclarations: [geminiFunctionDeclaration] }];
1772
+ llm = this.bindTools(tools).withConfig({ allowedFunctionNames: [functionName] });
1773
+ outputParser = (0, _langchain_core_language_models_structured_output.createFunctionCallingParser)(schema, functionName, GoogleGenerativeAIToolsOutputParser);
1774
+ } else {
1775
+ const jsonSchema = schemaToGenerativeAIParameters(schema);
1776
+ llm = this.withConfig({ responseSchema: jsonSchema });
1777
+ outputParser = (0, _langchain_core_language_models_structured_output.createContentParser)(schema);
1778
+ }
1779
+ return (0, _langchain_core_language_models_structured_output.assembleStructuredOutputPipeline)(llm, outputParser, includeRaw, includeRaw ? "StructuredOutputRunnable" : "ChatGoogleGenerativeAIStructuredOutput");
1780
+ }
1781
+ };
1782
+ //#endregion
1783
+ //#region src/embeddings.ts
1784
+ /**
1785
+ * Class that extends the Embeddings class and provides methods for
1786
+ * generating embeddings using the Google Palm API.
1787
+ * @example
1788
+ * ```typescript
1789
+ * const model = new GoogleGenerativeAIEmbeddings({
1790
+ * apiKey: "<YOUR API KEY>",
1791
+ * modelName: "embedding-001",
1792
+ * });
1793
+ *
1794
+ * // Embed a single query
1795
+ * const res = await model.embedQuery(
1796
+ * "What would be a good company name for a company that makes colorful socks?"
1797
+ * );
1798
+ * console.log({ res });
1799
+ *
1800
+ * // Embed multiple documents
1801
+ * const documentRes = await model.embedDocuments(["Hello world", "Bye bye"]);
1802
+ * console.log({ documentRes });
1803
+ * ```
1804
+ */
1805
+ var GoogleGenerativeAIEmbeddings = class extends _langchain_core_embeddings.Embeddings {
1806
+ apiKey;
1807
+ modelName = "gemini-embedding-001";
1808
+ model = "gemini-embedding-001";
1809
+ taskType;
1810
+ title;
1811
+ stripNewLines = true;
1812
+ maxBatchSize = 100;
1813
+ client;
1814
+ constructor(fields) {
1815
+ super(fields ?? {});
1816
+ this.modelName = fields?.model?.replace(/^models\//, "") ?? fields?.modelName?.replace(/^models\//, "") ?? this.modelName;
1817
+ this.model = this.modelName;
1818
+ this.taskType = fields?.taskType ?? this.taskType;
1819
+ this.title = fields?.title ?? this.title;
1820
+ if (this.title && this.taskType !== "RETRIEVAL_DOCUMENT") throw new Error("title can only be sepcified with TaskType.RETRIEVAL_DOCUMENT");
1821
+ this.apiKey = fields?.apiKey ?? (0, _langchain_core_utils_env.getEnvironmentVariable)("GOOGLE_API_KEY") ?? (0, _langchain_core_utils_env.getEnvironmentVariable)("GEMINI_API_KEY");
1822
+ if (!this.apiKey) throw new Error("Please set an API key for Google GenerativeAI in the environment variable GOOGLE_API_KEY (or GEMINI_API_KEY) or in the `apiKey` field of the GoogleGenerativeAIEmbeddings constructor");
1823
+ this.client = new _google_genai.GoogleGenAI({
1824
+ apiKey: this.apiKey,
1825
+ httpOptions: { baseUrl: fields?.baseUrl }
1826
+ });
1827
+ }
1828
+ _cleanText(text) {
1829
+ return this.stripNewLines ? text.replace(/\n/g, " ") : text;
1830
+ }
1831
+ get _embedConfig() {
1832
+ return {
1833
+ taskType: this.taskType,
1834
+ title: this.title
1835
+ };
1836
+ }
1837
+ async _embedQueryContent(text) {
1838
+ return (await this.client.models.embedContent({
1839
+ model: this.model,
1840
+ contents: [this._cleanText(text)],
1841
+ config: this._embedConfig
1842
+ })).embeddings?.[0]?.values ?? [];
1843
+ }
1844
+ async _embedDocumentsContent(documents) {
1845
+ const batchEmbedChunks = (0, _langchain_core_utils_chunk_array.chunkArray)(documents, this.maxBatchSize);
1846
+ return (await Promise.allSettled(batchEmbedChunks.map((chunk) => this.client.models.embedContent({
1847
+ model: this.model,
1848
+ contents: chunk.map((doc) => this._cleanText(doc)),
1849
+ config: this._embedConfig
1850
+ })))).flatMap((res, idx) => {
1851
+ if (res.status === "fulfilled") return (res.value.embeddings ?? []).map((e) => e.values ?? []);
1852
+ else return Array(batchEmbedChunks[idx].length).fill([]);
1853
+ });
1854
+ }
1855
+ /**
1856
+ * Method that takes a document as input and returns a promise that
1857
+ * resolves to an embedding for the document. It calls the _embedText
1858
+ * method with the document as the input.
1859
+ * @param document Document for which to generate an embedding.
1860
+ * @returns Promise that resolves to an embedding for the input document.
1861
+ */
1862
+ embedQuery(document) {
1863
+ return this.caller.call(this._embedQueryContent.bind(this), document);
1864
+ }
1865
+ /**
1866
+ * Method that takes an array of documents as input and returns a promise
1867
+ * that resolves to a 2D array of embeddings for each document. It calls
1868
+ * the _embedText method for each document in the array.
1869
+ * @param documents Array of documents for which to generate embeddings.
1870
+ * @returns Promise that resolves to a 2D array of embeddings for each input document.
1871
+ */
1872
+ embedDocuments(documents) {
1873
+ return this.caller.call(this._embedDocumentsContent.bind(this), documents);
1874
+ }
1875
+ };
1876
+ //#endregion
1877
+ exports.ChatGoogleGenerativeAI = ChatGoogleGenerativeAI;
1878
+ exports.GoogleGenerativeAIEmbeddings = GoogleGenerativeAIEmbeddings;
1879
+
1880
+ //# sourceMappingURL=index.cjs.map