import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; /** * Reflet de SettingsDTO cote Brain / SettingsController cote Core. * `onemin_api_key_set` indique si une cle est configuree, sans la reveler. */ export interface AppSettings { llm_provider: 'ollama' | 'onemin'; ollama_base_url: string; llm_model: string; onemin_model: string; onemin_api_key_set: boolean; llm_num_ctx: number; } /** * Patch partiel — seuls les champs a modifier sont presents. * `onemin_api_key: ''` efface la cle, `null`/absent ne touche a rien. */ export interface AppSettingsUpdate { llm_provider?: 'ollama' | 'onemin'; ollama_base_url?: string; llm_model?: string; onemin_model?: string; onemin_api_key?: string; llm_num_ctx?: number; } /** Metadonnees d'un modele Ollama (issues de /api/show). */ export interface OllamaModelInfo { /** Fenetre de contexte max du modele (en tokens). 0 si inconnue. */ context_length: number; } @Injectable({ providedIn: 'root' }) export class SettingsService { private readonly apiUrl = '/api/settings'; // HTTP Basic : le browser gere le prompt natif de credentials au premier 401. // withCredentials=true pour que les creds soient renvoyees sur les appels // suivants en cross-origin (dev Angular sur :4200 -> core sur :8080). private readonly authOptions = { withCredentials: true }; constructor(private http: HttpClient) {} getSettings(): Observable { return this.http.get(this.apiUrl, this.authOptions); } updateSettings(patch: AppSettingsUpdate): Observable { return this.http.put(this.apiUrl, patch, this.authOptions); } listOllamaModels(): Observable<{ models: string[] }> { return this.http.get<{ models: string[] }>(`${this.apiUrl}/models/ollama`, this.authOptions); } getOllamaModelInfo(name: string): Observable { return this.http.post( `${this.apiUrl}/models/ollama/info`, { name }, this.authOptions); } listOneMinModels(): Observable<{ groups: OneMinModelGroup[] }> { return this.http.get<{ groups: OneMinModelGroup[] }>(`${this.apiUrl}/models/onemin`, this.authOptions); } } /** Un groupe de modeles 1min.ai regroupes par fournisseur (Anthropic, OpenAI, ...). */ export interface OneMinModelGroup { provider: string; models: string[]; }