fix: sanitize Gemini function names to meet API requirements (closes #369) (#403)

This commit is contained in:
Anurag Saxena
2026-03-26 23:40:29 -04:00
committed by GitHub
parent 56be393a59
commit ade3f57d4c

View File

@@ -20,6 +20,21 @@ import {
} from "../helpers/geminiHelper.js";
import { deriveSessionId } from "../../utils/sessionManager.js";
// Sanitize function names for Gemini API.
// Gemini requires: starts with [a-zA-Z_], followed by [a-zA-Z0-9_.:\-], max 64 chars.
// Replace any invalid character with '_' and truncate to 64.
function sanitizeGeminiFunctionName(name) {
if (!name) return "_unknown";
// Replace any char not in [a-zA-Z0-9_.:\-] with '_'
let sanitized = name.replace(/[^a-zA-Z0-9_.:\-]/g, "_");
// First char must be letter or underscore
if (!/^[a-zA-Z_]/.test(sanitized)) {
sanitized = "_" + sanitized;
}
// Truncate to 64 chars
return sanitized.substring(0, 64);
}
// Core: Convert OpenAI request to Gemini format (base for all variants)
function openaiToGeminiBase(model, body, stream) {
const result = {
@@ -116,7 +131,7 @@ function openaiToGeminiBase(model, body, stream) {
thoughtSignature: DEFAULT_THINKING_GEMINI_SIGNATURE,
functionCall: {
id: tc.id,
name: tc.function.name,
name: sanitizeGeminiFunctionName(tc.function.name),
args: args
}
});
@@ -156,7 +171,7 @@ function openaiToGeminiBase(model, body, stream) {
toolParts.push({
functionResponse: {
id: fid,
name: name,
name: sanitizeGeminiFunctionName(name),
response: { result: parsedResp }
}
});
@@ -180,7 +195,7 @@ function openaiToGeminiBase(model, body, stream) {
if (t.name && t.input_schema) {
const cleanedSchema = cleanJSONSchemaForAntigravity(structuredClone(t.input_schema || { type: "object", properties: {} }));
functionDeclarations.push({
name: t.name,
name: sanitizeGeminiFunctionName(t.name),
description: t.description || "",
parameters: cleanedSchema
});
@@ -190,7 +205,7 @@ function openaiToGeminiBase(model, body, stream) {
const fn = t.function;
const cleanedSchema = cleanJSONSchemaForAntigravity(structuredClone(fn.parameters || { type: "object", properties: {} }));
functionDeclarations.push({
name: fn.name,
name: sanitizeGeminiFunctionName(fn.name),
description: fn.description || "",
parameters: cleanedSchema
});
@@ -372,7 +387,7 @@ function wrapInCloudCodeEnvelopeForClaude(model, claudeRequest, credentials = nu
if (tool.name && tool.input_schema) {
const cleanedSchema = cleanJSONSchemaForAntigravity(tool.input_schema);
functionDeclarations.push({
name: tool.name,
name: sanitizeGeminiFunctionName(tool.name),
description: tool.description || "",
parameters: cleanedSchema
});