Files
claude-task-master/src/ai-providers/google.js
Eyal Toledano e53d5e1577 feat(ai): Enhance Google provider telemetry and AI object response handling
This commit introduces two key improvements:

1.  **Google Provider Telemetry:**
    - Updated  to include token usage data (, ) in the responses from  and .
    - This aligns the Google provider with others for consistent AI usage telemetry.

2.  **Robust AI Object Response Handling:**
    - Modified  to more flexibly handle responses from .
    - The add-task module now check for the AI-generated object in both  and , improving compatibility with different AI provider response structures (e.g., Gemini).

These changes enhance the reliability of AI interactions, particularly with the Google provider, and ensure accurate telemetry collection.
2025-05-13 12:13:35 -04:00

184 lines
6.4 KiB
JavaScript

/**
* google.js
* AI provider implementation for Google AI models (e.g., Gemini) using Vercel AI SDK.
*/
// import { GoogleGenerativeAI } from '@ai-sdk/google'; // Incorrect import
import { createGoogleGenerativeAI } from '@ai-sdk/google'; // Correct import for customization
import { generateText, streamText, generateObject } from 'ai'; // Import from main 'ai' package
import { log } from '../../scripts/modules/utils.js'; // Import logging utility
// Consider making model configurable via config-manager.js later
const DEFAULT_MODEL = 'gemini-2.5-pro-exp-03-25'; // Or a suitable default
const DEFAULT_TEMPERATURE = 0.2; // Or a suitable default
/**
* Generates text using a Google AI model.
*
* @param {object} params - Parameters for the generation.
* @param {string} params.apiKey - Google API Key.
* @param {string} params.modelId - Specific model ID to use (overrides default).
* @param {number} params.temperature - Generation temperature.
* @param {Array<object>} params.messages - The conversation history (system/user prompts).
* @param {number} [params.maxTokens] - Optional max tokens.
* @returns {Promise<string>} The generated text content.
* @throws {Error} If API key is missing or API call fails.
*/
async function generateGoogleText({
apiKey,
modelId = DEFAULT_MODEL,
temperature = DEFAULT_TEMPERATURE,
messages,
maxTokens // Note: Vercel SDK might handle this differently, needs verification
}) {
if (!apiKey) {
throw new Error('Google API key is required.');
}
log('info', `Generating text with Google model: ${modelId}`);
try {
// const google = new GoogleGenerativeAI({ apiKey }); // Incorrect instantiation
const googleProvider = createGoogleGenerativeAI({ apiKey }); // Correct instantiation
// const model = google.getGenerativeModel({ model: modelId }); // Incorrect model retrieval
const model = googleProvider(modelId); // Correct model retrieval
// Construct payload suitable for Vercel SDK's generateText
// Note: The exact structure might depend on how messages are passed
const result = await generateText({
model, // Pass the model instance
messages, // Pass the messages array directly
temperature,
maxOutputTokens: maxTokens // Map to correct Vercel SDK param if available
});
// Assuming result structure provides text directly or within a property
// return result.text; // Adjust based on actual SDK response
// Return both text and usage
return {
text: result.text,
usage: {
inputTokens: result.usage.promptTokens,
outputTokens: result.usage.completionTokens
}
};
} catch (error) {
log(
'error',
`Error generating text with Google (${modelId}): ${error.message}`
);
throw error; // Re-throw for unified service handler
}
}
/**
* Streams text using a Google AI model.
*
* @param {object} params - Parameters for the streaming.
* @param {string} params.apiKey - Google API Key.
* @param {string} params.modelId - Specific model ID to use (overrides default).
* @param {number} params.temperature - Generation temperature.
* @param {Array<object>} params.messages - The conversation history.
* @param {number} [params.maxTokens] - Optional max tokens.
* @returns {Promise<ReadableStream>} A readable stream of text deltas.
* @throws {Error} If API key is missing or API call fails.
*/
async function streamGoogleText({
apiKey,
modelId = DEFAULT_MODEL,
temperature = DEFAULT_TEMPERATURE,
messages,
maxTokens
}) {
if (!apiKey) {
throw new Error('Google API key is required.');
}
log('info', `Streaming text with Google model: ${modelId}`);
try {
// const google = new GoogleGenerativeAI({ apiKey }); // Incorrect instantiation
const googleProvider = createGoogleGenerativeAI({ apiKey }); // Correct instantiation
// const model = google.getGenerativeModel({ model: modelId }); // Incorrect model retrieval
const model = googleProvider(modelId); // Correct model retrieval
const stream = await streamText({
model, // Pass the model instance
messages,
temperature,
maxOutputTokens: maxTokens
});
return stream; // Return the stream directly
} catch (error) {
log(
'error',
`Error streaming text with Google (${modelId}): ${error.message}`
);
throw error;
}
}
/**
* Generates a structured object using a Google AI model.
*
* @param {object} params - Parameters for the object generation.
* @param {string} params.apiKey - Google API Key.
* @param {string} params.modelId - Specific model ID to use (overrides default).
* @param {number} params.temperature - Generation temperature.
* @param {Array<object>} params.messages - The conversation history.
* @param {import('zod').ZodSchema} params.schema - Zod schema for the expected object.
* @param {string} params.objectName - Name for the object generation context.
* @param {number} [params.maxTokens] - Optional max tokens.
* @returns {Promise<object>} The generated object matching the schema.
* @throws {Error} If API key is missing or API call fails.
*/
async function generateGoogleObject({
apiKey,
modelId = DEFAULT_MODEL,
temperature = DEFAULT_TEMPERATURE,
messages,
schema,
objectName, // Note: Vercel SDK might use this differently or not at all
maxTokens
}) {
if (!apiKey) {
throw new Error('Google API key is required.');
}
log('info', `Generating object with Google model: ${modelId}`);
try {
// const google = new GoogleGenerativeAI({ apiKey }); // Incorrect instantiation
const googleProvider = createGoogleGenerativeAI({ apiKey }); // Correct instantiation
// const model = google.getGenerativeModel({ model: modelId }); // Incorrect model retrieval
const model = googleProvider(modelId); // Correct model retrieval
const result = await generateObject({
model, // Pass the model instance
schema,
messages,
temperature,
maxOutputTokens: maxTokens
// Note: 'objectName' or 'mode' might not be directly applicable here
// depending on how `@ai-sdk/google` handles `generateObject`.
// Check SDK docs if specific tool calling/JSON mode needs explicit setup.
});
// return object; // Return the parsed object
// Return both object and usage
return {
object: result.object,
usage: {
inputTokens: result.usage.promptTokens,
outputTokens: result.usage.completionTokens
}
};
} catch (error) {
log(
'error',
`Error generating object with Google (${modelId}): ${error.message}`
);
throw error;
}
}
export { generateGoogleText, streamGoogleText, generateGoogleObject };