123 lines
4.9 KiB
Diff
123 lines
4.9 KiB
Diff
diff --git a/dist/providers/google-shared.js b/dist/providers/google-shared.js
|
|
--- a/dist/providers/google-shared.js
|
|
+++ b/dist/providers/google-shared.js
|
|
@@ -52,19 +52,25 @@
|
|
}
|
|
else if (block.type === "thinking") {
|
|
// Thinking blocks require signatures for Claude via Antigravity.
|
|
- // If signature is missing (e.g. from GPT-OSS), convert to regular text with delimiters.
|
|
- if (block.thinkingSignature) {
|
|
+ // Only send thought signatures for Claude models - Gemini doesn't support them
|
|
+ // and will mimic <thinking> tags if we include them as text.
|
|
+ if (block.thinkingSignature && model.id.includes("claude")) {
|
|
parts.push({
|
|
thought: true,
|
|
text: sanitizeSurrogates(block.thinking),
|
|
thoughtSignature: block.thinkingSignature,
|
|
});
|
|
}
|
|
- else {
|
|
- parts.push({
|
|
- text: `<thinking>\n${sanitizeSurrogates(block.thinking)}\n</thinking>`,
|
|
- });
|
|
+ else if (!model.id.includes("gemini")) {
|
|
+ // For non-Gemini, non-Claude models, include as text with delimiters
|
|
+ // Skip entirely for Gemini to avoid it mimicking the pattern
|
|
+ if (block.thinking && block.thinking.trim()) {
|
|
+ parts.push({
|
|
+ text: `<thinking>\n${sanitizeSurrogates(block.thinking)}\n</thinking>`,
|
|
+ });
|
|
+ }
|
|
}
|
|
+ // For Gemini models without Claude signature: skip thinking blocks entirely
|
|
}
|
|
else if (block.type === "toolCall") {
|
|
const part = {
|
|
@@ -147,6 +153,77 @@
|
|
return contents;
|
|
}
|
|
/**
|
|
+ * Sanitize JSON Schema for Google Cloud Code Assist API.
|
|
+ * Removes unsupported keywords like patternProperties, const, anyOf, etc.
|
|
+ * and converts to a format compatible with Google's function declarations.
|
|
+ */
|
|
+function sanitizeSchemaForGoogle(schema) {
|
|
+ if (!schema || typeof schema !== 'object') {
|
|
+ return schema;
|
|
+ }
|
|
+ // If it's an array, sanitize each element
|
|
+ if (Array.isArray(schema)) {
|
|
+ return schema.map(item => sanitizeSchemaForGoogle(item));
|
|
+ }
|
|
+ const sanitized = {};
|
|
+ // List of unsupported JSON Schema keywords that Google's API doesn't understand
|
|
+ const unsupportedKeywords = [
|
|
+ 'patternProperties',
|
|
+ 'const',
|
|
+ 'anyOf',
|
|
+ 'oneOf',
|
|
+ 'allOf',
|
|
+ 'not',
|
|
+ '$schema',
|
|
+ '$id',
|
|
+ '$ref',
|
|
+ '$defs',
|
|
+ 'definitions',
|
|
+ 'if',
|
|
+ 'then',
|
|
+ 'else',
|
|
+ 'dependentSchemas',
|
|
+ 'dependentRequired',
|
|
+ 'unevaluatedProperties',
|
|
+ 'unevaluatedItems',
|
|
+ 'contentEncoding',
|
|
+ 'contentMediaType',
|
|
+ 'contentSchema',
|
|
+ 'deprecated',
|
|
+ 'readOnly',
|
|
+ 'writeOnly',
|
|
+ 'examples',
|
|
+ '$comment',
|
|
+ 'additionalProperties',
|
|
+ ];
|
|
+ // TODO(steipete): lossy schema scrub; revisit when Google supports these keywords.
|
|
+ for (const [key, value] of Object.entries(schema)) {
|
|
+ // Skip unsupported keywords
|
|
+ if (unsupportedKeywords.includes(key)) {
|
|
+ continue;
|
|
+ }
|
|
+ // Recursively sanitize nested objects
|
|
+ if (key === 'properties' && typeof value === 'object' && value !== null) {
|
|
+ sanitized[key] = {};
|
|
+ for (const [propKey, propValue] of Object.entries(value)) {
|
|
+ sanitized[key][propKey] = sanitizeSchemaForGoogle(propValue);
|
|
+ }
|
|
+ } else if (key === 'items' && typeof value === 'object') {
|
|
+ sanitized[key] = sanitizeSchemaForGoogle(value);
|
|
+ } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
+ sanitized[key] = sanitizeSchemaForGoogle(value);
|
|
+ } else {
|
|
+ sanitized[key] = value;
|
|
+ }
|
|
+ }
|
|
+ // Ensure type: "object" is present when properties or required exist
|
|
+ // Google API requires type to be set when these fields are present
|
|
+ if (('properties' in sanitized || 'required' in sanitized) && !('type' in sanitized)) {
|
|
+ sanitized.type = 'object';
|
|
+ }
|
|
+ return sanitized;
|
|
+}
|
|
+/**
|
|
* Convert tools to Gemini function declarations format.
|
|
*/
|
|
export function convertTools(tools) {
|
|
@@ -157,7 +234,7 @@
|
|
functionDeclarations: tools.map((tool) => ({
|
|
name: tool.name,
|
|
description: tool.description,
|
|
- parameters: tool.parameters,
|
|
+ parameters: sanitizeSchemaForGoogle(tool.parameters),
|
|
})),
|
|
},
|
|
];
|