UNPKG

prprompts-flutter-generator

Version:

AI-powered Flutter development with full automation + official extension support - Generate 32 security-audited guides & auto-implement in 2-3 hours. NEW v5.1: Official Claude Code plugin with hooks, Gemini TOML commands, Qwen MCP settings. Features: Comp

304 lines (258 loc) 7.88 kB
/** * Gemini AI Client Implementation * Google Gemini API integration for code enhancement */ const AIClient = require('./AIClient'); const https = require('https'); class GeminiClient extends AIClient { constructor(config = {}) { super({ apiKey: config.apiKey || process.env.GEMINI_API_KEY, model: config.model || 'gemini-pro', ...config }); this.apiUrl = 'generativelanguage.googleapis.com'; } /** * Enhance Flutter code with AI improvements */ async enhance(code, context) { const cacheKey = this._getCacheKey('enhance', { code: code.substring(0, 200), context }); const cached = this._getCached(cacheKey); if (cached) return cached; const prompt = this._buildEnhancePrompt(code, context); const response = await this._makeRequest(prompt); try { const result = this._parseJSON(response); this._setCache(cacheKey, result); return result; } catch (error) { return { enhanced_code: code, changes: [{ type: 'note', description: 'AI enhancement failed, using original code', reason: error.message }], confidence: 0.5 }; } } /** * Optimize widget structure */ async optimize(widgetTree) { const cacheKey = this._getCacheKey('optimize', { widgetTree }); const cached = this._getCached(cacheKey); if (cached) return cached; const prompt = this._buildOptimizePrompt(widgetTree); const response = await this._makeRequest(prompt); const result = this._parseJSON(response); this._setCache(cacheKey, result); return result; } /** * Generate improvement suggestions */ async suggest(code, context) { const cacheKey = this._getCacheKey('suggest', { code: code.substring(0, 200), context }); const cached = this._getCached(cacheKey); if (cached) return cached; const prompt = this._buildSuggestPrompt(code, context); const response = await this._makeRequest(prompt); const result = this._parseJSON(response); this._setCache(cacheKey, result); return result; } /** * Validate generated code */ async validate(code, options = {}) { const cacheKey = this._getCacheKey('validate', { code: code.substring(0, 200), options }); const cached = this._getCached(cacheKey); if (cached) return cached; const prompt = this._buildValidatePrompt(code, options); const response = await this._makeRequest(prompt); const result = this._parseJSON(response); this._setCache(cacheKey, result); return result; } /** * Build enhancement prompt (same as Claude) * @private */ _buildEnhancePrompt(code, context) { const { reactCode, componentName, feature } = context; return `You are a Flutter expert. Improve the following Dart code generated from React. **Original React Component:** ${reactCode ? reactCode.substring(0, 500) + '...' : 'N/A'} **Generated Flutter Code:** ${code} **Context:** - Component: ${componentName || 'Unknown'} - Feature: ${feature || 'Unknown'} **Enhancement Goals:** 1. Better variable/method naming (Flutter conventions) 2. More idiomatic Dart code 3. Performance optimizations (const constructors) 4. Proper error handling 5. Comments for complex logic **Output Format (JSON only):** \`\`\`json { "enhanced_code": "complete enhanced code here", "changes": [ { "type": "naming | performance | error_handling | idiomatic | comments", "description": "What was changed", "reason": "Why this improvement matters" } ], "confidence": 0.95 } \`\`\``; } /** * Build optimization prompt * @private */ _buildOptimizePrompt(widgetTree) { return `Analyze this Flutter widget tree and suggest optimizations. **Widget Tree:** ${JSON.stringify(widgetTree, null, 2)} **Output Format (JSON only):** \`\`\`json { "optimizations": [ { "type": "const | extraction | rebuild | performance | keys", "widget": "widget name", "suggestion": "specific improvement", "impact": "high | medium | low", "code_snippet": "example code" } ], "overall_score": 0.85, "summary": "widget tree health summary" } \`\`\``; } /** * Build suggestion prompt * @private */ _buildSuggestPrompt(code, context) { return `Review this Flutter code and provide improvement suggestions. **Code:** ${code} **Context:** ${JSON.stringify(context, null, 2)} **Output Format (JSON only):** \`\`\`json { "suggestions": [ { "category": "organization | state | errors | performance | accessibility | testing", "priority": "high | medium | low", "description": "what to improve", "example": "code example" } ], "quality_score": 0.85 } \`\`\``; } /** * Build validation prompt * @private */ _buildValidatePrompt(code, options) { const { checkAccessibility, checkPerformance, checkSecurity } = options; return `Validate this Flutter code for quality and correctness. **Code:** ${code} **Validation Checks:** ${checkAccessibility ? '- Accessibility' : ''} ${checkPerformance ? '- Performance' : ''} ${checkSecurity ? '- Security' : ''} **Output Format (JSON only):** \`\`\`json { "valid": true, "issues": [ { "severity": "error | warning | info", "category": "accessibility | performance | security | null_safety | errors | best_practices", "description": "issue description", "line": 42, "suggestion": "how to fix" } ], "score": 0.92, "summary": "overall validation summary" } \`\`\``; } /** * Make API request to Gemini * @private */ async _makeRequest(prompt) { return this._makeRequestWithRetry(async () => { const payload = JSON.stringify({ contents: [ { parts: [ { text: prompt } ] } ], generationConfig: { temperature: this.config.temperature, maxOutputTokens: this.config.maxTokens } }); return new Promise((resolve, reject) => { const options = { hostname: this.apiUrl, path: `/v1beta/models/${this.config.model}:generateContent?key=${this.config.apiKey}`, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) } }; const req = https.request(options, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { if (res.statusCode !== 200) { reject(new Error(`Gemini API error ${res.statusCode}: ${data}`)); return; } try { const json = JSON.parse(data); // Track token usage (Gemini doesn't provide detailed usage in response) this.tokenUsage.totalTokens += 1000; // Estimate this.tokenUsage.requestCount++; const content = json.candidates?.[0]?.content?.parts?.[0]?.text || ''; resolve(content); } catch (error) { reject(new Error(`Failed to parse Gemini response: ${error.message}`)); } }); }); req.on('error', (error) => { reject(new Error(`Gemini API request failed: ${error.message}`)); }); req.write(payload); req.end(); }); }); } } module.exports = GeminiClient;