flare / flare-ui /src /app /components /environment /environment.component.ts
ciyidogan's picture
Update flare-ui/src/app/components/environment/environment.component.ts
0dd2a6a verified
raw
history blame
13.8 kB
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;
}
@Component({
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 || '';
}
}