UNPKG

@semantest/chrome-extension

Version:

Browser extension for ChatGPT-buddy - AI automation extension built on Web-Buddy framework

1,317 lines 104 kB
/** * @fileoverview ChatGPT Buddy Plugin Implementation * @description AI-powered automation plugin for ChatGPT and language models */ /** * ChatGPT Plugin Events */ export const ChatGPTPluginEvents = { // AI Interaction Events AI_INTERACTION_REQUESTED: 'chatgpt:interaction:requested', AI_RESPONSE_RECEIVED: 'chatgpt:response:received', AI_MODEL_SWITCHED: 'chatgpt:model:switched', // Training Events TRAINING_MODE_ENABLED: 'chatgpt:training:enabled', TRAINING_PATTERN_LEARNED: 'chatgpt:training:pattern:learned', TRAINING_SESSION_COMPLETED: 'chatgpt:training:session:completed', // Automation Events CHATGPT_MESSAGE_SENT: 'chatgpt:message:sent', CHATGPT_RESPONSE_EXTRACTED: 'chatgpt:response:extracted', CONVERSATION_STARTED: 'chatgpt:conversation:started', // Performance Events AI_PERFORMANCE_UPDATED: 'chatgpt:performance:updated', OPTIMIZATION_SUGGESTED: 'chatgpt:optimization:suggested' }; /** * ChatGPT Web Application Contracts */ const chatGPTContracts = [ { version: "1.0.0", domain: "chat.openai.com", title: "ChatGPT Interface Contract", description: "Automation contract for ChatGPT web interface", capabilities: { sendMessage: { type: "action", description: "Send a message to ChatGPT", selector: "textarea[data-id='root']", parameters: [ { name: "message", type: "string", description: "Message to send to ChatGPT", required: true } ], returnType: { type: "object", description: "Send operation result" } }, getResponse: { type: "query", description: "Extract ChatGPT's latest response", selector: "[data-message-author-role='assistant']:last-child", returnType: { type: "string", description: "ChatGPT's response text" } }, startNewConversation: { type: "action", description: "Start a new conversation", selector: "[data-testid='new-chat-button'], .text-token-text-primary", returnType: { type: "void", description: "New conversation started" } }, selectModel: { type: "action", description: "Select GPT model", selector: "[data-testid='model-selector']", parameters: [ { name: "model", type: "string", description: "Model to select (gpt-4, gpt-3.5-turbo, etc.)", required: true, enum: ["gpt-4", "gpt-4-turbo", "gpt-3.5-turbo"] } ] }, getConversationHistory: { type: "query", description: "Get the full conversation history", selector: "[data-testid='conversation-turn']", returnType: { type: "array", description: "Array of conversation messages" } }, enableBrowsing: { type: "action", description: "Enable web browsing capability", selector: "[data-testid='browsing-toggle']" }, enablePlugins: { type: "action", description: "Enable ChatGPT plugins", selector: "[data-testid='plugins-toggle']" } }, context: { urlPatterns: [ "https://chat.openai.com/*", "https://chatgpt.com/*" ], accessibility: { ariaCompliant: true, keyboardNavigation: true }, performance: { maxExecutionTime: 30000, cacheResults: true } } }, { version: "1.0.0", domain: "claude.ai", title: "Claude AI Interface Contract", description: "Automation contract for Claude AI web interface", capabilities: { sendMessage: { type: "action", description: "Send a message to Claude", selector: "[data-testid='chat-input']", parameters: [ { name: "message", type: "string", description: "Message to send to Claude", required: true } ] }, getResponse: { type: "query", description: "Extract Claude's latest response", selector: "[data-testid='message']:last-child", returnType: { type: "string", description: "Claude's response text" } }, startNewConversation: { type: "action", description: "Start a new conversation with Claude", selector: "[data-testid='new-chat']" } }, context: { urlPatterns: [ "https://claude.ai/*" ] } } ]; /** * ChatGPT Buddy Plugin - Main plugin implementation */ export class ChatGPTBuddyPlugin { constructor() { this.id = 'chatgpt-buddy'; this.name = 'ChatGPT Buddy'; this.version = '2.0.0'; this.description = 'AI-powered automation for ChatGPT and language models'; this.author = 'rydnr'; this.metadata = { id: this.id, name: this.name, version: this.version, description: this.description, author: this.author, license: 'MIT', repository: 'https://github.com/rydnr/chatgpt-buddy' }; this.capabilities = { supportedDomains: [ 'chat.openai.com', 'chatgpt.com', 'claude.ai', 'beta.character.ai' ], contractDefinitions: chatGPTContracts, permissions: [ 'activeTab', 'storage', 'background', 'webRequest' ], requiredAPIs: [ 'chrome.tabs', 'chrome.storage', 'chrome.runtime', 'chrome.webRequest' ] }; this.state = 'uninitialized'; } /** * Initialize the plugin */ async initialize(context) { try { this.context = context; this.state = 'initialized'; // Initialize core services this.aiModelManager = new AIModelManager(context); this.trainingManager = new TrainingManager(context); this.automationEngine = new AutomationEngine(context); this.performanceTracker = new PerformanceTracker(context); // Set up event listeners this.setupEventListeners(); // Load plugin configuration const config = await this.loadConfiguration(); await this.applyConfiguration(config); context.logger.info('ChatGPT Buddy Plugin initialized successfully'); } catch (error) { this.state = 'error'; throw error; } } /** * Activate the plugin */ async activate() { if (!this.context) { throw new Error('Plugin not initialized'); } try { this.state = 'active'; // Start core services await this.aiModelManager?.start(); await this.trainingManager?.start(); await this.automationEngine?.start(); await this.performanceTracker?.start(); // Register contracts for (const contract of chatGPTContracts) { await this.context.contractRegistry.register(contract); } // Emit activation event await this.context.eventBus.emit({ type: ChatGPTPluginEvents.AI_INTERACTION_REQUESTED, source: this.id, data: { activated: true }, timestamp: new Date().toISOString() }); this.context.logger.info('ChatGPT Buddy Plugin activated successfully'); } catch (error) { this.state = 'error'; throw error; } } /** * Deactivate the plugin */ async deactivate() { if (!this.context) { return; } try { this.state = 'inactive'; // Stop core services await this.aiModelManager?.stop(); await this.trainingManager?.stop(); await this.automationEngine?.stop(); await this.performanceTracker?.stop(); // Unregister contracts for (const contract of chatGPTContracts) { await this.context.contractRegistry.unregister(contract.domain + ':' + contract.title); } this.context.logger.info('ChatGPT Buddy Plugin deactivated'); } catch (error) { this.context.logger.error('Error deactivating ChatGPT Buddy Plugin', error); throw error; } } /** * Destroy the plugin */ async destroy() { if (!this.context) { return; } try { this.state = 'destroyed'; // Cleanup all services await this.aiModelManager?.destroy(); await this.trainingManager?.destroy(); await this.automationEngine?.destroy(); await this.performanceTracker?.destroy(); // Clear references this.aiModelManager = undefined; this.trainingManager = undefined; this.automationEngine = undefined; this.performanceTracker = undefined; this.context = undefined; } catch (error) { console.error('Error destroying ChatGPT Buddy Plugin:', error); throw error; } } /** * Get plugin contracts */ getContracts() { return [...chatGPTContracts]; } /** * Execute a plugin capability */ async executeCapability(capability, params) { if (!this.context || this.state !== 'active') { throw new Error('Plugin not active'); } try { switch (capability) { case 'sendMessage': return await this.sendMessage(params.message, params.options); case 'getResponse': return await this.getLatestResponse(params.options); case 'startNewConversation': return await this.startNewConversation(); case 'selectModel': return await this.selectAIModel(params.model); case 'enableTraining': return await this.enableTrainingMode(params.options); case 'learnPattern': return await this.learnAutomationPattern(params.pattern); case 'getInsights': return await this.getAIInsights(params.options); default: throw new Error(`Unknown capability: ${capability}`); } } catch (error) { this.context.logger.error(`Failed to execute capability: ${capability}`, error); throw error; } } /** * Validate capability parameters */ async validateCapability(capability, params) { const errors = []; switch (capability) { case 'sendMessage': if (!params.message || typeof params.message !== 'string') { errors.push('Message parameter is required and must be a string'); } break; case 'selectModel': const validModels = ['gpt-4', 'gpt-4-turbo', 'gpt-3.5-turbo', 'claude-3-opus', 'claude-3-sonnet']; if (!params.model || !validModels.includes(params.model)) { errors.push(`Model must be one of: ${validModels.join(', ')}`); } break; default: errors.push(`Unknown capability: ${capability}`); } return { valid: errors.length === 0, errors }; } /** * Get UI components */ getUIComponents() { if (!this.context) return []; return [ this.context.createUIComponent({ type: 'overlay', name: 'ChatGPT Training Interface', description: 'Interactive training overlay for ChatGPT automation', render: () => this.renderTrainingOverlay() }), this.context.createUIComponent({ type: 'popup', name: 'AI Model Selector', description: 'Select and configure AI models', render: () => this.renderModelSelector() }), this.context.createUIComponent({ type: 'sidebar', name: 'Automation Pattern Library', description: 'Manage learned automation patterns', render: () => this.renderPatternLibrary() }), this.context.createUIComponent({ type: 'panel', name: 'AI Insights Dashboard', description: 'View AI performance metrics and suggestions', render: () => this.renderInsightsDashboard() }) ]; } /** * Get menu items */ getMenuItems() { if (!this.context) return []; return [ this.context.createMenuItem({ label: 'Enable Training Mode', description: 'Start training ChatGPT automation patterns', icon: '🎓', shortcut: 'Ctrl+Shift+T', action: () => this.enableTrainingMode() }), this.context.createMenuItem({ label: 'Select AI Model', description: 'Choose preferred AI model', icon: '🤖', action: () => this.showModelSelector() }), this.context.createMenuItem({ label: 'View Pattern Library', description: 'Manage automation patterns', icon: '📚', action: () => this.showPatternLibrary() }), this.context.createMenuItem({ label: 'AI Insights', description: 'View performance metrics', icon: '📊', action: () => this.showInsightsDashboard() }), this.context.createMenuItem({ label: 'Plugin Settings', description: 'Configure ChatGPT Buddy settings', icon: '⚙️', action: () => this.showSettings() }) ]; } /** * Handle plugin events */ async onEvent(event) { if (!this.context) return; try { switch (event.type) { case 'tab:activated': await this.handleTabActivated(event.data); break; case 'automation:pattern:detected': await this.handlePatternDetected(event.data); break; case 'training:session:started': await this.handleTrainingSessionStarted(event.data); break; case ChatGPTPluginEvents.AI_MODEL_SWITCHED: await this.handleModelSwitched(event.data); break; default: this.context.logger.debug(`Unhandled event: ${event.type}`); } } catch (error) { this.context.logger.error(`Error handling event: ${event.type}`, error); } } /** * Get default configuration */ getDefaultConfig() { return { enabled: true, settings: { // AI Model Preferences preferredModel: 'gpt-4', fallbackModel: 'gpt-3.5-turbo', // Training Settings enableTrainingMode: true, autoLearnPatterns: true, trainingConfidenceThreshold: 0.8, // Performance Settings enablePatternRecognition: true, enableAIInsights: true, cacheResponses: true, maxResponseTime: 30000, // UI Preferences showTrainingOverlay: true, enableKeyboardShortcuts: true, notificationLevel: 'normal', // API Configuration apiKeys: {}, rateLimits: { requestsPerMinute: 60, maxDailyCost: 10.0 } }, domains: this.capabilities.supportedDomains, permissions: this.capabilities.permissions, uiPreferences: { theme: 'auto', language: 'en', notifications: true } }; } /** * Handle configuration changes */ async onConfigChange(config) { if (!this.context) return; try { await this.applyConfiguration(config); this.context.logger.info('ChatGPT Buddy Plugin configuration updated'); } catch (error) { this.context.logger.error('Failed to apply configuration changes', error); throw error; } } /** * Health check */ async healthCheck() { const issues = []; try { // Check plugin state if (this.state !== 'active') { issues.push(`Plugin is in ${this.state} state`); } // Check services if (!this.aiModelManager) { issues.push('AI Model Manager not initialized'); } if (!this.trainingManager) { issues.push('Training Manager not initialized'); } if (!this.automationEngine) { issues.push('Automation Engine not initialized'); } // Check context if (!this.context) { issues.push('Plugin context not available'); } return { healthy: issues.length === 0, issues }; } catch (error) { issues.push(`Health check failed: ${error.message}`); return { healthy: false, issues }; } } /** * Get plugin metrics */ async getMetrics() { const metrics = { pluginId: this.id, version: this.version, state: this.state, uptime: Date.now() - this.metadata.initTime || 0 }; try { if (this.performanceTracker) { const perfMetrics = await this.performanceTracker.getMetrics(); metrics.performance = perfMetrics; } if (this.trainingManager) { const trainingMetrics = await this.trainingManager.getMetrics(); metrics.training = trainingMetrics; } if (this.automationEngine) { const automationMetrics = await this.automationEngine.getMetrics(); metrics.automation = automationMetrics; } } catch (error) { metrics.error = error.message; } return metrics; } // Private helper methods setupEventListeners() { if (!this.context) return; // Listen for domain-specific events this.context.eventBus.on('chatgpt:*', (event) => this.onEvent(event)); this.context.eventBus.on('automation:*', (event) => this.onEvent(event)); this.context.eventBus.on('training:*', (event) => this.onEvent(event)); } async loadConfiguration() { if (!this.context) return this.getDefaultConfig(); try { const storedConfig = await this.context.storageService.getConfig(); return { ...this.getDefaultConfig(), ...storedConfig }; } catch (error) { this.context.logger.warn('Failed to load configuration, using defaults', error); return this.getDefaultConfig(); } } async applyConfiguration(config) { if (!this.context) return; // Apply configuration to services await this.aiModelManager?.configure(config.settings); await this.trainingManager?.configure(config.settings); await this.automationEngine?.configure(config.settings); await this.performanceTracker?.configure(config.settings); // Save configuration await this.context.storageService.setConfig(config); } // Core functionality methods implementation async sendMessage(message, options) { if (!this.automationEngine) { throw new Error('Automation engine not initialized'); } try { const startTime = Date.now(); // Use automation engine to send message const result = await this.automationEngine.sendMessage(message, options); const responseTime = Date.now() - startTime; // Record performance data if (this.performanceTracker) { await this.performanceTracker.recordPerformanceData({ responseTime, accuracy: 0.9, // Default, should be measured userSatisfaction: 0.8, // Default cost: this.calculateMessageCost(message, options?.model), errorOccurred: false, requestId: this.generateRequestId(), modelUsed: options?.model || this.aiModelManager?.getCurrentModel() || 'default', operationType: 'sendMessage' }); } // Emit event await this.context.eventBus.emit({ type: ChatGPTPluginEvents.CHATGPT_MESSAGE_SENT, source: this.id, data: { message, options, responseTime, success: true }, timestamp: new Date().toISOString() }); return { success: true, messageId: this.generateRequestId(), timestamp: new Date() }; } catch (error) { this.context.logger.error('Failed to send message', error); // Record error if (this.performanceTracker) { await this.performanceTracker.recordPerformanceData({ responseTime: 0, accuracy: 0, userSatisfaction: 0, errorOccurred: true, requestId: this.generateRequestId(), modelUsed: options?.model || 'unknown', operationType: 'sendMessage' }); } throw error; } } async getLatestResponse(options) { if (!this.automationEngine) { throw new Error('Automation engine not initialized'); } try { const startTime = Date.now(); // Use automation engine to extract response const response = await this.automationEngine.extractResponse(options); const responseTime = Date.now() - startTime; // Emit event await this.context.eventBus.emit({ type: ChatGPTPluginEvents.CHATGPT_RESPONSE_EXTRACTED, source: this.id, data: { response, responseTime, length: response.length }, timestamp: new Date().toISOString() }); return response; } catch (error) { this.context.logger.error('Failed to get latest response', error); throw error; } } async startNewConversation() { if (!this.automationEngine) { throw new Error('Automation engine not initialized'); } try { await this.automationEngine.startNewConversation(); // Emit event await this.context.eventBus.emit({ type: ChatGPTPluginEvents.CONVERSATION_STARTED, source: this.id, data: { timestamp: new Date().toISOString() }, timestamp: new Date().toISOString() }); this.context.logger.info('New conversation started successfully'); } catch (error) { this.context.logger.error('Failed to start new conversation', error); throw error; } } async selectAIModel(model) { if (!this.aiModelManager) { throw new Error('AI Model Manager not initialized'); } try { // Switch model using AI Model Manager await this.aiModelManager.switchToModel(model, 'user_preference'); // Use automation engine to select model in UI if available if (this.automationEngine) { try { await this.automationEngine.selectModel(model); } catch (uiError) { this.context.logger.warn('Failed to select model in UI, but model manager updated', uiError); } } this.context.logger.info(`AI model selected: ${model}`); } catch (error) { this.context.logger.error('Failed to select AI model', error); throw error; } } async enableTrainingMode(options) { if (!this.trainingManager) { throw new Error('Training Manager not initialized'); } try { await this.trainingManager.enableTrainingMode(); this.context.logger.info('Training mode enabled'); } catch (error) { this.context.logger.error('Failed to enable training mode', error); throw error; } } async learnAutomationPattern(pattern) { if (!this.trainingManager) { throw new Error('Training Manager not initialized'); } try { // Start a training session for the pattern const sessionId = await this.trainingManager.startTrainingSession({ type: 'automation_pattern', description: pattern.description || 'User-defined automation pattern', expectedOutcome: pattern.expectedOutcome || 'Execute automation successfully', context: pattern.context || {} }); // Add the pattern as a training step await this.trainingManager.addTrainingStep(sessionId, { action: pattern.action, selector: pattern.selector, parameters: pattern.parameters, timestamp: new Date(), success: true }); // Complete the session const result = await this.trainingManager.endTrainingSession(sessionId, 'pattern_learned'); this.context.logger.info(`Automation pattern learned: ${result.patternsLearned.length} patterns created`); } catch (error) { this.context.logger.error('Failed to learn automation pattern', error); throw error; } } async getAIInsights(options) { const insights = { performance: {}, recommendations: [], trends: [], models: {}, training: {} }; try { // Gather performance insights if (this.performanceTracker) { const performanceMetrics = await this.performanceTracker.getMetrics(); insights.performance = performanceMetrics.current; insights.recommendations.push(...performanceMetrics.recommendations); insights.trends = performanceMetrics.trends; // Get optimization suggestions const optimizations = await this.performanceTracker.getOptimizationSuggestions(); insights.recommendations.push(...optimizations.map(opt => opt.recommendation)); } // Gather AI model insights if (this.aiModelManager) { const modelMetrics = await this.aiModelManager.getMetrics(); insights.models = { current: modelMetrics.currentModel, available: modelMetrics.availableModels, performance: modelMetrics.modelPerformance, switchHistory: modelMetrics.switchHistory }; // Get model recommendations if (options?.context) { const recommendation = await this.aiModelManager.recommendOptimalModel(options.context); insights.recommendations.push(`Consider switching to ${recommendation.modelId}: ${recommendation.reasoning}`); } } // Gather training insights if (this.trainingManager) { const trainingMetrics = await this.trainingManager.getMetrics(); insights.training = { mode: trainingMetrics.trainingMode, patterns: trainingMetrics.learnedPatterns, sessions: trainingMetrics.activeSessions, recentActivity: trainingMetrics.recentActivity }; // Get pattern recommendations const patterns = await this.trainingManager.getLearnedPatterns(); const validPatterns = patterns.filter(p => p.confidence > 0.8); if (validPatterns.length > 0) { insights.recommendations.push(`${validPatterns.length} high-confidence automation patterns available`); } } // Gather automation insights if (this.automationEngine) { const automationMetrics = await this.automationEngine.getMetrics(); insights.automation = { activeExecutions: automationMetrics.activeExecutions, successRate: automationMetrics.successRate, averageExecutionTime: automationMetrics.averageExecutionTime, recentErrors: automationMetrics.recentErrors }; } // Generate overall recommendations this.generateOverallRecommendations(insights); return insights; } catch (error) { this.context.logger.error('Failed to get AI insights', error); return { error: 'Failed to gather insights', message: error.message }; } } // UI rendering methods (to be implemented) async renderTrainingOverlay() { const overlay = document.createElement('div'); overlay.innerHTML = '<div>Training Overlay - Coming Soon</div>'; return overlay; } async renderModelSelector() { const selector = document.createElement('div'); selector.innerHTML = '<div>Model Selector - Coming Soon</div>'; return selector; } async renderPatternLibrary() { const library = document.createElement('div'); library.innerHTML = '<div>Pattern Library - Coming Soon</div>'; return library; } async renderInsightsDashboard() { const dashboard = document.createElement('div'); dashboard.innerHTML = '<div>AI Insights Dashboard - Coming Soon</div>'; return dashboard; } // Menu action methods (to be implemented) async showModelSelector() { // Implementation will be added in next step } async showPatternLibrary() { // Implementation will be added in next step } async showInsightsDashboard() { // Implementation will be added in next step } async showSettings() { // Implementation will be added in next step } // Event handlers (to be implemented) async handleTabActivated(data) { // Implementation will be added in next step } async handlePatternDetected(data) { // Implementation will be added in next step } async handleTrainingSessionStarted(data) { // Implementation will be added in next step } async handleModelSwitched(data) { this.context.logger.info('AI model switched', data); // Record model switch for performance tracking if (this.performanceTracker) { await this.performanceTracker.recordPerformanceData({ responseTime: 0, accuracy: 1, userSatisfaction: 0.8, cost: 0, errorOccurred: false, requestId: this.generateRequestId(), modelUsed: data.currentModel, operationType: 'model_switch' }); } } // Helper methods calculateMessageCost(message, model) { // Simplified cost calculation based on message length and model const baseCostPerToken = 0.002; // Default cost const estimatedTokens = Math.ceil(message.length / 4); // Rough estimation const modelMultiplier = this.getModelCostMultiplier(model || 'gpt-3.5-turbo'); return estimatedTokens * baseCostPerToken * modelMultiplier; } getModelCostMultiplier(model) { const multipliers = { 'gpt-4': 15, 'gpt-4-turbo': 7.5, 'gpt-3.5-turbo': 1, 'claude-3-opus': 18, 'claude-3-sonnet': 4 }; return multipliers[model] || 1; } generateRequestId() { return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } generateOverallRecommendations(insights) { // Add overall system recommendations based on all insights if (insights.performance?.responseTime?.current > 10000) { insights.recommendations.unshift('PRIORITY: Response time is critically high - consider model optimization'); } if (insights.performance?.errorRate?.current > 0.1) { insights.recommendations.unshift('PRIORITY: High error rate detected - review automation patterns'); } if (insights.training?.patterns > 10 && insights.performance?.successRate < 0.8) { insights.recommendations.push('Consider reviewing learned patterns for quality'); } if (insights.models?.switchHistory?.length > 5) { insights.recommendations.push('Frequent model switching detected - consider setting a preferred model'); } } } // Service classes implementation /** * AI Model Manager - Handles AI model selection, switching, and optimization */ class AIModelManager { constructor(context) { this.context = context; this.isStarted = false; this.availableModels = []; this.modelPerformance = new Map(); this.modelSwitchHistory = []; this.currentModel = 'gpt-3.5-turbo'; // Default model this.initializeAvailableModels(); } async start() { if (this.isStarted) return; this.context.logger.info('Starting AI Model Manager'); // Load saved model preferences const savedModel = await this.context.storageService.get('currentModel'); if (savedModel) { this.currentModel = savedModel; } // Load performance data const performanceData = await this.context.storageService.get('modelPerformance'); if (performanceData) { this.modelPerformance = new Map(performanceData); } // Set up event listeners this.context.eventBus.on(ChatGPTPluginEvents.AI_MODEL_SWITCHED, (event) => { this.handleModelSwitched(event); }); this.isStarted = true; this.context.logger.info('AI Model Manager started successfully'); } async stop() { if (!this.isStarted) return; // Save current state await this.context.storageService.set('currentModel', this.currentModel); await this.context.storageService.set('modelPerformance', Array.from(this.modelPerformance.entries())); this.isStarted = false; this.context.logger.info('AI Model Manager stopped'); } async destroy() { await this.stop(); this.modelPerformance.clear(); this.modelSwitchHistory = []; this.context.logger.info('AI Model Manager destroyed'); } async configure(settings) { if (settings.preferredModel && this.isModelAvailable(settings.preferredModel)) { await this.switchToModel(settings.preferredModel); } if (settings.fallbackModel) { await this.context.storageService.set('fallbackModel', settings.fallbackModel); } } async getMetrics() { return { currentModel: this.currentModel, availableModels: this.availableModels.length, modelPerformance: Object.fromEntries(this.modelPerformance), switchHistory: this.modelSwitchHistory.slice(-10), // Last 10 switches uptime: this.isStarted ? Date.now() - this.context.startTime : 0 }; } // Public API methods getCurrentModel() { return this.currentModel; } getAvailableModels() { return [...this.availableModels]; } async switchToModel(modelId, reason) { if (!this.isModelAvailable(modelId)) { throw new Error(`Model ${modelId} is not available`); } const previousModel = this.currentModel; this.currentModel = modelId; // Record the switch const switchEvent = { timestamp: new Date(), fromModel: previousModel, toModel: modelId, reason: reason || 'user_preference', success: true }; this.modelSwitchHistory.push(switchEvent); // Emit event await this.context.eventBus.emit({ type: ChatGPTPluginEvents.AI_MODEL_SWITCHED, source: 'ai-model-manager', data: { previousModel, currentModel: modelId, reason }, timestamp: new Date().toISOString() }); await this.context.storageService.set('currentModel', modelId); this.context.logger.info(`Switched from ${previousModel} to ${modelId}`); } async recommendOptimalModel(context) { const recommendations = []; for (const model of this.availableModels) { const performance = this.modelPerformance.get(model.id); let score = model.baseScore || 0.7; // Adjust score based on context if (context.taskType === 'code_generation' && model.capabilities.includes('code_generation')) { score += 0.2; } if (context.taskType === 'analysis' && model.capabilities.includes('analysis')) { score += 0.15; } if (context.complexityLevel === 'high' && model.tier === 'premium') { score += 0.1; } // Adjust based on performance history if (performance) { score += (performance.averageResponseTime < 5000 ? 0.1 : -0.1); score += (performance.successRate > 0.9 ? 0.1 : -0.05); score += (performance.userSatisfaction > 0.8 ? 0.05 : -0.05); } // Consider cost if specified if (context.costPreference === 'low' && model.costTier === 'low') { score += 0.1; } else if (context.costPreference === 'high' && model.costTier === 'high') { score += 0.05; } recommendations.push({ modelId: model.id, confidence: Math.min(1.0, Math.max(0.1, score)), reasoning: this.generateRecommendationReasoning(model, context, score), estimatedPerformance: this.estimateModelPerformance(model, context) }); } // Sort by confidence and return the best recommendations.sort((a, b) => b.confidence - a.confidence); return recommendations[0]; } async recordModelPerformance(data) { const existing = this.modelPerformance.get(data.modelId) || { modelId: data.modelId, totalRequests: 0, successfulRequests: 0, totalResponseTime: 0, averageResponseTime: 0, successRate: 0, totalCost: 0, averageCost: 0, userSatisfaction: 0, lastUpdated: new Date() }; // Update metrics existing.totalRequests++; if (data.success) existing.successfulRequests++; existing.totalResponseTime += data.responseTime; existing.averageResponseTime = existing.totalResponseTime / existing.totalRequests; existing.successRate = existing.successfulRequests / existing.totalRequests; existing.totalCost += data.cost || 0; existing.averageCost = existing.totalCost / existing.totalRequests; // Update user satisfaction (weighted average) if (data.userSatisfaction !== undefined) { existing.userSatisfaction = (existing.userSatisfaction * 0.8) + (data.userSatisfaction * 0.2); } existing.lastUpdated = new Date(); this.modelPerformance.set(data.modelId, existing); // Persist to storage periodically if (existing.totalRequests % 10 === 0) { await this.context.storageService.set('modelPerformance', Array.from(this.modelPerformance.entries())); } } // Private helper methods initializeAvailableModels() { this.availableModels = [ { id: 'gpt-4', name: 'GPT-4', provider: 'openai', tier: 'premium', costTier: 'high', capabilities: ['text_generation', 'code_generation', 'analysis', 'reasoning'], maxTokens: 8192, baseScore: 0.9, description: 'Most capable model for complex tasks' }, { id: 'gpt-4-turbo', name: 'GPT-4 Turbo', provider: 'openai', tier: 'premium', costTier: 'medium', capabilities: ['text_generation', 'code_generation', 'analysis', 'reasoning', 'vision'], maxTokens: 128000, baseScore: 0.85, description: 'Fast and efficient GPT-4 variant' }, { id: 'gpt-3.5-turbo', name: 'GPT-3.5 Turbo', provider: 'openai', tier: 'standard', costTier: 'low', capabilities: ['text_generation', 'basic_analysis', 'conversation'], maxTokens: 4096, baseScore: 0.7, description: 'Balanced performance and cost' }, { id: 'claude-3-opus', name: 'Claude 3 Opus', provider: 'anthropic', tier: 'premium', costTier: 'high', capabilities: ['text_generation', 'analysis', 'reasoning', 'safety'], maxTokens: 200000, baseScore: 0.88, description: 'Excellent for complex analysis and safety' }, { id: 'claude-3-sonnet', name: 'Claude 3 Sonnet', provider: 'anthropic', tier: 'standard', costTier: 'medium', capabilities: ['text_generation', 'analysis', 'reasoning'], maxTokens: 200000, baseScore: 0.75, description: 'Balanced Claude model for most tasks' } ]; } isModelAvailable(modelId) { return this.availableModels.some(model => model.id === modelId); } async handleModelSwitched(event) { // Handle model switch events for analytics and optimization this.context.logger.debug('Model switch event received', event.data); } generateRecommendationReasoning(model, context, score) { const reasons = []; if (model.capabilities.includes(context.taskType)) { reasons.push(`Optimized for ${context.taskType}`); } if (context.complexityLevel === 'high' && model.tier === 'premium') { reasons.push('Premium model suitable for complex tasks'); } if (context.costPreference === 'low' && model.costTier === 'low') { reasons.push('Cost-effective option'); } const performance = this.modelPerformance.get(model.id); if (performance?.successRate > 0.9) { reasons.push('High success rate in previous tasks'); } return reasons.join('; '); } estimateModelPerformance(model, context) { const historical = this.modelPerformance.get(model.id); return { responseTime: historical?.averageResponseTime || this.getBaselineResponseTime(model), successRate: historical?.successRate || 0.85, cost: historical?.averageCost || this.getBaselineCost(model), quality: this.estimateQuality(model, context) }; } getBaselineResponseTime(model) { const baselines = { 'gpt-4': 8000, 'gpt-4-turbo': 4000, 'gpt-3.5-turbo': 2000, 'claude-3-opus': 6000, 'claude-3-sonnet': 3000 }; return baselines[model.id] || 5000; } getBaselineCost(model) { const baselines = { 'gpt-4': 0.06, 'gpt-4-turbo': 0.03, 'gpt-3.5-turbo': 0.002, 'claude-3-opus': 0.075, 'claude-3-sonnet': 0.015 }; return baselines[model.id] || 0.01; } estimateQuality(model, context) { let quality = model.baseScore || 0.7; if (model.capabilities.includes(context.taskType)) { quality += 0.1; } if (context.complexityLevel === 'high' && model.tier === 'premium') { quality += 0.05; } return Math.min(1.0, quality); } } /** * Training Manager - Handles automation pattern training and learning */ class TrainingManager { constructor(context) { this.context = context; this.isStarted = false; this.trainingMode = false; this.activeSessions = new Map(); this.learnedPatterns = new Map(); this.trainingHistory = []; this.confidence = 0.8; } async start() { if (this.isStarted) return; this.context.logger.info('Starting Training Manager'); // Load existing patterns const patterns = await this.context.storageService.get('learnedPatterns'); if (patterns) { this.learnedPatterns = new Map(patterns); } // Load training history const history = await this.context.storageService.get('trainingHistory'); if (history) { this.trainingHistory = history; } // Set up event listeners this.context.eventBus.on(ChatGPTPluginEvents.TRAINING_MODE_ENABLED, (event) => { this.handleTrainingModeEnabled(event); }); this.context.eventBus.on(ChatGPTPluginEvents.TRAINING_PATTERN_LEARNED, (event) => { this.handlePatternLearned(event); }); this.isStarted = true; this.context.logger.info('Training Manager started successfully'); } async stop() { if (!this.isStarted) return; // Save current state await this.context.storageService.set('learnedPatterns', Array.from(this.learnedPatterns.entries())); await this.context.storageService.set('trainingHistory', this.trainingHistory); // End all active sessions for (const session of this.activeSessions.values()) { await this.endTrainingSession(session.id, 'manager_stopped'); } this.isStarted = false; this.context.logger.info('Training Manager stopped'); } async destroy() { await this.stop(); this.activeSessions.clear(); this.learnedPatterns.clear(); this.trainingHistory = []; this.context.logger.info('Training Manager destroyed'); } async configure(settings) { if (settings.enableTrainingMode !== undefined) { this.trainingMode = settings.enableTrainingMode; } if (settings.tr