@wernerthiago/teo
Version:
Test Execution Optimizer
268 lines (230 loc) • 7.07 kB
JavaScript
/**
* AI Provider Factory
* Creates and manages AI provider instances with fallback support
*/
import OpenAIProvider from './openai-provider.js'
import AzureOpenAIProvider from './azure-openai-provider.js'
import AnthropicProvider from './anthropic-provider.js'
import GoogleGeminiProvider from './google-gemini-provider.js'
import OllamaProvider from './ollama-provider.js'
import logger from '../core/logger.js'
// Provider type constants
export const ProviderType = {
OPENAI: 'openai',
AZURE_OPENAI: 'azure-openai',
ANTHROPIC: 'anthropic',
GOOGLE_GEMINI: 'google-gemini',
OLLAMA: 'ollama'
}
/**
* AI Provider Manager with fallback support
*/
export class AIProviderManager {
constructor(config) {
this.config = config
this.providers = new Map()
this.primaryProvider = null
this.fallbackProviders = []
this.initializeProviders()
}
/**
* Initialize all configured providers
*/
initializeProviders() {
const aiConfig = this.config || {}
// Initialize primary provider
if (aiConfig.primary) {
try {
this.primaryProvider = this.createProvider(aiConfig.primary)
this.providers.set('primary', this.primaryProvider)
logger.info('Primary AI provider initialized', {
type: aiConfig.primary.type
})
} catch (error) {
logger.error('Failed to initialize primary AI provider', {
error: error.message
})
}
}
// Initialize fallback providers
if (aiConfig.fallback) {
try {
const fallbackProvider = this.createProvider(aiConfig.fallback)
this.fallbackProviders.push(fallbackProvider)
this.providers.set('fallback', fallbackProvider)
logger.info('Fallback AI provider initialized', {
type: aiConfig.fallback.type
})
} catch (error) {
logger.error('Failed to initialize fallback AI provider', {
error: error.message
})
}
}
// Initialize local provider
if (aiConfig.local) {
try {
const localProvider = this.createProvider(aiConfig.local)
this.fallbackProviders.push(localProvider)
this.providers.set('local', localProvider)
logger.info('Local AI provider initialized', {
type: aiConfig.local.type
})
} catch (error) {
logger.error('Failed to initialize local AI provider', {
error: error.message
})
}
}
if (this.providers.size === 0) {
logger.warn('No AI providers initialized - AI analysis will be disabled')
}
}
/**
* Create provider instance based on configuration
*/
createProvider(config) {
switch (config.type) {
case ProviderType.OPENAI:
return new OpenAIProvider(config)
case ProviderType.AZURE_OPENAI:
return new AzureOpenAIProvider(config)
case ProviderType.ANTHROPIC:
return new AnthropicProvider(config)
case ProviderType.GOOGLE_GEMINI:
return new GoogleGeminiProvider(config)
case ProviderType.OLLAMA:
return new OllamaProvider(config)
default:
throw new Error(`Unknown AI provider type: ${config.type}`)
}
}
/**
* Analyze impact with automatic fallback
*/
async analyzeImpact(diffResult, featureMapping, options = {}) {
const timer = logger.time('AI impact analysis')
try {
// Try primary provider first
if (this.primaryProvider) {
try {
const prompt = this.primaryProvider.createAnalysisPrompt(
diffResult,
featureMapping,
options
)
const response = await this.primaryProvider.analyzeImpact(prompt, options)
const analysis = this.primaryProvider.parseAnalysisResponse(
response,
featureMapping?.featureName || 'unknown'
)
timer.end({ provider: 'primary', success: true })
return analysis
} catch (error) {
logger.warn('Primary AI provider failed', {
provider: this.primaryProvider.type,
error: error.message
})
}
}
// Try fallback providers
for (const provider of this.fallbackProviders) {
try {
logger.info('Trying fallback AI provider', { type: provider.type })
const prompt = provider.createAnalysisPrompt(
diffResult,
featureMapping,
options
)
const response = await provider.analyzeImpact(prompt, options)
const analysis = provider.parseAnalysisResponse(
response,
featureMapping?.featureName || 'unknown'
)
timer.end({ provider: provider.type, success: true })
return analysis
} catch (error) {
logger.warn('Fallback AI provider failed', {
provider: provider.type,
error: error.message
})
}
}
// All providers failed
throw new Error('All AI providers failed')
} catch (error) {
timer.end({ success: false, error: error.message })
logger.error('AI impact analysis failed', { error: error.message })
// Return fallback analysis
return this.createFallbackAnalysis(featureMapping?.featureName || 'unknown')
}
}
/**
* Create fallback analysis when AI fails
*/
createFallbackAnalysis(featureName) {
return {
featureName,
impactLevel: 'medium',
confidence: 0.3,
reasoning: 'AI analysis unavailable - using fallback heuristics',
affectedComponents: [],
riskFactors: ['AI analysis failed'],
recommendedTests: ['regression tests'],
metadata: { fallback: true }
}
}
/**
* Validate all provider connections
*/
async validateConnections() {
const results = {}
for (const [name, provider] of this.providers) {
try {
const isValid = await provider.validateConnection()
results[name] = {
type: provider.type,
model: provider.model,
valid: isValid
}
} catch (error) {
results[name] = {
type: provider.type,
model: provider.model,
valid: false,
error: error.message
}
}
}
return results
}
/**
* Get usage statistics for all providers
*/
getUsageStats() {
const stats = {}
for (const [name, provider] of this.providers) {
stats[name] = provider.getUsageStats()
}
return stats
}
/**
* Get available providers
*/
getAvailableProviders() {
return Array.from(this.providers.keys())
}
/**
* Get specific provider
*/
getProvider(name) {
return this.providers.get(name)
}
/**
* Check if AI analysis is available
*/
isAvailable() {
return this.providers.size > 0
}
}
export default AIProviderManager