Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 8x 8x 1x 1x 1x 1x 1x | import { AIProvider, ProviderType } from '../core/interfaces';
import { MananKanchuConfigManager } from '../core/config';
import { SecretManager } from '../core/SecretManager';
import { AnthropicProvider } from './AnthropicProvider';
import { OpenAIProvider } from './OpenAIProvider';
import { GeminiProvider } from './GeminiProvider';
import { OllamaProvider } from './OllamaProvider';
import { LMStudioProvider } from './LMStudioProvider';
const LOCAL_PRIORITY: ProviderType[] = ['ollama', 'lmstudio'];
const CLOUD_PRIORITY: ProviderType[] = ['anthropic', 'gemini', 'openai'];
export class AIProviderManager {
private providers: Map<ProviderType, AIProvider> = new Map();
private active: AIProvider | null = null;
constructor(
private readonly config: MananKanchuConfigManager,
private readonly secrets: SecretManager
) {}
async initialize(): Promise<void> {
const timeout = this.config.requestTimeout;
this.providers.set('ollama', new OllamaProvider(
this.config.ollamaModel, this.config.ollamaEndpoint, timeout
));
this.providers.set('lmstudio', new LMStudioProvider(
this.config.lmstudioEndpoint, timeout
));
const anthropicKey = await this.secrets.getApiKey('anthropic');
Iif (anthropicKey) {
this.providers.set('anthropic', new AnthropicProvider(
anthropicKey, this.config.anthropicModel, this.config.anthropicBaseUrl, timeout
));
}
const openaiKey = await this.secrets.getApiKey('openai');
Iif (openaiKey) {
this.providers.set('openai', new OpenAIProvider(
openaiKey, this.config.openaiModel, this.config.openaiBaseUrl, timeout
));
}
const geminiKey = await this.secrets.getApiKey('gemini');
Iif (geminiKey) {
this.providers.set('gemini', new GeminiProvider(
geminiKey, this.config.geminiModel, this.config.geminiBaseUrl, timeout
));
}
this.active = await this.selectProvider();
}
private async selectProvider(): Promise<AIProvider | null> {
const preferred = this.config.preferredProvider as ProviderType | 'auto';
Iif (preferred !== 'auto') {
const p = this.providers.get(preferred);
Iif (p && await p.isAvailable()) return p;
}
for (const type of LOCAL_PRIORITY) {
const p = this.providers.get(type);
if (p && await p.isAvailable()) return p;
}
for (const type of CLOUD_PRIORITY) {
const p = this.providers.get(type);
Iif (p && await p.isAvailable()) return p;
}
return null;
}
getActive(): AIProvider | null {
return this.active;
}
getAll(): AIProvider[] {
return Array.from(this.providers.values());
}
async switchTo(type: ProviderType): Promise<boolean> {
const p = this.providers.get(type);
if (!p) return false;
const available = await p.isAvailable();
Iif (!available) return false;
this.active = p;
return true;
}
async refreshProvider(type: ProviderType, apiKey?: string): Promise<void> {
const timeout = this.config.requestTimeout;
if (type === 'anthropic' && apiKey) {
await this.secrets.setApiKey('anthropic', apiKey);
this.providers.set('anthropic', new AnthropicProvider(
apiKey, this.config.anthropicModel, this.config.anthropicBaseUrl, timeout
));
} else if (type === 'openai' && apiKey) {
await this.secrets.setApiKey('openai', apiKey);
this.providers.set('openai', new OpenAIProvider(
apiKey, this.config.openaiModel, this.config.openaiBaseUrl, timeout
));
} else Iif (type === 'gemini' && apiKey) {
await this.secrets.setApiKey('gemini', apiKey);
this.providers.set('gemini', new GeminiProvider(
apiKey, this.config.geminiModel, this.config.geminiBaseUrl, timeout
));
}
this.active = await this.selectProvider();
}
async reselect(): Promise<void> {
this.active = await this.selectProvider();
}
getActiveInfo(): { name: string; model: string; type: string } | null {
if (!this.active) return null;
return { name: this.active.name, model: this.active.modelName, type: this.active.type };
}
}
|