@semantest/chrome-extension
Version:
Browser extension for ChatGPT-buddy - AI automation extension built on Web-Buddy framework
1,317 lines • 104 kB
JavaScript
/**
* @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