Spaces:
Running
Running
import { Component, inject, OnInit } from '@angular/core'; | |
import { CommonModule } from '@angular/common'; | |
import { FormsModule } from '@angular/forms'; | |
import { MatCardModule } from '@angular/material/card'; | |
import { MatFormFieldModule } from '@angular/material/form-field'; | |
import { MatInputModule } from '@angular/material/input'; | |
import { MatSelectModule } from '@angular/material/select'; | |
import { MatButtonModule } from '@angular/material/button'; | |
import { MatIconModule } from '@angular/material/icon'; | |
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; | |
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar'; | |
import { MatExpansionModule } from '@angular/material/expansion'; | |
import { MatSliderModule } from '@angular/material/slider'; | |
import { MatTooltipModule } from '@angular/material/tooltip'; | |
import { MatCheckboxModule } from '@angular/material/checkbox'; | |
import { ApiService, Environment, STTSettings } from '../../services/api.service'; | |
import { EnvironmentService } from '../../services/environment.service'; | |
({ | |
selector: 'app-environment', | |
standalone: true, | |
imports: [ | |
CommonModule, | |
FormsModule, | |
MatCardModule, | |
MatFormFieldModule, | |
MatInputModule, | |
MatSelectModule, | |
MatButtonModule, | |
MatIconModule, | |
MatProgressSpinnerModule, | |
MatSnackBarModule, | |
MatExpansionModule, | |
MatSliderModule, | |
MatTooltipModule, | |
MatCheckboxModule | |
], | |
template: ` | |
<div class="environment-container"> | |
<mat-card> | |
<mat-card-header> | |
<mat-card-title> | |
<mat-icon>settings</mat-icon> | |
Environment Configuration | |
</mat-card-title> | |
</mat-card-header> | |
<mat-card-content> | |
@if (isGPTMode()) { | |
<mat-card class="info-card"> | |
<mat-card-content> | |
<mat-icon>info</mat-icon> | |
<div> | |
<strong>{{ environment.work_mode === 'gpt4o' ? 'GPT-4o' : 'GPT-4o Mini' }} Mode</strong> | |
<p>This mode uses OpenAI's API which has usage-based pricing.</p> | |
<p>Approximate cost: {{ environment.work_mode === 'gpt4o' ? '$0.01-0.03' : '$0.001-0.003' }} per conversation turn.</p> | |
</div> | |
</mat-card-content> | |
</mat-card> | |
} | |
<form (ngSubmit)="save()" #envForm="ngForm"> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Work Mode</mat-label> | |
<mat-select | |
name="workMode" | |
[(ngModel)]="environment.work_mode" | |
(selectionChange)="onWorkModeChange()" | |
required | |
[disabled]="loading" | |
> | |
<mat-option value="hfcloud">HF Cloud</mat-option> | |
<mat-option value="cloud">Cloud</mat-option> | |
<mat-option value="on-premise">On-Premise</mat-option> | |
<mat-option value="gpt4o">GPT-4o</mat-option> | |
<mat-option value="gpt4o-mini">GPT-4o Mini</mat-option> | |
</mat-select> | |
<mat-icon matPrefix>cloud</mat-icon> | |
</mat-form-field> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>{{ getTokenLabel() }}</mat-label> | |
<input | |
matInput | |
type="password" | |
name="cloudToken" | |
[(ngModel)]="environment.cloud_token" | |
[disabled]="loading || environment.work_mode === 'on-premise'" | |
[placeholder]="getTokenPlaceholder()" | |
> | |
<mat-icon matPrefix>vpn_key</mat-icon> | |
<mat-hint>{{ isGPTMode() ? 'Required for OpenAI API access' : 'Required for HF Cloud and Cloud modes' }}</mat-hint> | |
</mat-form-field> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Spark Endpoint</mat-label> | |
<input | |
matInput | |
type="url" | |
name="sparkEndpoint" | |
[(ngModel)]="environment.spark_endpoint" | |
[required]="!isGPTMode()" | |
[disabled]="loading || isGPTMode()" | |
placeholder="https://spark-service.example.com" | |
> | |
<mat-icon matPrefix>link</mat-icon> | |
<button | |
mat-icon-button | |
matSuffix | |
type="button" | |
(click)="testConnection()" | |
[disabled]="loading || !environment.spark_endpoint || isGPTMode()" | |
matTooltip="Test Connection" | |
> | |
<mat-icon>wifi_tethering</mat-icon> | |
</button> | |
@if (isGPTMode()) { | |
<mat-hint>Not required for GPT mode</mat-hint> | |
} | |
</mat-form-field> | |
<!-- TTS Configuration --> | |
<div class="engine-row"> | |
<mat-form-field appearance="outline" class="engine-field"> | |
<mat-label>TTS Engine</mat-label> | |
<mat-select | |
name="ttsEngine" | |
[(ngModel)]="environment.tts_engine" | |
(selectionChange)="onTTSEngineChange()" | |
[disabled]="loading" | |
> | |
<mat-option value="no_tts">No TTS</mat-option> | |
<mat-option value="elevenlabs">ElevenLabs</mat-option> | |
<mat-option value="blaze">Blaze (Coming Soon)</mat-option> | |
</mat-select> | |
<mat-icon matPrefix>record_voice_over</mat-icon> | |
</mat-form-field> | |
<mat-form-field appearance="outline" class="api-key-field"> | |
<mat-label>TTS API Key</mat-label> | |
<input | |
matInput | |
type="password" | |
name="ttsApiKey" | |
[(ngModel)]="environment.tts_engine_api_key" | |
[disabled]="loading || environment.tts_engine === 'no_tts'" | |
[required]="environment.tts_engine !== 'no_tts'" | |
placeholder="Enter TTS API key" | |
> | |
<mat-icon matPrefix>key</mat-icon> | |
</mat-form-field> | |
</div> | |
<!-- STT Configuration --> | |
<div class="engine-row"> | |
<mat-form-field appearance="outline" class="engine-field"> | |
<mat-label>STT Engine</mat-label> | |
<mat-select | |
name="sttEngine" | |
[(ngModel)]="environment.stt_engine" | |
(selectionChange)="onSTTEngineChange()" | |
[disabled]="loading" | |
> | |
<mat-option value="no_stt">No STT</mat-option> | |
<mat-option value="google">Google Cloud Speech-to-Text</mat-option> | |
<mat-option value="azure">Azure Speech Services (Coming Soon)</mat-option> | |
<mat-option value="amazon">Amazon Transcribe (Coming Soon)</mat-option> | |
<mat-option value="gpt4o_realtime">GPT-4o Realtime (Coming Soon)</mat-option> | |
<mat-option value="flicker">Flicker (Coming Soon)</mat-option> | |
</mat-select> | |
<mat-icon matPrefix>mic</mat-icon> | |
</mat-form-field> | |
<mat-form-field appearance="outline" class="api-key-field"> | |
<mat-label>STT API Key / Credentials</mat-label> | |
<input | |
matInput | |
type="password" | |
name="sttApiKey" | |
[(ngModel)]="environment.stt_engine_api_key" | |
[disabled]="loading || environment.stt_engine === 'no_stt'" | |
[required]="environment.stt_engine !== 'no_stt'" | |
[placeholder]="getSTTKeyPlaceholder()" | |
> | |
<mat-icon matPrefix>key</mat-icon> | |
<button mat-icon-button matSuffix | |
*ngIf="environment.stt_engine === 'google'" | |
(click)="fileInput.click()" | |
[disabled]="loading" | |
matTooltip="Upload Google credentials JSON"> | |
<mat-icon>upload_file</mat-icon> | |
</button> | |
<input #fileInput type="file" accept=".json" | |
style="display: none" | |
(change)="onSTTCredentialsFileSelected($event)"> | |
</mat-form-field> | |
</div> | |
<!-- STT Settings Panel --> | |
<mat-expansion-panel class="stt-settings-panel" | |
*ngIf="environment.stt_engine !== 'no_stt'" | |
[expanded]="sttSettingsExpanded"> | |
<mat-expansion-panel-header> | |
<mat-panel-title> | |
<mat-icon>settings_voice</mat-icon> | |
STT Advanced Settings | |
</mat-panel-title> | |
<mat-panel-description> | |
Configure speech recognition parameters | |
</mat-panel-description> | |
</mat-expansion-panel-header> | |
<div class="stt-settings-grid" *ngIf="environment.stt_settings"> | |
<mat-form-field appearance="outline"> | |
<mat-label>Speech Timeout (ms)</mat-label> | |
<input matInput type="number" | |
name="speechTimeout" | |
[value]="environment.stt_settings.speech_timeout_ms" | |
(input)="updateSTTSetting('speech_timeout_ms', +$any($event.target).value)" | |
min="500" max="5000" step="100" | |
[disabled]="loading"> | |
<mat-icon matPrefix>timer</mat-icon> | |
<mat-hint>Silence duration to end speech (500-5000ms)</mat-hint> | |
</mat-form-field> | |
<mat-form-field appearance="outline"> | |
<mat-label>Noise Reduction Level</mat-label> | |
<mat-select name="noiseReduction" | |
[value]="environment.stt_settings.noise_reduction_level" | |
(selectionChange)="updateSTTSetting('noise_reduction_level', $event.value)" | |
[disabled]="loading"> | |
<mat-option [value]="0">Off</mat-option> | |
<mat-option [value]="1">Low</mat-option> | |
<mat-option [value]="2">Medium</mat-option> | |
<mat-option [value]="3">High</mat-option> | |
</mat-select> | |
<mat-icon matPrefix>noise_aware</mat-icon> | |
</mat-form-field> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>VAD Sensitivity</mat-label> | |
<mat-slider min="0" max="1" step="0.1" | |
[discrete]="true" | |
[displayWith]="formatVAD"> | |
<input matSliderThumb | |
name="vadSensitivity" | |
[value]="environment.stt_settings.vad_sensitivity" | |
(input)="updateSTTSetting('vad_sensitivity', +$any($event.target).value)" | |
[disabled]="loading"> | |
</mat-slider> | |
<mat-icon matPrefix>graphic_eq</mat-icon> | |
<mat-hint>Voice activity detection sensitivity (0=low, 1=high)</mat-hint> | |
</mat-form-field> | |
<mat-form-field appearance="outline"> | |
<mat-label>Language</mat-label> | |
<mat-select name="sttLanguage" | |
[value]="environment.stt_settings.language" | |
(selectionChange)="updateSTTSetting('language', $event.value)" | |
[disabled]="loading"> | |
<mat-option value="tr-TR">Turkish (tr-TR)</mat-option> | |
<mat-option value="en-US">English (en-US)</mat-option> | |
<mat-option value="de-DE">German (de-DE)</mat-option> | |
<mat-option value="fr-FR">French (fr-FR)</mat-option> | |
<mat-option value="es-ES">Spanish (es-ES)</mat-option> | |
</mat-select> | |
<mat-icon matPrefix>language</mat-icon> | |
</mat-form-field> | |
<mat-form-field appearance="outline" | |
*ngIf="environment.stt_engine === 'google'"> | |
<mat-label>Model</mat-label> | |
<mat-select name="sttModel" | |
[value]="environment.stt_settings.model" | |
(selectionChange)="updateSTTSetting('model', $event.value)" | |
[disabled]="loading"> | |
<mat-option value="latest_long">Latest Long (Best for conversations)</mat-option> | |
<mat-option value="command_and_search">Command & Search (Short queries)</mat-option> | |
<mat-option value="phone_call">Phone Call (Telephony)</mat-option> | |
<mat-option value="video">Video (Multiple speakers)</mat-option> | |
</mat-select> | |
<mat-icon matPrefix>model_training</mat-icon> | |
</mat-form-field> | |
<div class="checkbox-group"> | |
<mat-checkbox name="useEnhanced" | |
[checked]="environment.stt_settings.use_enhanced" | |
(change)="updateSTTSetting('use_enhanced', $event.checked)" | |
[disabled]="loading || environment.stt_engine !== 'google'"> | |
Use Enhanced Model | |
<mat-icon matTooltip="Better accuracy but higher cost" class="info-icon">info</mat-icon> | |
</mat-checkbox> | |
<mat-checkbox name="enablePunctuation" | |
[checked]="environment.stt_settings.enable_punctuation" | |
(change)="updateSTTSetting('enable_punctuation', $event.checked)" | |
[disabled]="loading"> | |
Automatic Punctuation | |
</mat-checkbox> | |
<mat-checkbox name="interimResults" | |
[checked]="environment.stt_settings.interim_results" | |
(change)="updateSTTSetting('interim_results', $event.checked)" | |
[disabled]="loading"> | |
Show Interim Results | |
</mat-checkbox> | |
</div> | |
</div> | |
<div class="stt-info-card" *ngIf="environment.stt_engine === 'google'"> | |
<mat-icon>info</mat-icon> | |
<div> | |
<strong>Google Cloud Setup Required:</strong> | |
<ol> | |
<li>Create a Google Cloud project</li> | |
<li>Enable Speech-to-Text API</li> | |
<li>Create service account & download JSON key</li> | |
<li>Upload JSON key file as STT API Key</li> | |
</ol> | |
<p class="cost-info">Cost: ~$0.024/minute (standard), ~$0.036/minute (enhanced)</p> | |
</div> | |
</div> | |
</mat-expansion-panel> | |
<mat-expansion-panel class="prompt-panel"> | |
<mat-expansion-panel-header> | |
<mat-panel-title> | |
<mat-icon>psychology</mat-icon> | |
Internal System Prompt | |
</mat-panel-title> | |
<mat-panel-description> | |
Advanced configuration for LLM | |
</mat-panel-description> | |
</mat-expansion-panel-header> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Internal Prompt</mat-label> | |
<textarea | |
matInput | |
name="internalPrompt" | |
[(ngModel)]="environment.internal_prompt" | |
[disabled]="loading" | |
rows="10" | |
placeholder="Enter internal system prompt..." | |
></textarea> | |
<mat-hint>This prompt will be prepended to all project prompts</mat-hint> | |
</mat-form-field> | |
</mat-expansion-panel> | |
<div class="form-actions"> | |
<button | |
mat-raised-button | |
color="primary" | |
type="submit" | |
[disabled]="loading || !envForm.valid || saving" | |
> | |
@if (saving) { | |
<mat-spinner diameter="20"></mat-spinner> | |
Saving... | |
} @else { | |
<mat-icon>save</mat-icon> | |
Save | |
} | |
</button> | |
<button | |
mat-raised-button | |
type="button" | |
(click)="reloadFromSpark()" | |
[disabled]="loading || isGPTMode()" | |
> | |
<mat-icon>refresh</mat-icon> | |
Reload from Spark | |
</button> | |
</div> | |
</form> | |
</mat-card-content> | |
</mat-card> | |
</div> | |
`, | |
styles: [` | |
.environment-container { | |
max-width: 800px; | |
margin: 0 auto; | |
} | |
mat-card-header { | |
margin-bottom: 24px; | |
mat-card-title { | |
display: flex; | |
align-items: center; | |
gap: 8px; | |
font-size: 24px; | |
mat-icon { | |
font-size: 28px; | |
width: 28px; | |
height: 28px; | |
} | |
} | |
} | |
.info-card { | |
margin-bottom: 20px; | |
background-color: #e3f2fd; | |
mat-card-content { | |
display: flex; | |
gap: 16px; | |
align-items: flex-start; | |
mat-icon { | |
color: #1976d2; | |
margin-top: 4px; | |
} | |
p { | |
margin: 4px 0; | |
font-size: 14px; | |
} | |
} | |
} | |
.full-width { | |
width: 100%; | |
margin-bottom: 20px; | |
} | |
.engine-row { | |
display: flex; | |
gap: 16px; | |
align-items: flex-start; | |
margin-bottom: 20px; | |
.engine-field { | |
flex: 1; | |
} | |
.api-key-field { | |
flex: 1.5; | |
} | |
} | |
.prompt-panel { | |
margin-bottom: 20px; | |
mat-expansion-panel-header { | |
mat-panel-title { | |
display: flex; | |
align-items: center; | |
gap: 8px; | |
mat-icon { | |
color: #666; | |
} | |
} | |
} | |
} | |
.form-actions { | |
display: flex; | |
gap: 16px; | |
margin-top: 24px; | |
padding-top: 24px; | |
border-top: 1px solid #e0e0e0; | |
button { | |
mat-spinner { | |
margin-right: 8px; | |
vertical-align: middle; // Spinner'ı hizalamak için ekleyin | |
} | |
mat-icon { | |
vertical-align: middle; // Icon'u hizalamak için ekleyin | |
margin-right: 4px; // Icon ile text arasına boşluk | |
} | |
} | |
} | |
.stt-settings-panel { | |
margin-bottom: 20px; | |
.stt-settings-grid { | |
display: grid; | |
grid-template-columns: 1fr 1fr; | |
gap: 16px; | |
.full-width { | |
grid-column: 1 / -1; | |
} | |
.checkbox-group { | |
grid-column: 1 / -1; | |
display: flex; | |
flex-direction: column; | |
gap: 12px; | |
mat-checkbox { | |
display: flex; | |
align-items: center; | |
.info-icon { | |
font-size: 18px; | |
margin-left: 8px; | |
color: #666; | |
cursor: help; | |
} | |
} | |
} | |
} | |
.stt-info-card { | |
margin-top: 16px; | |
padding: 16px; | |
background-color: #e3f2fd; | |
border-radius: 4px; | |
display: flex; | |
gap: 16px; | |
mat-icon { | |
color: #1976d2; | |
flex-shrink: 0; | |
} | |
ol { | |
margin: 8px 0; | |
padding-left: 20px; | |
} | |
.cost-info { | |
margin-top: 8px; | |
font-size: 14px; | |
color: #666; | |
} | |
} | |
} | |
::ng-deep { | |
.mat-mdc-form-field-icon-prefix { | |
padding-right: 12px; | |
} | |
.mat-mdc-progress-spinner { | |
--mdc-circular-progress-active-indicator-color: white; | |
} | |
.mat-expansion-panel-body { | |
padding: 16px 0 !important; | |
} | |
} | |
`] | |
}) | |
export class EnvironmentComponent implements OnInit { | |
private apiService = inject(ApiService); | |
private snackBar = inject(MatSnackBar); | |
private environmentService = inject(EnvironmentService); | |
environment: Environment = { | |
work_mode: 'hfcloud', | |
cloud_token: '', | |
spark_endpoint: '', | |
internal_prompt: '', | |
tts_engine: 'no_tts', | |
tts_engine_api_key: '', | |
stt_engine: 'no_stt', | |
stt_engine_api_key: '', | |
stt_settings: { | |
speech_timeout_ms: 2000, | |
noise_reduction_level: 2, | |
vad_sensitivity: 0.5, | |
language: 'tr-TR', | |
model: 'latest_long', | |
use_enhanced: true, | |
enable_punctuation: true, | |
interim_results: true | |
} | |
}; | |
sttSettingsExpanded = false; | |
loading = true; | |
saving = false; | |
ngOnInit() { | |
console.log('EnvironmentComponent ngOnInit started'); | |
try { | |
this.loadEnvironment(); | |
} catch (error) { | |
console.error('Error in ngOnInit:', error); | |
console.error('Stack trace:', error.stack); | |
} | |
} | |
ngAfterViewInit() { | |
console.log('EnvironmentComponent ngAfterViewInit'); | |
console.log('Current environment:', this.environment); | |
console.log('STT settings:', this.environment.stt_settings); | |
} | |
loadEnvironment() { | |
console.log('loadEnvironment called'); | |
this.loading = true; | |
this.apiService.getEnvironment().subscribe({ | |
next: (env) => { | |
console.log('Environment loaded from API:', env); | |
this.environment = env; | |
// Debug check | |
console.log('Checking stt_settings:', this.environment.stt_settings); | |
if (!this.environment.stt_settings) { | |
console.log('No stt_settings found, creating defaults...'); | |
this.environment.stt_settings = { | |
speech_timeout_ms: 2000, | |
noise_reduction_level: 2, | |
vad_sensitivity: 0.5, | |
language: 'tr-TR', | |
model: 'latest_long', | |
use_enhanced: true, | |
enable_punctuation: true, | |
interim_results: true | |
}; | |
} | |
console.log('Final environment:', this.environment); | |
this.loading = false; | |
}, | |
error: (err) => { | |
console.error('Error loading environment:', err); | |
this.snackBar.open('Failed to load environment configuration', 'Close', { | |
duration: 5000, | |
panelClass: 'error-snackbar' | |
}); | |
this.loading = false; | |
} | |
}); | |
} | |
onSTTCredentialsFileSelected(event: any) { | |
const file = event.target.files[0]; | |
if (file && file.type === 'application/json') { | |
const reader = new FileReader(); | |
reader.onload = (e: any) => { | |
try { | |
// Validate it's a valid JSON | |
const jsonContent = JSON.parse(e.target.result); | |
// Store the entire JSON content as the API key | |
this.environment.stt_engine_api_key = e.target.result; | |
this.snackBar.open('Google credentials loaded successfully', 'Close', { | |
duration: 3000 | |
}); | |
} catch (error) { | |
this.snackBar.open('Invalid JSON file', 'Close', { | |
duration: 3000, | |
panelClass: 'error-snackbar' | |
}); | |
} | |
}; | |
reader.readAsText(file); | |
} | |
} | |
updateSTTSetting(key: string, value: any) { | |
if (!this.environment.stt_settings) { | |
this.environment.stt_settings = { | |
speech_timeout_ms: 2000, | |
noise_reduction_level: 2, | |
vad_sensitivity: 0.5, | |
language: 'tr-TR', | |
model: 'latest_long', | |
use_enhanced: true, | |
enable_punctuation: true, | |
interim_results: true | |
}; | |
} | |
(this.environment.stt_settings as any)[key] = value; | |
} | |
getTokenLabel(): string { | |
switch(this.environment.work_mode) { | |
case 'gpt4o': | |
case 'gpt4o-mini': | |
return 'OpenAI API Key'; | |
case 'hfcloud': | |
case 'cloud': | |
return 'Cloud Token'; | |
default: | |
return 'Cloud Token'; | |
} | |
} | |
getTokenPlaceholder(): string { | |
switch(this.environment.work_mode) { | |
case 'gpt4o': | |
case 'gpt4o-mini': | |
return 'Enter OpenAI API key (sk-...)'; | |
case 'hfcloud': | |
case 'cloud': | |
return 'Enter cloud token'; | |
default: | |
return 'Enter cloud token'; | |
} | |
} | |
isGPTMode(): boolean { | |
return this.environment.work_mode === 'gpt4o' || this.environment.work_mode === 'gpt4o-mini'; | |
} | |
onWorkModeChange() { | |
if (this.environment.work_mode === 'on-premise') { | |
this.environment.cloud_token = ''; | |
} | |
} | |
onSTTEngineChange() { | |
console.log('onSTTEngineChange called with:', this.environment.stt_engine); | |
console.log('Current stt_settings:', this.environment.stt_settings); | |
try { | |
if (this.environment.stt_engine === 'no_stt') { | |
this.environment.stt_engine_api_key = ''; | |
this.sttSettingsExpanded = false; | |
} else { | |
// Debug log | |
console.log('Setting up STT settings...'); | |
if (!this.environment.stt_settings) { | |
console.log('Creating new stt_settings...'); | |
this.environment.stt_settings = { | |
speech_timeout_ms: 2000, | |
noise_reduction_level: 2, | |
vad_sensitivity: 0.5, | |
language: 'tr-TR', | |
model: 'latest_long', | |
use_enhanced: true, | |
enable_punctuation: true, | |
interim_results: true | |
}; | |
} | |
this.sttSettingsExpanded = true; | |
console.log('STT settings after setup:', this.environment.stt_settings); | |
} | |
} catch (error) { | |
console.error('Error in onSTTEngineChange:', error); | |
console.error('Stack trace:', error.stack); | |
} | |
} | |
formatVAD(value: number): string { | |
return value.toFixed(1); | |
} | |
getSTTKeyPlaceholder(): string { | |
switch(this.environment.stt_engine) { | |
case 'google': | |
return 'Google service account JSON content'; | |
case 'azure': | |
return 'Azure subscription key'; | |
case 'amazon': | |
return 'AWS access key'; | |
case 'gpt4o_realtime': | |
return 'OpenAI API key'; | |
default: | |
return 'Enter API key'; | |
} | |
} | |
onSTTEngineChange() { | |
if (this.environment.stt_engine === 'no_stt') { | |
this.environment.stt_engine_api_key = ''; | |
this.sttSettingsExpanded = false; | |
} else { | |
// Ensure stt_settings exists when enabling STT | |
if (!this.environment.stt_settings) { | |
this.environment.stt_settings = { | |
speech_timeout_ms: 2000, | |
noise_reduction_level: 2, | |
vad_sensitivity: 0.5, | |
language: 'tr-TR', | |
model: 'latest_long', | |
use_enhanced: true, | |
enable_punctuation: true, | |
interim_results: true | |
}; | |
} | |
this.sttSettingsExpanded = true; | |
} | |
} | |
save() { | |
this.saving = true; | |
this.apiService.updateEnvironment(this.environment).subscribe({ | |
next: () => { | |
// Environment service'i güncelle | |
this.environmentService.updateEnvironment(this.environment); | |
this.snackBar.open('Environment configuration saved successfully', 'Close', { | |
duration: 3000 | |
}); | |
this.saving = false; | |
}, | |
error: (err) => { | |
this.snackBar.open( | |
err.error?.detail || 'Failed to save configuration', | |
'Close', | |
{ duration: 5000, panelClass: 'error-snackbar' } | |
); | |
this.saving = false; | |
} | |
}); | |
} | |
testConnection() { | |
this.snackBar.open('Testing connection to Spark endpoint...', undefined, { | |
duration: 2000 | |
}); | |
// TODO: Implement actual connection test | |
setTimeout(() => { | |
this.snackBar.open('Connection successful!', 'Close', { | |
duration: 3000 | |
}); | |
}, 2000); | |
} | |
reloadFromSpark() { | |
if (this.isGPTMode()) { | |
return; | |
} | |
this.snackBar.open('Reloading configuration from Spark...', undefined, { | |
duration: 2000 | |
}); | |
setTimeout(() => { | |
this.loadEnvironment(); | |
this.snackBar.open('Configuration reloaded', 'Close', { | |
duration: 3000 | |
}); | |
}, 1000); | |
} | |
} |