UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with external MCP server integration, multi-provider support, and professional CLI. Connect to 65+ MCP servers for filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 9 major pr

217 lines (216 loc) 8.72 kB
import { createGoogleGenerativeAI } from '@ai-sdk/google'; import { streamText, generateText, Output } from 'ai'; import { logger } from '../utils/logger.js'; // Default system context const DEFAULT_SYSTEM_CONTEXT = { systemPrompt: 'You are a helpful AI assistant.' }; // Configuration helpers const getGoogleAIApiKey = () => { const apiKey = process.env.GOOGLE_AI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY; if (!apiKey) { throw new Error('GOOGLE_AI_API_KEY environment variable is not set'); } return apiKey; }; const getGoogleAIModelId = () => { return process.env.GOOGLE_AI_MODEL || 'gemini-1.5-pro-latest'; }; const hasValidAuth = () => { return !!(process.env.GOOGLE_AI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY); }; // Lazy initialization cache let _google = null; function getGoogleInstance() { if (!_google) { const apiKey = getGoogleAIApiKey(); _google = createGoogleGenerativeAI({ apiKey: apiKey, headers: { 'X-Powered-By': 'NeuroLink' } }); } return _google; } // Google AI Studio class with enhanced error handling export class GoogleAIStudio { modelName; /** * Initializes a new instance of GoogleAIStudio * @param modelName - Optional model name to override the default from config */ constructor(modelName) { const functionTag = 'GoogleAIStudio.constructor'; this.modelName = modelName || getGoogleAIModelId(); try { logger.debug(`[${functionTag}] Initialization started`, { modelName: this.modelName, hasApiKey: hasValidAuth() }); logger.debug(`[${functionTag}] Initialization completed`, { modelName: this.modelName, success: true }); } catch (err) { logger.error(`[${functionTag}] Initialization failed`, { message: 'Error in initializing Google AI Studio', modelName: this.modelName, error: err instanceof Error ? err.message : String(err), stack: err instanceof Error ? err.stack : undefined }); } } /** * Gets the appropriate model instance * @private */ getModel() { logger.debug('GoogleAIStudio.getModel - Google AI model selected', { modelName: this.modelName }); const google = getGoogleInstance(); return google(this.modelName); } /** * Processes text using streaming approach with enhanced error handling callbacks * @param prompt - The input text prompt to analyze * @param analysisSchema - Optional Zod schema or Schema object for output validation * @returns Promise resolving to StreamTextResult or null if operation fails */ async streamText(optionsOrPrompt, analysisSchema) { const functionTag = 'GoogleAIStudio.streamText'; const provider = 'google-ai'; let chunkCount = 0; try { // Parse parameters - support both string and options object const options = typeof optionsOrPrompt === 'string' ? { prompt: optionsOrPrompt } : optionsOrPrompt; const { prompt, temperature = 0.7, maxTokens = 500, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema } = options; // Use schema from options or fallback parameter const finalSchema = schema || analysisSchema; logger.debug(`[${functionTag}] Stream request started`, { provider, modelName: this.modelName, promptLength: prompt.length, temperature, maxTokens, hasSchema: !!finalSchema }); const model = this.getModel(); const streamOptions = { model: model, prompt: prompt, system: systemPrompt, temperature, maxTokens, onError: (event) => { const error = event.error; const errorMessage = error instanceof Error ? error.message : String(error); const errorStack = error instanceof Error ? error.stack : undefined; logger.error(`[${functionTag}] Stream text error`, { provider, modelName: this.modelName, error: errorMessage, stack: errorStack, promptLength: prompt.length, chunkCount }); }, onFinish: (event) => { logger.debug(`[${functionTag}] Stream text finished`, { provider, modelName: this.modelName, finishReason: event.finishReason, usage: event.usage, totalChunks: chunkCount, promptLength: prompt.length, responseLength: event.text?.length || 0 }); }, onChunk: (event) => { chunkCount++; logger.debug(`[${functionTag}] Stream text chunk`, { provider, modelName: this.modelName, chunkNumber: chunkCount, chunkLength: event.chunk.text?.length || 0, chunkType: event.chunk.type }); } }; if (analysisSchema) { streamOptions.experimental_output = Output.object({ schema: analysisSchema }); } const result = streamText(streamOptions); return result; } catch (err) { logger.error(`[${functionTag}] Exception`, { provider, modelName: this.modelName, message: 'Error in streaming text', err: String(err), promptLength: typeof optionsOrPrompt === 'string' ? optionsOrPrompt.length : optionsOrPrompt.prompt.length }); throw err; // Re-throw error to trigger fallback } } /** * Processes text using non-streaming approach with optional schema validation * @param prompt - The input text prompt to analyze * @param analysisSchema - Optional Zod schema or Schema object for output validation * @returns Promise resolving to GenerateTextResult or null if operation fails */ async generateText(optionsOrPrompt, analysisSchema) { const functionTag = 'GoogleAIStudio.generateText'; const provider = 'google-ai'; try { // Parse parameters - support both string and options object const options = typeof optionsOrPrompt === 'string' ? { prompt: optionsOrPrompt } : optionsOrPrompt; const { prompt, temperature = 0.7, maxTokens = 500, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema } = options; // Use schema from options or fallback parameter const finalSchema = schema || analysisSchema; logger.debug(`[${functionTag}] Generate request started`, { provider, modelName: this.modelName, promptLength: prompt.length, temperature, maxTokens }); const model = this.getModel(); const generateOptions = { model: model, prompt: prompt, system: systemPrompt, temperature, maxTokens }; if (finalSchema) { generateOptions.experimental_output = Output.object({ schema: finalSchema }); } const result = await generateText(generateOptions); logger.debug(`[${functionTag}] Generate text completed`, { provider, modelName: this.modelName, usage: result.usage, finishReason: result.finishReason, responseLength: result.text?.length || 0 }); return result; } catch (err) { logger.error(`[${functionTag}] Exception`, { provider, modelName: this.modelName, message: 'Error in generating text', err: String(err) }); throw err; // Re-throw error to trigger fallback } } }