UNPKG

mcp-codesentry

Version:

CodeSentry MCP - AI-powered code review assistant with 5 specialized review tools for security, best practices, and comprehensive code analysis

180 lines (169 loc) 6.22 kB
/** * Google Gemini API Client * Handles interactions with Gemini for code reviews */ import { GoogleGenerativeAI } from '@google/generative-ai'; import { logger } from '../utils/logger.js'; export class GeminiClient { client; proModel; flashModel; config; constructor(config) { if (!config.apiKey) { throw new Error('Gemini API key is required'); } this.config = config; this.client = new GoogleGenerativeAI(config.apiKey); this.proModel = this.client.getGenerativeModel({ model: config.proModel }); this.flashModel = this.client.getGenerativeModel({ model: config.flashModel }); logger.info('Gemini client initialized'); } async reviewPlan(params) { logger.info(`Reviewing plan for task: ${params.taskId}`); const prompt = this.buildPlanReviewPrompt(params); try { // Use Pro model for plan reviews (more complex reasoning) const result = await this.proModel.generateContent({ contents: [{ role: 'user', parts: [{ text: prompt }] }], generationConfig: { temperature: 0.3, maxOutputTokens: 8192, responseMimeType: 'application/json' } }); const response = result.response; const text = response.text(); return this.parseReviewResponse(text, 'plan', params.taskId); } catch (error) { logger.error('Error calling Gemini API for plan review:', error); throw error; } } async reviewImplementation(params) { logger.info(`Reviewing implementation for task: ${params.taskId}`); const prompt = this.buildImplementationReviewPrompt(params); try { // Use Flash model for implementation reviews (faster, pattern matching) const result = await this.flashModel.generateContent({ contents: [{ role: 'user', parts: [{ text: prompt }] }], generationConfig: { temperature: 0.2, maxOutputTokens: 8192, responseMimeType: 'application/json' } }); const response = result.response; const text = response.text(); return this.parseReviewResponse(text, 'implementation', params.taskId); } catch (error) { logger.error('Error calling Gemini API for implementation review:', error); throw error; } } buildPlanReviewPrompt(params) { return `You are a senior software architect reviewing an implementation plan. Analyze the following plan and provide structured feedback. Task ID: ${params.taskId} Task Description: ${params.taskDescription} Implementation Plan: ${params.implementationPlan} Codebase Context: ${params.codebaseContext} Please provide a JSON response with the following structure: { "approved": boolean, "feedback": { "summary": "Brief overall assessment", "issues": ["List of critical issues or concerns"], "suggestions": ["List of recommendations"], "strengths": ["List of positive aspects"] }, "metadata": { "confidence": 0.0-1.0 } } Consider: 1. Architectural soundness 2. Security implications 3. Performance considerations 4. Maintainability 5. Alignment with task requirements 6. Best practices adherence`; } buildImplementationReviewPrompt(params) { return `You are a senior software architect reviewing a completed implementation. Compare the implementation against the original plan and provide structured feedback. Task ID: ${params.taskId} Task Description: ${params.taskDescription} Original Plan: ${params.originalPlan} Implementation Summary: ${params.implementationSummary} Current Codebase State: ${params.codebaseSnapshot} Please provide a JSON response with the following structure: { "approved": boolean, "feedback": { "summary": "Brief overall assessment", "issues": ["List of deviations or problems"], "suggestions": ["List of improvements"], "strengths": ["List of well-implemented aspects"] }, "metadata": { "confidence": 0.0-1.0 } } Consider: 1. Adherence to the original plan 2. Code quality and best practices 3. Test coverage 4. Documentation completeness 5. Security and performance 6. Any technical debt introduced`; } parseReviewResponse(responseText, reviewType, taskId) { try { const parsed = JSON.parse(responseText); return { approved: parsed.approved || false, reviewType, feedback: { summary: parsed.feedback?.summary || 'No summary provided', issues: parsed.feedback?.issues || [], suggestions: parsed.feedback?.suggestions || [], strengths: parsed.feedback?.strengths || [] }, metadata: { taskId, reviewedAt: new Date().toISOString(), modelUsed: reviewType === 'plan' ? this.config.proModel : this.config.flashModel, confidence: parsed.metadata?.confidence || 0.5 } }; } catch (error) { logger.error('Error parsing Gemini response:', error); logger.error('Raw response:', responseText); // Return a default response on parse error return { approved: false, reviewType, feedback: { summary: 'Error parsing review response', issues: ['Failed to parse AI response'], suggestions: ['Please retry the review'], strengths: [] }, metadata: { taskId, reviewedAt: new Date().toISOString(), modelUsed: reviewType === 'plan' ? this.config.proModel : this.config.flashModel, confidence: 0 } }; } } } //# sourceMappingURL=client.js.map