Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

@langchain/google-genai

Package Overview
Dependencies
Maintainers
12
Versions
97
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@langchain/google-genai - npm Package Compare versions

Comparing version
2.1.13
to
2.1.14
+28
dist/utils/validate_schema.cjs
//#region src/utils/validate_schema.ts
function assertNoEmptyStringEnums(schema, toolName, path = []) {
if (schema == null || typeof schema !== "object") return;
const obj = schema;
if (Array.isArray(obj.enum)) {
if (obj.enum.some((v) => v === "")) {
const pathStr = path.length ? ` at path "${path.join(".")}"` : "";
const toolStr = toolName ? ` in tool "${toolName}"` : "";
throw new Error(`Invalid enum: empty string not allowed${toolStr}${pathStr}. Gemini API rejects empty strings in enums.`);
}
}
if (obj.type === "object" && obj.properties && typeof obj.properties === "object") for (const [prop, child] of Object.entries(obj.properties)) assertNoEmptyStringEnums(child, toolName, [...path, prop]);
if (obj.items) assertNoEmptyStringEnums(obj.items, toolName, [...path, "[]"]);
for (const k of [
"anyOf",
"oneOf",
"allOf"
]) {
const arr = obj[k];
if (Array.isArray(arr)) arr.forEach((child, i) => assertNoEmptyStringEnums(child, toolName, [...path, `${k}[${i}]`]));
}
if (obj.additionalProperties && typeof obj.additionalProperties === "object") assertNoEmptyStringEnums(obj.additionalProperties, toolName, [...path, "additionalProperties"]);
}
//#endregion
exports.assertNoEmptyStringEnums = assertNoEmptyStringEnums;
//# sourceMappingURL=validate_schema.cjs.map
{"version":3,"file":"validate_schema.cjs","names":["schema: unknown","toolName?: string","path: string[]"],"sources":["../../src/utils/validate_schema.ts"],"sourcesContent":["export function assertNoEmptyStringEnums(\n schema: unknown,\n toolName?: string,\n path: string[] = []\n): void {\n if (schema == null || typeof schema !== \"object\") return;\n const obj = schema as Record<string, unknown>;\n\n if (Array.isArray(obj.enum)) {\n if (obj.enum.some((v) => v === \"\")) {\n const pathStr = path.length ? ` at path \"${path.join(\".\")}\"` : \"\";\n const toolStr = toolName ? ` in tool \"${toolName}\"` : \"\";\n throw new Error(\n `Invalid enum: empty string not allowed${toolStr}${pathStr}. ` +\n \"Gemini API rejects empty strings in enums.\"\n );\n }\n }\n\n // Descend into common JSON Schema nests\n if (\n obj.type === \"object\" &&\n obj.properties &&\n typeof obj.properties === \"object\"\n ) {\n for (const [prop, child] of Object.entries(\n obj.properties as Record<string, unknown>\n )) {\n assertNoEmptyStringEnums(child, toolName, [...path, prop]);\n }\n }\n\n if (obj.items) {\n assertNoEmptyStringEnums(obj.items, toolName, [...path, \"[]\"]);\n }\n\n for (const k of [\"anyOf\", \"oneOf\", \"allOf\"]) {\n const arr = obj[k];\n if (Array.isArray(arr)) {\n arr.forEach((child, i) =>\n assertNoEmptyStringEnums(child, toolName, [...path, `${k}[${i}]`])\n );\n }\n }\n\n if (\n obj.additionalProperties &&\n typeof obj.additionalProperties === \"object\"\n ) {\n assertNoEmptyStringEnums(obj.additionalProperties, toolName, [\n ...path,\n \"additionalProperties\",\n ]);\n }\n}\n"],"mappings":";;AAAA,SAAgB,yBACdA,QACAC,UACAC,OAAiB,CAAE,GACb;AACN,KAAI,UAAU,QAAQ,OAAO,WAAW,SAAU;CAClD,MAAM,MAAM;AAEZ,KAAI,MAAM,QAAQ,IAAI,KAAK,EACzB;MAAI,IAAI,KAAK,KAAK,CAAC,MAAM,MAAM,GAAG,EAAE;GAClC,MAAM,UAAU,KAAK,SAAS,CAAC,UAAU,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG;GAC/D,MAAM,UAAU,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,GAAG;AACtD,SAAM,IAAI,MACR,CAAC,sCAAsC,EAAE,UAAU,QAAQ,4CAAE,CACf;EAEjD;;AAIH,KACE,IAAI,SAAS,YACb,IAAI,cACJ,OAAO,IAAI,eAAe,SAE1B,MAAK,MAAM,CAAC,MAAM,MAAM,IAAI,OAAO,QACjC,IAAI,WACL,EACC,yBAAyB,OAAO,UAAU,CAAC,GAAG,MAAM,IAAK,EAAC;AAI9D,KAAI,IAAI,OACN,yBAAyB,IAAI,OAAO,UAAU,CAAC,GAAG,MAAM,IAAK,EAAC;AAGhE,MAAK,MAAM,KAAK;EAAC;EAAS;EAAS;CAAQ,GAAE;EAC3C,MAAM,MAAM,IAAI;AAChB,MAAI,MAAM,QAAQ,IAAI,EACpB,IAAI,QAAQ,CAAC,OAAO,MAClB,yBAAyB,OAAO,UAAU,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,AAAC,EAAC,CACnE;CAEJ;AAED,KACE,IAAI,wBACJ,OAAO,IAAI,yBAAyB,UAEpC,yBAAyB,IAAI,sBAAsB,UAAU,CAC3D,GAAG,MACH,sBACD,EAAC;AAEL"}
//#region src/utils/validate_schema.ts
function assertNoEmptyStringEnums(schema, toolName, path = []) {
if (schema == null || typeof schema !== "object") return;
const obj = schema;
if (Array.isArray(obj.enum)) {
if (obj.enum.some((v) => v === "")) {
const pathStr = path.length ? ` at path "${path.join(".")}"` : "";
const toolStr = toolName ? ` in tool "${toolName}"` : "";
throw new Error(`Invalid enum: empty string not allowed${toolStr}${pathStr}. Gemini API rejects empty strings in enums.`);
}
}
if (obj.type === "object" && obj.properties && typeof obj.properties === "object") for (const [prop, child] of Object.entries(obj.properties)) assertNoEmptyStringEnums(child, toolName, [...path, prop]);
if (obj.items) assertNoEmptyStringEnums(obj.items, toolName, [...path, "[]"]);
for (const k of [
"anyOf",
"oneOf",
"allOf"
]) {
const arr = obj[k];
if (Array.isArray(arr)) arr.forEach((child, i) => assertNoEmptyStringEnums(child, toolName, [...path, `${k}[${i}]`]));
}
if (obj.additionalProperties && typeof obj.additionalProperties === "object") assertNoEmptyStringEnums(obj.additionalProperties, toolName, [...path, "additionalProperties"]);
}
//#endregion
export { assertNoEmptyStringEnums };
//# sourceMappingURL=validate_schema.js.map
{"version":3,"file":"validate_schema.js","names":["schema: unknown","toolName?: string","path: string[]"],"sources":["../../src/utils/validate_schema.ts"],"sourcesContent":["export function assertNoEmptyStringEnums(\n schema: unknown,\n toolName?: string,\n path: string[] = []\n): void {\n if (schema == null || typeof schema !== \"object\") return;\n const obj = schema as Record<string, unknown>;\n\n if (Array.isArray(obj.enum)) {\n if (obj.enum.some((v) => v === \"\")) {\n const pathStr = path.length ? ` at path \"${path.join(\".\")}\"` : \"\";\n const toolStr = toolName ? ` in tool \"${toolName}\"` : \"\";\n throw new Error(\n `Invalid enum: empty string not allowed${toolStr}${pathStr}. ` +\n \"Gemini API rejects empty strings in enums.\"\n );\n }\n }\n\n // Descend into common JSON Schema nests\n if (\n obj.type === \"object\" &&\n obj.properties &&\n typeof obj.properties === \"object\"\n ) {\n for (const [prop, child] of Object.entries(\n obj.properties as Record<string, unknown>\n )) {\n assertNoEmptyStringEnums(child, toolName, [...path, prop]);\n }\n }\n\n if (obj.items) {\n assertNoEmptyStringEnums(obj.items, toolName, [...path, \"[]\"]);\n }\n\n for (const k of [\"anyOf\", \"oneOf\", \"allOf\"]) {\n const arr = obj[k];\n if (Array.isArray(arr)) {\n arr.forEach((child, i) =>\n assertNoEmptyStringEnums(child, toolName, [...path, `${k}[${i}]`])\n );\n }\n }\n\n if (\n obj.additionalProperties &&\n typeof obj.additionalProperties === \"object\"\n ) {\n assertNoEmptyStringEnums(obj.additionalProperties, toolName, [\n ...path,\n \"additionalProperties\",\n ]);\n }\n}\n"],"mappings":";AAAA,SAAgB,yBACdA,QACAC,UACAC,OAAiB,CAAE,GACb;AACN,KAAI,UAAU,QAAQ,OAAO,WAAW,SAAU;CAClD,MAAM,MAAM;AAEZ,KAAI,MAAM,QAAQ,IAAI,KAAK,EACzB;MAAI,IAAI,KAAK,KAAK,CAAC,MAAM,MAAM,GAAG,EAAE;GAClC,MAAM,UAAU,KAAK,SAAS,CAAC,UAAU,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG;GAC/D,MAAM,UAAU,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,GAAG;AACtD,SAAM,IAAI,MACR,CAAC,sCAAsC,EAAE,UAAU,QAAQ,4CAAE,CACf;EAEjD;;AAIH,KACE,IAAI,SAAS,YACb,IAAI,cACJ,OAAO,IAAI,eAAe,SAE1B,MAAK,MAAM,CAAC,MAAM,MAAM,IAAI,OAAO,QACjC,IAAI,WACL,EACC,yBAAyB,OAAO,UAAU,CAAC,GAAG,MAAM,IAAK,EAAC;AAI9D,KAAI,IAAI,OACN,yBAAyB,IAAI,OAAO,UAAU,CAAC,GAAG,MAAM,IAAK,EAAC;AAGhE,MAAK,MAAM,KAAK;EAAC;EAAS;EAAS;CAAQ,GAAE;EAC3C,MAAM,MAAM,IAAI;AAChB,MAAI,MAAM,QAAQ,IAAI,EACpB,IAAI,QAAQ,CAAC,OAAO,MAClB,yBAAyB,OAAO,UAAU,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,AAAC,EAAC,CACnE;CAEJ;AAED,KACE,IAAI,wBACJ,OAAO,IAAI,yBAAyB,UAEpC,yBAAyB,IAAI,sBAAsB,UAAU,CAC3D,GAAG,MACH,sBACD,EAAC;AAEL"}
+24
-0
# @langchain/google-genai
## 2.1.14
### Patch Changes
- [#9900](https://github.com/langchain-ai/langchainjs/pull/9900) [`a9b5059`](https://github.com/langchain-ai/langchainjs/commit/a9b50597186002221aaa4585246e569fa44c27c8) Thanks [@hntrl](https://github.com/hntrl)! - Improved abort signal handling for chat models:
- Added `ModelAbortError` class in `@langchain/core/errors` that contains partial output when a model invocation is aborted mid-stream
- `invoke()` now throws `ModelAbortError` with accumulated `partialOutput` when aborted during streaming (when using streaming callback handlers)
- `stream()` throws a regular `AbortError` when aborted (since chunks are already yielded to the caller)
- All provider implementations now properly check and propagate abort signals in both `_generate()` and `_streamResponseChunks()` methods
- Added standard tests for abort signal behavior
- [#9900](https://github.com/langchain-ai/langchainjs/pull/9900) [`a9b5059`](https://github.com/langchain-ai/langchainjs/commit/a9b50597186002221aaa4585246e569fa44c27c8) Thanks [@hntrl](https://github.com/hntrl)! - fix(providers): add proper abort signal handling for invoke and stream operations
- Added early abort check (`signal.throwIfAborted()`) at the start of `_generate` methods to immediately throw when signal is already aborted
- Added abort signal checks inside streaming loops in `_streamResponseChunks` to return early when signal is aborted
- Propagated abort signals to underlying SDK calls where applicable (Google GenAI, Google Common/VertexAI, Cohere)
- Added standard tests for abort signal behavior in `@langchain/standard-tests`
This enables proper cancellation behavior for both invoke and streaming operations, and allows fallback chains to correctly proceed to the next runnable when the previous one is aborted.
- [#9875](https://github.com/langchain-ai/langchainjs/pull/9875) [`a000b0f`](https://github.com/langchain-ai/langchainjs/commit/a000b0f642f24dd6a2159a4fa2c6bda5838a68e1) Thanks [@joeljohn159](https://github.com/joeljohn159)! - Add validation for empty strings in enum values to provide clear error messages instead of cryptic runtime errors from Gemini API
- Updated dependencies [[`a9b5059`](https://github.com/langchain-ai/langchainjs/commit/a9b50597186002221aaa4585246e569fa44c27c8), [`a9b5059`](https://github.com/langchain-ai/langchainjs/commit/a9b50597186002221aaa4585246e569fa44c27c8)]:
- @langchain/core@1.1.18
## 2.1.13

@@ -4,0 +28,0 @@

+4
-2

@@ -519,2 +519,3 @@ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');

async _generate(messages, options, runManager) {
options.signal?.throwIfAborted();
const prompt = require_common.convertBaseMessagesToContent(messages, this._isMultimodalModel, this.useSystemInstruction, this.model);

@@ -567,3 +568,3 @@ let actualPrompt = prompt;

const stream = await this.caller.callWithOptions({ signal: options?.signal }, async () => {
const { stream: stream$1 } = await this.client.generateContentStream(request);
const { stream: stream$1 } = await this.client.generateContentStream(request, { signal: options?.signal });
return stream$1;

@@ -577,2 +578,3 @@ });

for await (const response of stream) {
if (options.signal?.aborted) return;
if ("usageMetadata" in response && response.usageMetadata !== void 0 && this.streamUsage !== false && options.streamUsage !== false) {

@@ -603,3 +605,3 @@ usageMetadata = require_common.convertUsageMetadata(response.usageMetadata, this.model);

try {
return await this.client.generateContent(request);
return await this.client.generateContent(request, { signal: options?.signal });
} catch (e) {

@@ -606,0 +608,0 @@ if (e.message?.includes("400 Bad Request")) e.status = 400;

@@ -518,2 +518,3 @@ import { removeAdditionalProperties, schemaToGenerativeAIParameters } from "./utils/zod_to_genai_parameters.js";

async _generate(messages, options, runManager) {
options.signal?.throwIfAborted();
const prompt = convertBaseMessagesToContent(messages, this._isMultimodalModel, this.useSystemInstruction, this.model);

@@ -566,3 +567,3 @@ let actualPrompt = prompt;

const stream = await this.caller.callWithOptions({ signal: options?.signal }, async () => {
const { stream: stream$1 } = await this.client.generateContentStream(request);
const { stream: stream$1 } = await this.client.generateContentStream(request, { signal: options?.signal });
return stream$1;

@@ -576,2 +577,3 @@ });

for await (const response of stream) {
if (options.signal?.aborted) return;
if ("usageMetadata" in response && response.usageMetadata !== void 0 && this.streamUsage !== false && options.streamUsage !== false) {

@@ -602,3 +604,3 @@ usageMetadata = convertUsageMetadata(response.usageMetadata, this.model);

try {
return await this.client.generateContent(request);
return await this.client.generateContent(request, { signal: options?.signal });
} catch (e) {

@@ -605,0 +607,0 @@ if (e.message?.includes("400 Bad Request")) e.status = 400;

const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
const require_zod_to_genai_parameters = require('./zod_to_genai_parameters.cjs');
const require_validate_schema = require('./validate_schema.cjs');
const __langchain_core_messages = require_rolldown_runtime.__toESM(require("@langchain/core/messages"));

@@ -409,2 +410,3 @@ const __langchain_core_outputs = require_rolldown_runtime.__toESM(require("@langchain/core/outputs"));

};
require_validate_schema.assertNoEmptyStringEnums(jsonSchema, tool.name);
return {

@@ -416,7 +418,11 @@ name: tool.name,

}
if ((0, __langchain_core_language_models_base.isOpenAITool)(tool)) return {
name: tool.function.name,
description: tool.function.description ?? `A function available to call.`,
parameters: require_zod_to_genai_parameters.jsonSchemaToGeminiParameters(tool.function.parameters)
};
if ((0, __langchain_core_language_models_base.isOpenAITool)(tool)) {
const params = require_zod_to_genai_parameters.jsonSchemaToGeminiParameters(tool.function.parameters);
require_validate_schema.assertNoEmptyStringEnums(params, tool.function.name);
return {
name: tool.function.name,
description: tool.function.description ?? `A function available to call.`,
parameters: params
};
}
return tool;

@@ -423,0 +429,0 @@ }) }];

import { jsonSchemaToGeminiParameters, schemaToGenerativeAIParameters } from "./zod_to_genai_parameters.js";
import { assertNoEmptyStringEnums } from "./validate_schema.js";
import { AIMessage, AIMessageChunk, ChatMessage, convertToProviderContentBlock, isAIMessage, isBaseMessage, isDataContentBlock, isToolMessage, parseBase64DataUrl } from "@langchain/core/messages";

@@ -408,2 +409,3 @@ import { ChatGenerationChunk } from "@langchain/core/outputs";

};
assertNoEmptyStringEnums(jsonSchema, tool.name);
return {

@@ -415,7 +417,11 @@ name: tool.name,

}
if (isOpenAITool(tool)) return {
name: tool.function.name,
description: tool.function.description ?? `A function available to call.`,
parameters: jsonSchemaToGeminiParameters(tool.function.parameters)
};
if (isOpenAITool(tool)) {
const params = jsonSchemaToGeminiParameters(tool.function.parameters);
assertNoEmptyStringEnums(params, tool.function.name);
return {
name: tool.function.name,
description: tool.function.description ?? `A function available to call.`,
parameters: params
};
}
return tool;

@@ -422,0 +428,0 @@ }) }];

{
"name": "@langchain/google-genai",
"version": "2.1.13",
"version": "2.1.14",
"description": "Google Generative AI integration for LangChain.js",

@@ -21,3 +21,3 @@ "author": "LangChain",

"peerDependencies": {
"@langchain/core": "1.1.17"
"@langchain/core": "1.1.18"
},

@@ -39,5 +39,5 @@ "devDependencies": {

"zod": "^3.25.76",
"@langchain/core": "1.1.17",
"@langchain/core": "1.1.18",
"@langchain/eslint": "0.1.1",
"@langchain/standard-tests": "0.0.20",
"@langchain/standard-tests": "0.0.21",
"@langchain/tsconfig": "0.0.1"

@@ -44,0 +44,0 @@ },

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet