UNPKG

@robota-sdk/google

Version:

Google AI integration for Robota SDK - Gemini Pro, Gemini Flash, function calling, and tool integration with Google's Generative AI

1 lines 23.3 kB
{"version":3,"sources":["../src/adapter.ts","../src/provider.ts"],"names":["BaseAIProvider"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { UniversalMessage, UserMessage, AssistantMessage, SystemMessage, ToolMessage } from '@robota-sdk/core';\nimport type { Content, Part } from '@google/generative-ai';\n\n/**\n * Google AI ConversationHistory adapter\n * \n * Converts UniversalMessage to Google Generative AI format\n */\nexport class GoogleConversationAdapter {\n /**\n * Convert UniversalMessage array to Google AI message format\n */\n static toGoogleFormat(messages: UniversalMessage[]): Content[] {\n return messages\n .filter(msg => msg.role !== 'system') // System messages are handled separately\n .map(msg => this.convertMessage(msg));\n }\n\n /**\n * Convert a single UniversalMessage to Google AI format\n */\n static convertMessage(msg: UniversalMessage): Content {\n const messageRole = msg.role;\n\n // Handle user messages\n if (messageRole === 'user') {\n const userMsg = msg as UserMessage;\n return {\n role: 'user',\n parts: [{ text: userMsg.content }]\n };\n }\n\n // Handle assistant messages\n if (messageRole === 'assistant') {\n const assistantMsg = msg as AssistantMessage;\n if ((assistantMsg as any).toolCalls) {\n const parts: Part[] = [{ text: assistantMsg.content || '' }];\n\n // Add tool calls if they exist\n const toolCalls = (assistantMsg as any).toolCalls;\n for (const tc of toolCalls) {\n parts.push({\n functionCall: {\n name: tc.function.name,\n args: JSON.parse(tc.function.arguments)\n }\n } as Part);\n }\n\n return {\n role: 'model',\n parts\n };\n }\n return {\n role: 'model',\n parts: [{ text: assistantMsg.content || '' }]\n };\n }\n\n // Handle tool messages\n if (messageRole === 'tool') {\n const toolMsg = msg as ToolMessage;\n return {\n role: 'function',\n parts: [\n {\n functionResponse: {\n name: toolMsg.name || 'unknown',\n response: toolMsg.content\n }\n } as any\n ]\n };\n }\n\n // Handle system messages (convert to user)\n if (messageRole === 'system') {\n const systemMsg = msg as SystemMessage;\n return {\n role: 'user',\n parts: [{ text: `[System]: ${systemMsg.content}` }]\n };\n }\n\n // This should never happen but TypeScript requires exhaustive checking\n const _exhaustiveCheck: never = msg;\n return _exhaustiveCheck;\n }\n\n /**\n * Extract system messages and combine them as system instruction\n */\n static extractSystemInstruction(messages: UniversalMessage[], fallbackSystemPrompt?: string): string | undefined {\n const systemMessages = messages.filter(msg => msg.role === 'system') as SystemMessage[];\n\n if (systemMessages.length > 0) {\n return systemMessages.map(msg => msg.content).join('\\n\\n');\n }\n\n return fallbackSystemPrompt;\n }\n\n /**\n * Complete message conversion pipeline\n */\n static processMessages(\n messages: UniversalMessage[],\n systemPrompt?: string\n ): {\n contents: Content[],\n systemInstruction?: string\n } {\n // 1. Extract system instruction\n const systemInstruction = this.extractSystemInstruction(messages, systemPrompt);\n\n // 2. Convert messages to Google AI format\n const contents = this.toGoogleFormat(messages);\n\n return {\n contents,\n systemInstruction\n };\n }\n} ","import { GoogleGenerativeAI } from '@google/generative-ai';\nimport { BaseAIProvider } from '@robota-sdk/core';\nimport type {\n Context,\n ModelResponse,\n StreamingResponseChunk,\n UniversalMessage\n} from '@robota-sdk/core';\nimport type { FunctionSchema } from '@robota-sdk/tools';\nimport type { GoogleProviderOptions } from './types';\nimport { GoogleConversationAdapter } from './adapter';\n\n/**\n * Google AI provider implementation for Robota\n * \n * Provides integration with Google's Generative AI services including Gemini models.\n * Extends BaseAIProvider for common functionality and tool calling support.\n * \n * @see {@link ../../../apps/examples/03-integrations | Provider Integration Examples}\n * \n * @public\n */\nexport class GoogleProvider extends BaseAIProvider {\n /**\n * Provider identifier name\n * @readonly\n */\n public readonly name: string = 'google';\n\n /**\n * Google AI client instance\n * @internal\n */\n private readonly client: GoogleGenerativeAI;\n\n /**\n * Provider configuration options\n * @readonly\n */\n public readonly options: GoogleProviderOptions;\n\n /**\n * Create a new Google AI provider instance\n * \n * @param options - Configuration options for the Google provider\n * \n * @throws {Error} When client is not provided in options\n */\n constructor(options: GoogleProviderOptions) {\n super();\n\n this.options = {\n temperature: 0.7,\n maxTokens: undefined,\n ...options\n };\n\n // Validate required client injection\n if (!options.client) {\n throw new Error('Google AI client is not injected. The client option is required.');\n }\n\n this.client = options.client;\n }\n\n /**\n * Send a chat request to Google AI and receive a complete response\n * \n * @param model - Model name to use (e.g., 'gemini-1.5-pro', 'gemini-1.5-flash')\n * @param context - Context object containing messages and system prompt\n * @param options - Optional generation parameters and tools\n * @returns Promise resolving to the model's response\n * \n * @throws {Error} When context is invalid\n * @throws {Error} When messages array is invalid\n * @throws {Error} When Google AI API call fails\n */\n async chat(model: string, context: Context, options?: any): Promise<ModelResponse> {\n // Use base class validation\n this.validateContext(context);\n\n const { messages, systemPrompt } = context;\n\n try {\n // Convert UniversalMessage[] to Google AI format\n const { contents, systemInstruction } = GoogleConversationAdapter.processMessages(\n messages as UniversalMessage[],\n systemPrompt\n );\n\n // Configure tools if provided\n const toolConfig = this.configureTools(options?.tools);\n const modelConfig: any = {\n model: model || this.options.model || 'gemini-1.5-flash',\n systemInstruction: systemInstruction\n };\n\n // Add tools to model configuration if available\n if (toolConfig) {\n modelConfig.tools = toolConfig.tools;\n }\n\n // Get Google AI model instance\n const generativeModel = this.client.getGenerativeModel(modelConfig);\n\n // Configure generation parameters\n const generationConfig = {\n temperature: options?.temperature ?? this.options.temperature,\n maxOutputTokens: options?.maxTokens ?? this.options.maxTokens,\n ...(this.options.responseMimeType && {\n responseMimeType: this.options.responseMimeType\n }),\n ...(this.options.responseSchema && {\n responseSchema: this.options.responseSchema\n })\n };\n\n // Generate content\n const result = await generativeModel.generateContent({\n contents,\n generationConfig\n });\n\n return this.parseResponse(result);\n } catch (error) {\n this.handleApiError(error, 'chat');\n }\n }\n\n /**\n * Send a streaming chat request to Google AI and receive response chunks\n * \n * Generates an async iterator that yields response chunks as they arrive.\n * Useful for real-time display of responses or handling large responses incrementally.\n * \n * @param model - Model name to use\n * @param context - Context object containing messages and system prompt\n * @param options - Optional generation parameters and tools\n * @returns Async generator yielding response chunks\n * \n * @throws {Error} When context is invalid\n * @throws {Error} When messages array is invalid\n * @throws {Error} When Google AI API streaming call fails\n */\n async *chatStream(model: string, context: Context, options?: any): AsyncGenerator<StreamingResponseChunk, void, unknown> {\n // Use base class validation\n this.validateContext(context);\n\n const { messages, systemPrompt } = context;\n\n try {\n // Convert UniversalMessage[] to Google AI format\n const { contents, systemInstruction } = GoogleConversationAdapter.processMessages(\n messages as UniversalMessage[],\n systemPrompt\n );\n\n // Configure tools if provided\n const toolConfig = this.configureTools(options?.tools);\n const modelConfig: any = {\n model: model || this.options.model || 'gemini-1.5-flash',\n systemInstruction: systemInstruction\n };\n\n // Add tools to model configuration if available\n if (toolConfig) {\n modelConfig.tools = toolConfig.tools;\n }\n\n // Get Google AI model instance\n const generativeModel = this.client.getGenerativeModel(modelConfig);\n\n // Configure generation parameters\n const generationConfig = {\n temperature: options?.temperature ?? this.options.temperature,\n maxOutputTokens: options?.maxTokens ?? this.options.maxTokens,\n ...(this.options.responseMimeType && {\n responseMimeType: this.options.responseMimeType\n }),\n ...(this.options.responseSchema && {\n responseSchema: this.options.responseSchema\n })\n };\n\n // Generate streaming content\n const result = await generativeModel.generateContentStream({\n contents,\n generationConfig\n });\n\n for await (const chunk of result.stream) {\n yield this.parseStreamingChunk(chunk);\n }\n } catch (error) {\n this.handleApiError(error, 'chatStream');\n }\n }\n\n /**\n * Configure tools for Google AI API request\n * \n * Google AI supports function calling with Gemini models.\n * Transforms function schemas into Google AI tool format.\n * \n * @param tools - Array of function schemas\n * @returns Google AI tool configuration object or undefined\n */\n protected configureTools(tools?: FunctionSchema[]): { tools: any[] } | undefined {\n if (!tools || !Array.isArray(tools)) {\n return undefined;\n }\n\n return {\n tools: [{\n functionDeclarations: tools.map(fn => ({\n name: fn.name,\n description: fn.description || '',\n parameters: fn.parameters\n }))\n }]\n };\n }\n\n /**\n * Parse Google AI response into universal ModelResponse format\n * \n * Extracts content, usage information, and metadata from the Google AI response\n * and converts it to the standard format used across all providers.\n * Supports function calling with Gemini models.\n * \n * @param response - Raw response from Google AI API\n * @returns Parsed model response in universal format\n * \n * @internal\n */\n parseResponse(response: any): ModelResponse {\n let content = '';\n const toolCalls: any[] = [];\n\n // Extract content and function calls from response\n const candidate = response.response?.candidates?.[0];\n if (candidate?.content?.parts) {\n for (const part of candidate.content.parts) {\n if (part.text) {\n content += part.text;\n } else if (part.functionCall) {\n // Convert Google AI function call to OpenAI format for consistency\n toolCalls.push({\n id: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: 'function' as const,\n function: {\n name: part.functionCall.name,\n arguments: JSON.stringify(part.functionCall.args || {})\n }\n });\n }\n }\n }\n\n // Extract usage information from response if available\n const usageMetadata = response.response?.usageMetadata;\n const usage = usageMetadata ? {\n promptTokens: usageMetadata.promptTokenCount || 0,\n completionTokens: usageMetadata.candidatesTokenCount || 0,\n totalTokens: usageMetadata.totalTokenCount || 0\n } : {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0\n };\n\n const result: ModelResponse = {\n content: content || undefined,\n usage,\n metadata: {\n model: response.response?.model,\n finishReason: candidate?.finishReason,\n safetyRatings: candidate?.safetyRatings\n }\n };\n\n // Add tool calls if present\n if (toolCalls.length > 0) {\n result.toolCalls = toolCalls;\n }\n\n return result;\n }\n\n /**\n * Parse Google AI streaming response chunk into universal format\n * \n * Converts individual chunks from the streaming response into the standard\n * StreamingResponseChunk format used across all providers.\n * \n * @param chunk - Raw chunk from Google AI streaming API\n * @returns Parsed streaming response chunk\n * \n * @internal\n */\n parseStreamingChunk(chunk: any): StreamingResponseChunk {\n const text = chunk.text() || '';\n\n // Determine if this is the final chunk\n const candidate = chunk.candidates?.[0];\n const isComplete = candidate?.finishReason !== undefined && candidate.finishReason !== null;\n\n return {\n content: text,\n isComplete\n };\n }\n\n /**\n * Release resources and close connections\n * \n * Performs cleanup operations when the provider is no longer needed.\n * Google AI client doesn't require explicit cleanup, so this is a no-op.\n * \n * @returns Promise that resolves when cleanup is complete\n */\n async close(): Promise<void> {\n // Google AI client doesn't have explicit close method\n // This is implemented as no-op for interface compliance\n }\n} "]}