Spaces:
Running
Running
Update flare-ui/src/app/components/environment/environment.component.ts
Browse files
flare-ui/src/app/components/environment/environment.component.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
import { Component, OnInit } from '@angular/core';
|
2 |
import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
|
3 |
-
import {
|
|
|
4 |
import { ApiService } from '../../services/api.service';
|
5 |
import { EnvironmentService } from '../../services/environment.service';
|
6 |
import { CommonModule } from '@angular/common';
|
@@ -15,6 +16,8 @@ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
|
15 |
import { MatExpansionModule } from '@angular/material/expansion';
|
16 |
import { MatDividerModule } from '@angular/material/divider';
|
17 |
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
|
|
|
18 |
|
19 |
// Provider interfaces
|
20 |
interface ProviderConfig {
|
@@ -39,7 +42,6 @@ interface EnvironmentConfig {
|
|
39 |
tts_provider: ProviderSettings;
|
40 |
stt_provider: ProviderSettings;
|
41 |
providers: ProviderConfig[];
|
42 |
-
parameter_collection_config: any;
|
43 |
}
|
44 |
|
45 |
@Component({
|
@@ -48,6 +50,7 @@ interface EnvironmentConfig {
|
|
48 |
imports: [
|
49 |
CommonModule,
|
50 |
ReactiveFormsModule,
|
|
|
51 |
MatCardModule,
|
52 |
MatFormFieldModule,
|
53 |
MatInputModule,
|
@@ -58,7 +61,10 @@ interface EnvironmentConfig {
|
|
58 |
MatSlideToggleModule,
|
59 |
MatExpansionModule,
|
60 |
MatDividerModule,
|
61 |
-
MatProgressSpinnerModule
|
|
|
|
|
|
|
62 |
],
|
63 |
templateUrl: './environment.component.html',
|
64 |
styleUrls: ['./environment.component.scss']
|
@@ -67,6 +73,7 @@ export class EnvironmentComponent implements OnInit {
|
|
67 |
form: FormGroup;
|
68 |
loading = false;
|
69 |
saving = false;
|
|
|
70 |
|
71 |
// Provider lists
|
72 |
llmProviders: ProviderConfig[] = [];
|
@@ -78,9 +85,17 @@ export class EnvironmentComponent implements OnInit {
|
|
78 |
currentTTSProvider?: ProviderConfig;
|
79 |
currentSTTProvider?: ProviderConfig;
|
80 |
|
81 |
-
// Settings
|
82 |
-
|
83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
|
85 |
constructor(
|
86 |
private fb: FormBuilder,
|
@@ -110,196 +125,280 @@ export class EnvironmentComponent implements OnInit {
|
|
110 |
this.loadEnvironment();
|
111 |
}
|
112 |
|
113 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
this.loading = true;
|
|
|
|
|
115 |
this.apiService.getEnvironment().subscribe({
|
116 |
-
next: (data:
|
117 |
-
//
|
118 |
-
this.llmProviders = data.providers.filter(p => p.type === 'llm');
|
119 |
-
this.ttsProviders = data.providers.filter(p => p.type === 'tts');
|
120 |
-
this.sttProviders = data.providers.filter(p => p.type === 'stt');
|
121 |
-
|
122 |
-
// Load current settings
|
123 |
if (data.llm_provider) {
|
124 |
-
this.
|
125 |
-
|
126 |
-
|
127 |
-
llm_provider_endpoint: data.llm_provider.endpoint || ''
|
128 |
-
});
|
129 |
-
|
130 |
-
// Extract settings
|
131 |
-
this.internalPrompt = data.llm_provider.settings?.internal_prompt || '';
|
132 |
-
this.parameterCollectionConfig = data.llm_provider.settings?.parameter_collection_config || this.getDefaultParameterCollectionConfig();
|
133 |
-
|
134 |
-
this.onLLMProviderChange(data.llm_provider.name);
|
135 |
}
|
136 |
-
|
137 |
-
if (data.tts_provider) {
|
138 |
-
this.form.patchValue({
|
139 |
-
tts_provider_name: data.tts_provider.name,
|
140 |
-
tts_provider_api_key: data.tts_provider.api_key || '',
|
141 |
-
tts_provider_endpoint: data.tts_provider.endpoint || ''
|
142 |
-
});
|
143 |
-
this.onTTSProviderChange(data.tts_provider.name);
|
144 |
-
}
|
145 |
-
|
146 |
-
if (data.stt_provider) {
|
147 |
-
this.form.patchValue({
|
148 |
-
stt_provider_name: data.stt_provider.name,
|
149 |
-
stt_provider_api_key: data.stt_provider.api_key || '',
|
150 |
-
stt_provider_endpoint: data.stt_provider.endpoint || ''
|
151 |
-
});
|
152 |
-
this.onSTTProviderChange(data.stt_provider.name);
|
153 |
-
}
|
154 |
-
|
155 |
this.loading = false;
|
|
|
156 |
},
|
157 |
error: (err) => {
|
158 |
-
|
159 |
-
|
160 |
-
panelClass: 'error-snackbar'
|
161 |
-
});
|
162 |
this.loading = false;
|
|
|
163 |
}
|
164 |
});
|
165 |
}
|
166 |
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
apiKeyControl?.enable();
|
178 |
-
apiKeyControl?.setValidators([Validators.required]);
|
179 |
-
} else {
|
180 |
-
apiKeyControl?.disable();
|
181 |
-
apiKeyControl?.clearValidators();
|
182 |
-
}
|
183 |
-
|
184 |
-
// Endpoint field
|
185 |
-
if (this.currentLLMProvider.requires_endpoint) {
|
186 |
-
endpointControl?.enable();
|
187 |
-
endpointControl?.setValidators([Validators.required]);
|
188 |
-
} else {
|
189 |
-
endpointControl?.disable();
|
190 |
-
endpointControl?.clearValidators();
|
191 |
-
}
|
192 |
-
|
193 |
-
apiKeyControl?.updateValueAndValidity();
|
194 |
-
endpointControl?.updateValueAndValidity();
|
195 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
|
197 |
-
|
198 |
-
this.
|
|
|
|
|
199 |
}
|
200 |
|
201 |
-
|
202 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
|
204 |
-
|
205 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
|
207 |
-
if (this.
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
endpointControl?.setValue('');
|
226 |
-
}
|
227 |
-
|
228 |
-
apiKeyControl?.updateValueAndValidity();
|
229 |
-
endpointControl?.updateValueAndValidity();
|
230 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
}
|
232 |
|
233 |
-
|
234 |
-
this.
|
|
|
235 |
|
236 |
-
|
237 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
238 |
|
239 |
-
if (this.
|
240 |
-
|
241 |
-
if (this.currentSTTProvider.requires_api_key) {
|
242 |
-
apiKeyControl?.enable();
|
243 |
-
apiKeyControl?.setValidators([Validators.required]);
|
244 |
-
} else {
|
245 |
-
apiKeyControl?.disable();
|
246 |
-
apiKeyControl?.clearValidators();
|
247 |
-
apiKeyControl?.setValue('');
|
248 |
-
}
|
249 |
-
|
250 |
-
// Endpoint field
|
251 |
-
if (this.currentSTTProvider.requires_endpoint) {
|
252 |
-
endpointControl?.enable();
|
253 |
-
endpointControl?.setValidators([Validators.required]);
|
254 |
-
} else {
|
255 |
-
endpointControl?.disable();
|
256 |
-
endpointControl?.clearValidators();
|
257 |
-
endpointControl?.setValue('');
|
258 |
-
}
|
259 |
-
|
260 |
-
apiKeyControl?.updateValueAndValidity();
|
261 |
-
endpointControl?.updateValueAndValidity();
|
262 |
}
|
|
|
|
|
|
|
263 |
}
|
264 |
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
Rules:
|
277 |
-
1. Ask for maximum {{max_params}} parameters in one question
|
278 |
-
2. Group parameters that naturally go together (like from/to cities, dates)
|
279 |
-
3. If some parameters were asked before but not answered, include them again
|
280 |
-
4. Be natural and conversational in {{project_language}}
|
281 |
-
5. Use context from the conversation to make the question flow naturally
|
282 |
-
|
283 |
-
Generate ONLY the question, nothing else.`
|
284 |
-
};
|
285 |
}
|
286 |
|
287 |
-
|
288 |
if (this.form.invalid) {
|
289 |
-
this.
|
290 |
return;
|
291 |
}
|
292 |
|
293 |
this.saving = true;
|
294 |
-
|
295 |
const formValue = this.form.value;
|
296 |
-
|
297 |
-
// Build provider settings
|
298 |
const saveData = {
|
299 |
llm_provider: {
|
300 |
name: formValue.llm_provider_name,
|
301 |
-
api_key: formValue.llm_provider_api_key
|
302 |
-
endpoint: formValue.llm_provider_endpoint
|
303 |
settings: {
|
304 |
internal_prompt: this.internalPrompt,
|
305 |
parameter_collection_config: this.parameterCollectionConfig
|
@@ -307,159 +406,141 @@ Generate ONLY the question, nothing else.`
|
|
307 |
},
|
308 |
tts_provider: {
|
309 |
name: formValue.tts_provider_name,
|
310 |
-
api_key: formValue.tts_provider_api_key
|
311 |
-
endpoint: formValue.tts_provider_endpoint
|
312 |
settings: {}
|
313 |
},
|
314 |
stt_provider: {
|
315 |
name: formValue.stt_provider_name,
|
316 |
-
api_key: formValue.stt_provider_api_key
|
317 |
-
endpoint: formValue.stt_provider_endpoint
|
318 |
settings: {}
|
319 |
-
}
|
320 |
-
parameter_collection_config: this.parameterCollectionConfig
|
321 |
};
|
322 |
-
|
323 |
-
this.apiService.updateEnvironment(saveData).subscribe({
|
324 |
next: () => {
|
325 |
-
|
326 |
-
this.updateEnvironmentService();
|
327 |
-
|
328 |
-
this.snackBar.open('Environment configuration saved successfully', 'Close', {
|
329 |
-
duration: 3000
|
330 |
-
});
|
331 |
this.saving = false;
|
332 |
},
|
333 |
error: (err) => {
|
334 |
-
|
335 |
-
|
336 |
-
'Close',
|
337 |
-
{ duration: 5000, panelClass: 'error-snackbar' }
|
338 |
-
);
|
339 |
this.saving = false;
|
340 |
}
|
341 |
});
|
342 |
}
|
343 |
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
'spark':
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
}
|
358 |
-
|
359 |
-
getTTSProviderIcon(provider: ProviderConfig): string {
|
360 |
-
const iconMap: { [key: string]: string } = {
|
361 |
-
'no_tts': 'volume_off',
|
362 |
-
'elevenlabs': 'record_voice_over',
|
363 |
-
'blaze': 'campaign'
|
364 |
-
};
|
365 |
-
return iconMap[provider.name] || 'volume_up';
|
366 |
-
}
|
367 |
-
|
368 |
-
getSTTProviderIcon(provider: ProviderConfig): string {
|
369 |
-
const iconMap: { [key: string]: string } = {
|
370 |
-
'no_stt': 'mic_off',
|
371 |
-
'google': 'g_translate',
|
372 |
-
'azure': 'cloud',
|
373 |
-
'flicker': 'light_mode'
|
374 |
-
};
|
375 |
-
return iconMap[provider.name] || 'mic';
|
376 |
}
|
377 |
|
378 |
-
|
379 |
-
|
380 |
-
providerType === 'tts' ? this.currentTTSProvider :
|
381 |
-
this.currentSTTProvider;
|
382 |
-
|
383 |
-
if (!provider) return 'API Key';
|
384 |
|
385 |
-
|
386 |
-
|
387 |
-
|
|
|
|
|
|
|
|
|
388 |
}
|
389 |
-
|
390 |
-
return 'API Key';
|
391 |
}
|
392 |
|
393 |
-
|
394 |
-
|
395 |
-
providerType === 'tts' ? this.currentTTSProvider :
|
396 |
-
this.currentSTTProvider;
|
397 |
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
'
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
};
|
409 |
-
|
410 |
-
return placeholders[provider.name] || 'Enter API key';
|
411 |
}
|
412 |
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
'flicker': 'https://flicker-stt.example.com'
|
425 |
-
};
|
426 |
-
|
427 |
-
return placeholders[provider.name] || 'https://...';
|
428 |
}
|
429 |
|
430 |
-
|
431 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
432 |
}
|
433 |
|
434 |
-
|
435 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
436 |
}
|
437 |
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
|
|
|
|
|
|
|
|
444 |
}
|
|
|
|
|
|
|
|
|
|
|
445 |
|
|
|
446 |
const endpoint = this.form.get('llm_provider_endpoint')?.value;
|
447 |
if (!endpoint) {
|
448 |
-
this.snackBar.open('Please enter an endpoint URL', 'Close', {
|
449 |
-
duration: 3000
|
450 |
-
});
|
451 |
return;
|
452 |
}
|
453 |
-
|
454 |
-
this.snackBar.open('Testing connection...', undefined, {
|
455 |
-
duration: 2000
|
456 |
-
});
|
457 |
|
|
|
458 |
// TODO: Implement actual connection test
|
459 |
-
setTimeout(() => {
|
460 |
-
this.snackBar.open('Connection successful!', 'Close', {
|
461 |
-
duration: 3000
|
462 |
-
});
|
463 |
-
}, 2000);
|
464 |
}
|
465 |
}
|
|
|
1 |
import { Component, OnInit } from '@angular/core';
|
2 |
import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
|
3 |
+
import { FormsModule } from '@angular/forms';
|
4 |
+
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
|
5 |
import { ApiService } from '../../services/api.service';
|
6 |
import { EnvironmentService } from '../../services/environment.service';
|
7 |
import { CommonModule } from '@angular/common';
|
|
|
16 |
import { MatExpansionModule } from '@angular/material/expansion';
|
17 |
import { MatDividerModule } from '@angular/material/divider';
|
18 |
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
19 |
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
20 |
+
import { MatDialogModule } from '@angular/material/dialog';
|
21 |
|
22 |
// Provider interfaces
|
23 |
interface ProviderConfig {
|
|
|
42 |
tts_provider: ProviderSettings;
|
43 |
stt_provider: ProviderSettings;
|
44 |
providers: ProviderConfig[];
|
|
|
45 |
}
|
46 |
|
47 |
@Component({
|
|
|
50 |
imports: [
|
51 |
CommonModule,
|
52 |
ReactiveFormsModule,
|
53 |
+
FormsModule,
|
54 |
MatCardModule,
|
55 |
MatFormFieldModule,
|
56 |
MatInputModule,
|
|
|
61 |
MatSlideToggleModule,
|
62 |
MatExpansionModule,
|
63 |
MatDividerModule,
|
64 |
+
MatProgressSpinnerModule,
|
65 |
+
MatSnackBarModule,
|
66 |
+
MatTooltipModule,
|
67 |
+
MatDialogModule
|
68 |
],
|
69 |
templateUrl: './environment.component.html',
|
70 |
styleUrls: ['./environment.component.scss']
|
|
|
73 |
form: FormGroup;
|
74 |
loading = false;
|
75 |
saving = false;
|
76 |
+
isLoading = false;
|
77 |
|
78 |
// Provider lists
|
79 |
llmProviders: ProviderConfig[] = [];
|
|
|
85 |
currentTTSProvider?: ProviderConfig;
|
86 |
currentSTTProvider?: ProviderConfig;
|
87 |
|
88 |
+
// Settings for LLM
|
89 |
+
internalPrompt: string = '';
|
90 |
+
parameterCollectionConfig: any = {
|
91 |
+
enabled: false,
|
92 |
+
max_params_per_question: 1,
|
93 |
+
show_all_required: false,
|
94 |
+
ask_optional_params: false,
|
95 |
+
group_related_params: false,
|
96 |
+
min_confidence_score: 0.7,
|
97 |
+
collection_prompt: 'Please provide the following information:'
|
98 |
+
};
|
99 |
|
100 |
constructor(
|
101 |
private fb: FormBuilder,
|
|
|
125 |
this.loadEnvironment();
|
126 |
}
|
127 |
|
128 |
+
// Safe getters for template
|
129 |
+
get currentLLMProviderSafe(): ProviderConfig | null {
|
130 |
+
return this.currentLLMProvider || null;
|
131 |
+
}
|
132 |
+
|
133 |
+
get currentTTSProviderSafe(): ProviderConfig | null {
|
134 |
+
return this.currentTTSProvider || null;
|
135 |
+
}
|
136 |
+
|
137 |
+
get currentSTTProviderSafe(): ProviderConfig | null {
|
138 |
+
return this.currentSTTProvider || null;
|
139 |
+
}
|
140 |
+
|
141 |
+
loadEnvironment(): void {
|
142 |
this.loading = true;
|
143 |
+
this.isLoading = true;
|
144 |
+
|
145 |
this.apiService.getEnvironment().subscribe({
|
146 |
+
next: (data: any) => {
|
147 |
+
// Check if it's new format or legacy
|
|
|
|
|
|
|
|
|
|
|
148 |
if (data.llm_provider) {
|
149 |
+
this.handleNewFormat(data);
|
150 |
+
} else {
|
151 |
+
this.handleLegacyFormat(data);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
153 |
this.loading = false;
|
154 |
+
this.isLoading = false;
|
155 |
},
|
156 |
error: (err) => {
|
157 |
+
console.error('Failed to load environment:', err);
|
158 |
+
this.snackBar.open('Failed to load environment configuration', 'Close', { duration: 3000 });
|
|
|
|
|
159 |
this.loading = false;
|
160 |
+
this.isLoading = false;
|
161 |
}
|
162 |
});
|
163 |
}
|
164 |
|
165 |
+
handleNewFormat(data: EnvironmentConfig): void {
|
166 |
+
// Update provider lists
|
167 |
+
if (data.providers) {
|
168 |
+
this.llmProviders = data.providers.filter(p => p.type === 'llm');
|
169 |
+
this.ttsProviders = data.providers.filter(p => p.type === 'tts');
|
170 |
+
this.sttProviders = data.providers.filter(p => p.type === 'stt');
|
171 |
+
}
|
172 |
+
|
173 |
+
// Set form values
|
174 |
+
this.form.patchValue({
|
175 |
+
llm_provider_name: data.llm_provider?.name || '',
|
176 |
+
llm_provider_api_key: data.llm_provider?.api_key || '',
|
177 |
+
llm_provider_endpoint: data.llm_provider?.endpoint || '',
|
178 |
+
tts_provider_name: data.tts_provider?.name || 'no_tts',
|
179 |
+
tts_provider_api_key: data.tts_provider?.api_key || '',
|
180 |
+
tts_provider_endpoint: data.tts_provider?.endpoint || '',
|
181 |
+
stt_provider_name: data.stt_provider?.name || 'no_stt',
|
182 |
+
stt_provider_api_key: data.stt_provider?.api_key || '',
|
183 |
+
stt_provider_endpoint: data.stt_provider?.endpoint || ''
|
184 |
+
});
|
185 |
+
|
186 |
+
// Set internal prompt and parameter collection config
|
187 |
+
this.internalPrompt = data.llm_provider?.settings?.internal_prompt || '';
|
188 |
+
this.parameterCollectionConfig = data.llm_provider?.settings?.parameter_collection_config || this.parameterCollectionConfig;
|
189 |
+
|
190 |
+
// Update current providers
|
191 |
+
this.updateCurrentProviders();
|
192 |
|
193 |
+
// Notify environment service
|
194 |
+
if (data.tts_provider?.name !== 'no_tts') {
|
195 |
+
this.environmentService.setTTSEnabled(true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
}
|
197 |
+
if (data.stt_provider?.name !== 'no_stt') {
|
198 |
+
this.environmentService.setSTTEnabled(true);
|
199 |
+
}
|
200 |
+
}
|
201 |
+
|
202 |
+
handleLegacyFormat(data: any): void {
|
203 |
+
console.warn('Legacy environment format detected, using defaults');
|
204 |
+
|
205 |
+
// Set default providers if not present
|
206 |
+
this.llmProviders = this.getDefaultProviders('llm');
|
207 |
+
this.ttsProviders = this.getDefaultProviders('tts');
|
208 |
+
this.sttProviders = this.getDefaultProviders('stt');
|
209 |
+
|
210 |
+
// Map legacy fields
|
211 |
+
this.form.patchValue({
|
212 |
+
llm_provider_name: data.work_mode || 'spark',
|
213 |
+
llm_provider_api_key: data.cloud_token || '',
|
214 |
+
llm_provider_endpoint: data.spark_endpoint || '',
|
215 |
+
tts_provider_name: data.tts_engine || 'no_tts',
|
216 |
+
tts_provider_api_key: data.tts_engine_api_key || '',
|
217 |
+
stt_provider_name: data.stt_engine || 'no_stt',
|
218 |
+
stt_provider_api_key: data.stt_engine_api_key || ''
|
219 |
+
});
|
220 |
|
221 |
+
this.internalPrompt = data.internal_prompt || '';
|
222 |
+
this.parameterCollectionConfig = data.parameter_collection_config || this.parameterCollectionConfig;
|
223 |
+
|
224 |
+
this.updateCurrentProviders();
|
225 |
}
|
226 |
|
227 |
+
getDefaultProviders(type: string): ProviderConfig[] {
|
228 |
+
const defaults: { [key: string]: ProviderConfig[] } = {
|
229 |
+
llm: [
|
230 |
+
{
|
231 |
+
type: 'llm',
|
232 |
+
name: 'spark',
|
233 |
+
display_name: 'Spark (YTU Cosmos)',
|
234 |
+
requires_endpoint: true,
|
235 |
+
requires_api_key: true,
|
236 |
+
requires_repo_info: true,
|
237 |
+
description: 'YTU Cosmos Spark LLM Service'
|
238 |
+
},
|
239 |
+
{
|
240 |
+
type: 'llm',
|
241 |
+
name: 'gpt4o',
|
242 |
+
display_name: 'GPT-4o',
|
243 |
+
requires_endpoint: false,
|
244 |
+
requires_api_key: true,
|
245 |
+
requires_repo_info: false,
|
246 |
+
description: 'OpenAI GPT-4o model'
|
247 |
+
},
|
248 |
+
{
|
249 |
+
type: 'llm',
|
250 |
+
name: 'gpt4o-mini',
|
251 |
+
display_name: 'GPT-4o Mini',
|
252 |
+
requires_endpoint: false,
|
253 |
+
requires_api_key: true,
|
254 |
+
requires_repo_info: false,
|
255 |
+
description: 'OpenAI GPT-4o Mini model'
|
256 |
+
}
|
257 |
+
],
|
258 |
+
tts: [
|
259 |
+
{
|
260 |
+
type: 'tts',
|
261 |
+
name: 'no_tts',
|
262 |
+
display_name: 'No TTS',
|
263 |
+
requires_endpoint: false,
|
264 |
+
requires_api_key: false,
|
265 |
+
requires_repo_info: false,
|
266 |
+
description: 'Disable text-to-speech'
|
267 |
+
},
|
268 |
+
{
|
269 |
+
type: 'tts',
|
270 |
+
name: 'elevenlabs',
|
271 |
+
display_name: 'ElevenLabs',
|
272 |
+
requires_endpoint: false,
|
273 |
+
requires_api_key: true,
|
274 |
+
requires_repo_info: false,
|
275 |
+
description: 'ElevenLabs TTS service'
|
276 |
+
}
|
277 |
+
],
|
278 |
+
stt: [
|
279 |
+
{
|
280 |
+
type: 'stt',
|
281 |
+
name: 'no_stt',
|
282 |
+
display_name: 'No STT',
|
283 |
+
requires_endpoint: false,
|
284 |
+
requires_api_key: false,
|
285 |
+
requires_repo_info: false,
|
286 |
+
description: 'Disable speech-to-text'
|
287 |
+
},
|
288 |
+
{
|
289 |
+
type: 'stt',
|
290 |
+
name: 'google',
|
291 |
+
display_name: 'Google Cloud STT',
|
292 |
+
requires_endpoint: false,
|
293 |
+
requires_api_key: true,
|
294 |
+
requires_repo_info: false,
|
295 |
+
description: 'Google Cloud Speech-to-Text'
|
296 |
+
}
|
297 |
+
]
|
298 |
+
};
|
299 |
|
300 |
+
return defaults[type] || [];
|
301 |
+
}
|
302 |
+
|
303 |
+
updateCurrentProviders(): void {
|
304 |
+
const llmName = this.form.get('llm_provider_name')?.value;
|
305 |
+
const ttsName = this.form.get('tts_provider_name')?.value;
|
306 |
+
const sttName = this.form.get('stt_provider_name')?.value;
|
307 |
+
|
308 |
+
this.currentLLMProvider = this.llmProviders.find(p => p.name === llmName);
|
309 |
+
this.currentTTSProvider = this.ttsProviders.find(p => p.name === ttsName);
|
310 |
+
this.currentSTTProvider = this.sttProviders.find(p => p.name === sttName);
|
311 |
+
|
312 |
+
// Update form validators based on requirements
|
313 |
+
this.updateFormValidators();
|
314 |
+
}
|
315 |
+
|
316 |
+
updateFormValidators(): void {
|
317 |
+
// LLM validators
|
318 |
+
if (this.currentLLMProvider?.requires_api_key) {
|
319 |
+
this.form.get('llm_provider_api_key')?.setValidators(Validators.required);
|
320 |
+
} else {
|
321 |
+
this.form.get('llm_provider_api_key')?.clearValidators();
|
322 |
+
}
|
323 |
|
324 |
+
if (this.currentLLMProvider?.requires_endpoint) {
|
325 |
+
this.form.get('llm_provider_endpoint')?.setValidators(Validators.required);
|
326 |
+
} else {
|
327 |
+
this.form.get('llm_provider_endpoint')?.clearValidators();
|
328 |
+
}
|
329 |
+
|
330 |
+
// TTS validators
|
331 |
+
if (this.currentTTSProvider?.requires_api_key) {
|
332 |
+
this.form.get('tts_provider_api_key')?.setValidators(Validators.required);
|
333 |
+
} else {
|
334 |
+
this.form.get('tts_provider_api_key')?.clearValidators();
|
335 |
+
}
|
336 |
+
|
337 |
+
// STT validators
|
338 |
+
if (this.currentSTTProvider?.requires_api_key) {
|
339 |
+
this.form.get('stt_provider_api_key')?.setValidators(Validators.required);
|
340 |
+
} else {
|
341 |
+
this.form.get('stt_provider_api_key')?.clearValidators();
|
|
|
|
|
|
|
|
|
|
|
342 |
}
|
343 |
+
|
344 |
+
// Update validity
|
345 |
+
this.form.get('llm_provider_api_key')?.updateValueAndValidity();
|
346 |
+
this.form.get('llm_provider_endpoint')?.updateValueAndValidity();
|
347 |
+
this.form.get('tts_provider_api_key')?.updateValueAndValidity();
|
348 |
+
this.form.get('stt_provider_api_key')?.updateValueAndValidity();
|
349 |
}
|
350 |
|
351 |
+
onLLMProviderChange(value: string): void {
|
352 |
+
this.currentLLMProvider = this.llmProviders.find(p => p.name === value);
|
353 |
+
this.updateFormValidators();
|
354 |
|
355 |
+
// Reset fields if provider doesn't require them
|
356 |
+
if (!this.currentLLMProvider?.requires_api_key) {
|
357 |
+
this.form.get('llm_provider_api_key')?.setValue('');
|
358 |
+
}
|
359 |
+
if (!this.currentLLMProvider?.requires_endpoint) {
|
360 |
+
this.form.get('llm_provider_endpoint')?.setValue('');
|
361 |
+
}
|
362 |
+
}
|
363 |
+
|
364 |
+
onTTSProviderChange(value: string): void {
|
365 |
+
this.currentTTSProvider = this.ttsProviders.find(p => p.name === value);
|
366 |
+
this.updateFormValidators();
|
367 |
|
368 |
+
if (!this.currentTTSProvider?.requires_api_key) {
|
369 |
+
this.form.get('tts_provider_api_key')?.setValue('');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
370 |
}
|
371 |
+
|
372 |
+
// Notify environment service
|
373 |
+
this.environmentService.setTTSEnabled(value !== 'no_tts');
|
374 |
}
|
375 |
|
376 |
+
onSTTProviderChange(value: string): void {
|
377 |
+
this.currentSTTProvider = this.sttProviders.find(p => p.name === value);
|
378 |
+
this.updateFormValidators();
|
379 |
+
|
380 |
+
if (!this.currentSTTProvider?.requires_api_key) {
|
381 |
+
this.form.get('stt_provider_api_key')?.setValue('');
|
382 |
+
}
|
383 |
+
|
384 |
+
// Notify environment service
|
385 |
+
this.environmentService.setSTTEnabled(value !== 'no_stt');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
386 |
}
|
387 |
|
388 |
+
saveEnvironment(): void {
|
389 |
if (this.form.invalid) {
|
390 |
+
this.snackBar.open('Please fix validation errors', 'Close', { duration: 3000 });
|
391 |
return;
|
392 |
}
|
393 |
|
394 |
this.saving = true;
|
|
|
395 |
const formValue = this.form.value;
|
396 |
+
|
|
|
397 |
const saveData = {
|
398 |
llm_provider: {
|
399 |
name: formValue.llm_provider_name,
|
400 |
+
api_key: formValue.llm_provider_api_key,
|
401 |
+
endpoint: formValue.llm_provider_endpoint,
|
402 |
settings: {
|
403 |
internal_prompt: this.internalPrompt,
|
404 |
parameter_collection_config: this.parameterCollectionConfig
|
|
|
406 |
},
|
407 |
tts_provider: {
|
408 |
name: formValue.tts_provider_name,
|
409 |
+
api_key: formValue.tts_provider_api_key,
|
410 |
+
endpoint: formValue.tts_provider_endpoint,
|
411 |
settings: {}
|
412 |
},
|
413 |
stt_provider: {
|
414 |
name: formValue.stt_provider_name,
|
415 |
+
api_key: formValue.stt_provider_api_key,
|
416 |
+
endpoint: formValue.stt_provider_endpoint,
|
417 |
settings: {}
|
418 |
+
}
|
|
|
419 |
};
|
420 |
+
|
421 |
+
this.apiService.updateEnvironment(saveData as any).subscribe({
|
422 |
next: () => {
|
423 |
+
this.snackBar.open('Environment configuration saved successfully', 'Close', { duration: 3000 });
|
|
|
|
|
|
|
|
|
|
|
424 |
this.saving = false;
|
425 |
},
|
426 |
error: (err) => {
|
427 |
+
console.error('Failed to save environment:', err);
|
428 |
+
this.snackBar.open('Failed to save environment configuration', 'Close', { duration: 3000 });
|
|
|
|
|
|
|
429 |
this.saving = false;
|
430 |
}
|
431 |
});
|
432 |
}
|
433 |
|
434 |
+
// Icon helpers
|
435 |
+
getLLMProviderIcon(provider: ProviderConfig | null): string {
|
436 |
+
if (!provider || !provider.name) return 'smart_toy';
|
437 |
+
|
438 |
+
switch(provider.name) {
|
439 |
+
case 'gpt4o':
|
440 |
+
case 'gpt4o-mini':
|
441 |
+
return 'psychology';
|
442 |
+
case 'spark':
|
443 |
+
return 'auto_awesome';
|
444 |
+
default:
|
445 |
+
return 'smart_toy';
|
446 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
447 |
}
|
448 |
|
449 |
+
getTTSProviderIcon(provider: ProviderConfig | null): string {
|
450 |
+
if (!provider || !provider.name) return 'record_voice_over';
|
|
|
|
|
|
|
|
|
451 |
|
452 |
+
switch(provider.name) {
|
453 |
+
case 'elevenlabs':
|
454 |
+
return 'graphic_eq';
|
455 |
+
case 'blaze':
|
456 |
+
return 'volume_up';
|
457 |
+
default:
|
458 |
+
return 'record_voice_over';
|
459 |
}
|
|
|
|
|
460 |
}
|
461 |
|
462 |
+
getSTTProviderIcon(provider: ProviderConfig | null): string {
|
463 |
+
if (!provider || !provider.name) return 'mic';
|
|
|
|
|
464 |
|
465 |
+
switch(provider.name) {
|
466 |
+
case 'google':
|
467 |
+
return 'g_translate';
|
468 |
+
case 'azure':
|
469 |
+
return 'cloud';
|
470 |
+
case 'flicker':
|
471 |
+
return 'mic_none';
|
472 |
+
default:
|
473 |
+
return 'mic';
|
474 |
+
}
|
|
|
|
|
|
|
475 |
}
|
476 |
|
477 |
+
getProviderIcon(provider: ProviderConfig): string {
|
478 |
+
switch(provider.type) {
|
479 |
+
case 'llm':
|
480 |
+
return this.getLLMProviderIcon(provider);
|
481 |
+
case 'tts':
|
482 |
+
return this.getTTSProviderIcon(provider);
|
483 |
+
case 'stt':
|
484 |
+
return this.getSTTProviderIcon(provider);
|
485 |
+
default:
|
486 |
+
return 'settings';
|
487 |
+
}
|
|
|
|
|
|
|
|
|
488 |
}
|
489 |
|
490 |
+
// Helper methods
|
491 |
+
getApiKeyLabel(type: string): string {
|
492 |
+
switch(type) {
|
493 |
+
case 'llm':
|
494 |
+
return this.currentLLMProvider?.name === 'spark' ? 'API Token' : 'API Key';
|
495 |
+
case 'tts':
|
496 |
+
return 'API Key';
|
497 |
+
case 'stt':
|
498 |
+
return this.currentSTTProvider?.name === 'google' ? 'Credentials JSON Path' : 'API Key';
|
499 |
+
default:
|
500 |
+
return 'API Key';
|
501 |
+
}
|
502 |
}
|
503 |
|
504 |
+
getApiKeyPlaceholder(type: string): string {
|
505 |
+
switch(type) {
|
506 |
+
case 'llm':
|
507 |
+
if (this.currentLLMProvider?.name === 'spark') return 'Enter Spark token';
|
508 |
+
if (this.currentLLMProvider?.name?.includes('gpt')) return 'sk-...';
|
509 |
+
return 'Enter API key';
|
510 |
+
case 'tts':
|
511 |
+
return 'Enter TTS API key';
|
512 |
+
case 'stt':
|
513 |
+
return this.currentSTTProvider?.name === 'google' ? '/path/to/credentials.json' : 'Enter STT API key';
|
514 |
+
default:
|
515 |
+
return 'Enter API key';
|
516 |
+
}
|
517 |
}
|
518 |
|
519 |
+
getEndpointPlaceholder(type: string): string {
|
520 |
+
switch(type) {
|
521 |
+
case 'llm':
|
522 |
+
return 'https://spark-api.example.com';
|
523 |
+
case 'tts':
|
524 |
+
return 'https://tts-api.example.com';
|
525 |
+
case 'stt':
|
526 |
+
return 'https://stt-api.example.com';
|
527 |
+
default:
|
528 |
+
return 'https://api.example.com';
|
529 |
}
|
530 |
+
}
|
531 |
+
|
532 |
+
resetCollectionPrompt(): void {
|
533 |
+
this.parameterCollectionConfig.collection_prompt = 'Please provide the following information:';
|
534 |
+
}
|
535 |
|
536 |
+
testConnection(): void {
|
537 |
const endpoint = this.form.get('llm_provider_endpoint')?.value;
|
538 |
if (!endpoint) {
|
539 |
+
this.snackBar.open('Please enter an endpoint URL', 'Close', { duration: 2000 });
|
|
|
|
|
540 |
return;
|
541 |
}
|
|
|
|
|
|
|
|
|
542 |
|
543 |
+
this.snackBar.open('Testing connection...', 'Close', { duration: 2000 });
|
544 |
// TODO: Implement actual connection test
|
|
|
|
|
|
|
|
|
|
|
545 |
}
|
546 |
}
|