Spaces:
Running
Running
import { Component, OnInit } from '@angular/core'; | |
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; | |
import { MatSnackBar } from '@angular/material/snack-bar'; | |
import { ApiService } from '../services/api.service'; | |
import { finalize } from 'rxjs/operators'; | |
interface ProviderConfig { | |
type: string; | |
name: string; | |
display_name: string; | |
requires_endpoint: boolean; | |
requires_api_key: boolean; | |
requires_repo_info: boolean; | |
description?: string; | |
} | |
interface ProviderSettings { | |
name: string; | |
api_key?: string; | |
endpoint?: string; | |
settings: any; | |
} | |
({ | |
selector: 'app-environment', | |
templateUrl: './environment.component.html', | |
styleUrls: ['./environment.component.scss'] | |
}) | |
export class EnvironmentComponent implements OnInit { | |
environmentForm!: FormGroup; | |
loading = false; | |
saving = false; | |
showInternalPrompt = false; | |
showParameterCollection = false; | |
// Provider lists | |
allProviders: ProviderConfig[] = []; | |
llmProviders: ProviderConfig[] = []; | |
ttsProviders: ProviderConfig[] = []; | |
sttProviders: ProviderConfig[] = []; | |
// Current provider configs | |
currentLLMProvider?: ProviderConfig; | |
currentTTSProvider?: ProviderConfig; | |
currentSTTProvider?: ProviderConfig; | |
constructor( | |
private fb: FormBuilder, | |
private apiService: ApiService, | |
private snackBar: MatSnackBar | |
) {} | |
ngOnInit(): void { | |
this.initializeForm(); | |
this.loadEnvironment(); | |
} | |
initializeForm(): void { | |
this.environmentForm = this.fb.group({ | |
// LLM Provider | |
llm_provider_name: ['', Validators.required], | |
llm_provider_api_key: [''], | |
llm_provider_endpoint: [''], | |
internal_prompt: [''], | |
// Parameter Collection Config | |
max_params_per_question: [2, [Validators.min(1), Validators.max(5)]], | |
retry_unanswered: [true], | |
collection_prompt: [''], | |
// TTS Provider | |
tts_provider_name: ['no_tts'], | |
tts_provider_api_key: [''], | |
tts_provider_endpoint: [''], | |
tts_use_ssml: [false], | |
// STT Provider | |
stt_provider_name: ['no_stt'], | |
stt_provider_api_key: [''], | |
stt_provider_endpoint: [''], | |
stt_speech_timeout_ms: [2000], | |
stt_noise_reduction_level: [2], | |
stt_vad_sensitivity: [0.5], | |
stt_language: ['tr-TR'], | |
stt_model: ['latest_long'], | |
stt_use_enhanced: [true], | |
stt_enable_punctuation: [true], | |
stt_interim_results: [true] | |
}); | |
// Subscribe to provider changes | |
this.environmentForm.get('llm_provider_name')?.valueChanges.subscribe(name => { | |
this.onLLMProviderChange(name); | |
}); | |
this.environmentForm.get('tts_provider_name')?.valueChanges.subscribe(name => { | |
this.onTTSProviderChange(name); | |
}); | |
this.environmentForm.get('stt_provider_name')?.valueChanges.subscribe(name => { | |
this.onSTTProviderChange(name); | |
}); | |
} | |
loadEnvironment(): void { | |
this.loading = true; | |
this.apiService.getEnvironment() | |
.pipe(finalize(() => this.loading = false)) | |
.subscribe({ | |
next: (data) => { | |
// Store providers | |
this.allProviders = data.providers || []; | |
this.llmProviders = this.allProviders.filter(p => p.type === 'llm'); | |
this.ttsProviders = [{ | |
type: 'tts', | |
name: 'no_tts', | |
display_name: 'No TTS', | |
requires_endpoint: false, | |
requires_api_key: false, | |
requires_repo_info: false | |
}, ...this.allProviders.filter(p => p.type === 'tts')]; | |
this.sttProviders = [{ | |
type: 'stt', | |
name: 'no_stt', | |
display_name: 'No STT', | |
requires_endpoint: false, | |
requires_api_key: false, | |
requires_repo_info: false | |
}, ...this.allProviders.filter(p => p.type === 'stt')]; | |
// Set form values | |
this.environmentForm.patchValue({ | |
// LLM Provider | |
llm_provider_name: data.llm_provider?.name || '', | |
llm_provider_api_key: data.llm_provider?.api_key || '', | |
llm_provider_endpoint: data.llm_provider?.endpoint || '', | |
internal_prompt: data.llm_provider?.settings?.internal_prompt || '', | |
// Parameter Collection | |
max_params_per_question: data.llm_provider?.settings?.parameter_collection_config?.max_params_per_question || 2, | |
retry_unanswered: data.llm_provider?.settings?.parameter_collection_config?.retry_unanswered ?? true, | |
collection_prompt: data.llm_provider?.settings?.parameter_collection_config?.collection_prompt || '', | |
// TTS Provider | |
tts_provider_name: data.tts_provider?.name || 'no_tts', | |
tts_provider_api_key: data.tts_provider?.api_key || '', | |
tts_provider_endpoint: data.tts_provider?.endpoint || '', | |
tts_use_ssml: data.tts_provider?.settings?.use_ssml || false, | |
// STT Provider | |
stt_provider_name: data.stt_provider?.name || 'no_stt', | |
stt_provider_api_key: data.stt_provider?.api_key || '', | |
stt_provider_endpoint: data.stt_provider?.endpoint || '', | |
stt_speech_timeout_ms: data.stt_provider?.settings?.speech_timeout_ms || 2000, | |
stt_noise_reduction_level: data.stt_provider?.settings?.noise_reduction_level || 2, | |
stt_vad_sensitivity: data.stt_provider?.settings?.vad_sensitivity || 0.5, | |
stt_language: data.stt_provider?.settings?.language || 'tr-TR', | |
stt_model: data.stt_provider?.settings?.model || 'latest_long', | |
stt_use_enhanced: data.stt_provider?.settings?.use_enhanced ?? true, | |
stt_enable_punctuation: data.stt_provider?.settings?.enable_punctuation ?? true, | |
stt_interim_results: data.stt_provider?.settings?.interim_results ?? true | |
}); | |
// Trigger provider change handlers | |
this.onLLMProviderChange(data.llm_provider?.name || ''); | |
this.onTTSProviderChange(data.tts_provider?.name || 'no_tts'); | |
this.onSTTProviderChange(data.stt_provider?.name || 'no_stt'); | |
}, | |
error: (error) => { | |
this.snackBar.open('Failed to load environment configuration', 'Close', { | |
duration: 3000, | |
panelClass: ['error-snackbar'] | |
}); | |
} | |
}); | |
} | |
onLLMProviderChange(name: string): void { | |
this.currentLLMProvider = this.llmProviders.find(p => p.name === name); | |
if (this.currentLLMProvider) { | |
// Update validators | |
const apiKeyControl = this.environmentForm.get('llm_provider_api_key'); | |
const endpointControl = this.environmentForm.get('llm_provider_endpoint'); | |
if (this.currentLLMProvider.requires_api_key) { | |
apiKeyControl?.setValidators([Validators.required]); | |
} else { | |
apiKeyControl?.clearValidators(); | |
} | |
if (this.currentLLMProvider.requires_endpoint) { | |
endpointControl?.setValidators([Validators.required, Validators.pattern('https?://.+')]); | |
} else { | |
endpointControl?.clearValidators(); | |
} | |
apiKeyControl?.updateValueAndValidity(); | |
endpointControl?.updateValueAndValidity(); | |
} | |
} | |
onTTSProviderChange(name: string): void { | |
this.currentTTSProvider = this.ttsProviders.find(p => p.name === name); | |
if (this.currentTTSProvider) { | |
const apiKeyControl = this.environmentForm.get('tts_provider_api_key'); | |
const endpointControl = this.environmentForm.get('tts_provider_endpoint'); | |
if (this.currentTTSProvider.requires_api_key && name !== 'no_tts') { | |
apiKeyControl?.setValidators([Validators.required]); | |
} else { | |
apiKeyControl?.clearValidators(); | |
} | |
if (this.currentTTSProvider.requires_endpoint && name !== 'no_tts') { | |
endpointControl?.setValidators([Validators.required, Validators.pattern('https?://.+')]); | |
} else { | |
endpointControl?.clearValidators(); | |
} | |
apiKeyControl?.updateValueAndValidity(); | |
endpointControl?.updateValueAndValidity(); | |
} | |
} | |
onSTTProviderChange(name: string): void { | |
this.currentSTTProvider = this.sttProviders.find(p => p.name === name); | |
if (this.currentSTTProvider) { | |
const apiKeyControl = this.environmentForm.get('stt_provider_api_key'); | |
const endpointControl = this.environmentForm.get('stt_provider_endpoint'); | |
if (this.currentSTTProvider.requires_api_key && name !== 'no_stt') { | |
apiKeyControl?.setValidators([Validators.required]); | |
} else { | |
apiKeyControl?.clearValidators(); | |
} | |
if (this.currentSTTProvider.requires_endpoint && name !== 'no_stt') { | |
endpointControl?.setValidators([Validators.required, Validators.pattern('https?://.+')]); | |
} else { | |
endpointControl?.clearValidators(); | |
} | |
apiKeyControl?.updateValueAndValidity(); | |
endpointControl?.updateValueAndValidity(); | |
} | |
} | |
save(): void { | |
if (this.environmentForm.invalid) { | |
Object.keys(this.environmentForm.controls).forEach(key => { | |
const control = this.environmentForm.get(key); | |
if (control && control.invalid) { | |
control.markAsTouched(); | |
} | |
}); | |
return; | |
} | |
this.saving = true; | |
const formValue = this.environmentForm.value; | |
// Build environment update payload | |
const payload = { | |
llm_provider: { | |
name: formValue.llm_provider_name, | |
api_key: formValue.llm_provider_api_key || null, | |
endpoint: formValue.llm_provider_endpoint || null, | |
settings: { | |
internal_prompt: formValue.internal_prompt || null, | |
parameter_collection_config: { | |
max_params_per_question: formValue.max_params_per_question, | |
retry_unanswered: formValue.retry_unanswered, | |
collection_prompt: formValue.collection_prompt || null | |
} | |
} | |
}, | |
tts_provider: { | |
name: formValue.tts_provider_name, | |
api_key: formValue.tts_provider_api_key || null, | |
endpoint: formValue.tts_provider_endpoint || null, | |
settings: { | |
use_ssml: formValue.tts_use_ssml | |
} | |
}, | |
stt_provider: { | |
name: formValue.stt_provider_name, | |
api_key: formValue.stt_provider_api_key || null, | |
endpoint: formValue.stt_provider_endpoint || null, | |
settings: { | |
speech_timeout_ms: formValue.stt_speech_timeout_ms, | |
noise_reduction_level: formValue.stt_noise_reduction_level, | |
vad_sensitivity: formValue.stt_vad_sensitivity, | |
language: formValue.stt_language, | |
model: formValue.stt_model, | |
use_enhanced: formValue.stt_use_enhanced, | |
enable_punctuation: formValue.stt_enable_punctuation, | |
interim_results: formValue.stt_interim_results | |
} | |
} | |
}; | |
this.apiService.updateEnvironment(payload) | |
.pipe(finalize(() => this.saving = false)) | |
.subscribe({ | |
next: () => { | |
this.snackBar.open('Environment configuration saved successfully', 'Close', { | |
duration: 3000, | |
panelClass: ['success-snackbar'] | |
}); | |
}, | |
error: (error) => { | |
this.snackBar.open( | |
error.error?.detail || 'Failed to save environment configuration', | |
'Close', | |
{ | |
duration: 5000, | |
panelClass: ['error-snackbar'] | |
} | |
); | |
} | |
}); | |
} | |
testConnection(): void { | |
const endpoint = this.environmentForm.get('llm_provider_endpoint')?.value; | |
const apiKey = this.environmentForm.get('llm_provider_api_key')?.value; | |
const provider = this.environmentForm.get('llm_provider_name')?.value; | |
if (!endpoint) { | |
this.snackBar.open('Please enter an endpoint URL', 'Close', { | |
duration: 3000, | |
panelClass: ['error-snackbar'] | |
}); | |
return; | |
} | |
this.loading = true; | |
this.apiService.testConnection({ endpoint, api_key: apiKey, provider }) | |
.pipe(finalize(() => this.loading = false)) | |
.subscribe({ | |
next: (result) => { | |
if (result.success) { | |
this.snackBar.open('Connection successful!', 'Close', { | |
duration: 3000, | |
panelClass: ['success-snackbar'] | |
}); | |
} else { | |
this.snackBar.open(result.message || 'Connection failed', 'Close', { | |
duration: 5000, | |
panelClass: ['error-snackbar'] | |
}); | |
} | |
}, | |
error: (error) => { | |
this.snackBar.open('Connection test failed', 'Close', { | |
duration: 3000, | |
panelClass: ['error-snackbar'] | |
}); | |
} | |
}); | |
} | |
toggleInternalPrompt(): void { | |
this.showInternalPrompt = !this.showInternalPrompt; | |
} | |
toggleParameterCollection(): void { | |
this.showParameterCollection = !this.showParameterCollection; | |
} | |
isLLMEndpointRequired(): boolean { | |
return this.currentLLMProvider?.requires_endpoint || false; | |
} | |
isLLMApiKeyRequired(): boolean { | |
return this.currentLLMProvider?.requires_api_key || false; | |
} | |
isTTSEnabled(): boolean { | |
return this.environmentForm.get('tts_provider_name')?.value !== 'no_tts'; | |
} | |
isSTTEnabled(): boolean { | |
return this.environmentForm.get('stt_provider_name')?.value !== 'no_stt'; | |
} | |
getLLMProviderDescription(): string { | |
return this.currentLLMProvider?.description || ''; | |
} | |
getTTSProviderDescription(): string { | |
return this.currentTTSProvider?.description || ''; | |
} | |
getSTTProviderDescription(): string { | |
return this.currentSTTProvider?.description || ''; | |
} | |
} |