flare / flare-ui /src /app /services /environment.service.ts
ciyidogan's picture
Upload 118 files
9f79da5 verified
// environment.service.ts
// Path: /flare-ui/src/app/services/environment.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { Environment, ProviderSettings } from './api.service';
export interface EnvironmentError {
type: 'validation' | 'update' | 'unknown';
message: string;
details?: any;
}
@Injectable({
providedIn: 'root'
})
export class EnvironmentService {
private environmentSubject = new BehaviorSubject<Environment | null>(null);
public environment$ = this.environmentSubject.asObservable();
private ttsEnabledSource = new BehaviorSubject<boolean>(false);
private sttEnabledSource = new BehaviorSubject<boolean>(false);
private errorSubject = new BehaviorSubject<EnvironmentError | null>(null);
public error$ = this.errorSubject.asObservable();
// Local storage keys
private readonly TTS_KEY = 'flare_tts_enabled';
private readonly STT_KEY = 'flare_stt_enabled';
ttsEnabled$ = this.ttsEnabledSource.asObservable();
sttEnabled$ = this.sttEnabledSource.asObservable();
constructor() {
this.loadPreferences();
}
private loadPreferences(): void {
try {
const savedTTS = localStorage.getItem(this.TTS_KEY);
if (savedTTS !== null) {
this.ttsEnabledSource.next(savedTTS === 'true');
}
const savedSTT = localStorage.getItem(this.STT_KEY);
if (savedSTT !== null) {
this.sttEnabledSource.next(savedSTT === 'true');
}
} catch (error) {
console.error('Error loading preferences:', error);
this.ttsEnabledSource.next(false);
this.sttEnabledSource.next(false);
}
}
setTTSEnabled(enabled: boolean): void {
try {
if (typeof enabled !== 'boolean') {
throw new Error('TTS enabled must be a boolean value');
}
this.ttsEnabledSource.next(enabled);
try {
localStorage.setItem(this.TTS_KEY, enabled.toString());
} catch (error) {
console.warn('Failed to save TTS preference:', error);
}
console.log(`TTS ${enabled ? 'enabled' : 'disabled'}`);
} catch (error) {
this.handleError('validation', 'Invalid TTS setting', error);
}
}
setSTTEnabled(enabled: boolean): void {
try {
if (typeof enabled !== 'boolean') {
throw new Error('STT enabled must be a boolean value');
}
this.sttEnabledSource.next(enabled);
try {
localStorage.setItem(this.STT_KEY, enabled.toString());
} catch (error) {
console.warn('Failed to save STT preference:', error);
}
console.log(`STT ${enabled ? 'enabled' : 'disabled'}`);
} catch (error) {
this.handleError('validation', 'Invalid STT setting', error);
}
}
isTTSEnabled(): boolean {
return this.ttsEnabledSource.value;
}
isSTTEnabled(): boolean {
return this.sttEnabledSource.value;
}
updateEnvironment(env: Environment | null): void {
try {
this.environmentSubject.next(env);
this.errorSubject.next(null);
if (env) {
console.log('Environment updated:', {
llm_provider: env.llm_provider.name,
tts_provider: env.tts_provider.name,
stt_provider: env.stt_provider.name
});
// Update TTS/STT enabled states based on provider
if (env.tts_provider.name !== 'no_tts') {
this.setTTSEnabled(true);
}
if (env.stt_provider.name !== 'no_stt') {
this.setSTTEnabled(true);
}
}
} catch (error: any) {
this.handleError('update', error.message || 'Failed to update environment', error);
}
}
getEnvironment(): Environment | null {
return this.environmentSubject.value;
}
getCurrentLLMProvider(): ProviderSettings | null {
const env = this.environmentSubject.value;
return env?.llm_provider || null;
}
getCurrentTTSProvider(): ProviderSettings | null {
const env = this.environmentSubject.value;
return env?.tts_provider || null;
}
getCurrentSTTProvider(): ProviderSettings | null {
const env = this.environmentSubject.value;
return env?.stt_provider || null;
}
isGPTMode(): boolean {
try {
const env = this.environmentSubject.value;
const llmName = env?.llm_provider?.name?.toLowerCase();
return llmName?.startsWith('gpt4o') || false;
} catch (error) {
console.error('Error checking GPT mode:', error);
return false;
}
}
getWorkMode(): string | null {
const env = this.environmentSubject.value;
return env?.llm_provider?.name || null;
}
isTTSAvailable(): boolean {
const env = this.environmentSubject.value;
return env?.tts_provider?.name !== 'no_tts' && env?.tts_provider?.name !== undefined;
}
isSTTAvailable(): boolean {
const env = this.environmentSubject.value;
return env?.stt_provider?.name !== 'no_stt' && env?.stt_provider?.name !== undefined;
}
// Check if environment supports a specific feature
supportsFeature(feature: 'tts' | 'stt' | 'realtime' | 'streaming'): boolean {
const env = this.environmentSubject.value;
if (!env) return false;
switch (feature) {
case 'tts':
return this.isTTSAvailable() && this.isTTSEnabled();
case 'stt':
return this.isSTTAvailable() && this.isSTTEnabled();
case 'realtime':
return this.isGPTMode();
case 'streaming':
return true;
default:
return false;
}
}
// Get available providers
getAvailableProviders(type: 'llm' | 'tts' | 'stt'): any[] {
const env = this.environmentSubject.value;
if (!env?.providers) return [];
return env.providers.filter(p => p.type === type);
}
// Reset all settings
reset(): void {
try {
this.environmentSubject.next(null);
this.setTTSEnabled(false);
this.setSTTEnabled(false);
this.errorSubject.next(null);
try {
localStorage.removeItem(this.TTS_KEY);
localStorage.removeItem(this.STT_KEY);
} catch (error) {
console.warn('Failed to clear preferences:', error);
}
console.log('Environment service reset');
} catch (error) {
this.handleError('unknown', 'Failed to reset environment', error);
}
}
// Get configuration summary
getConfigSummary(): {
llmProvider: string | null;
ttsProvider: string | null;
sttProvider: string | null;
ttsEnabled: boolean;
sttEnabled: boolean;
features: string[];
} {
const env = this.environmentSubject.value;
const features: string[] = [];
if (this.supportsFeature('tts')) features.push('TTS');
if (this.supportsFeature('stt')) features.push('STT');
if (this.supportsFeature('realtime')) features.push('Realtime');
if (this.supportsFeature('streaming')) features.push('Streaming');
return {
llmProvider: env?.llm_provider?.name || null,
ttsProvider: env?.tts_provider?.name || null,
sttProvider: env?.stt_provider?.name || null,
ttsEnabled: this.isTTSEnabled(),
sttEnabled: this.isSTTEnabled(),
features
};
}
private handleError(type: EnvironmentError['type'], message: string, details?: any): void {
const error: EnvironmentError = {
type,
message,
details
};
console.error(`Environment error [${type}]:`, message, details);
this.errorSubject.next(error);
}
// Observable to check if environment is ready
isReady(): Observable<boolean> {
return new Observable(subscriber => {
const sub = this.environment$.subscribe(env => {
// Environment is ready if we have all providers configured
const isReady = !!(
env &&
env.llm_provider &&
env.tts_provider &&
env.stt_provider
);
subscriber.next(isReady);
});
return () => sub.unsubscribe();
});
}
// Get error state
hasError(): boolean {
return this.errorSubject.value !== null;
}
clearError(): void {
this.errorSubject.next(null);
}
}