From 32c81f156d0341b4fd39ba1bc36486ba780ff0ff Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Mon, 7 Sep 2026 20:48:25 -0400 Subject: [PATCH] =?UTF-8?q?feat(settings):=20bouton=20"R=C3=A9initialiser"?= =?UTF-8?q?=20fournisseur=20IA=20+=20correctif=20JS=20(page=20compl=C3=A8t?= =?UTF-8?q?e)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Nouveau bouton « 🗑 Réinitialiser » dans Réglages → Agent & IA (réservé aux admins) : bascule le fournisseur par défaut sur « hors-ligne » et efface la clé API/base/état vérifié stockés (clear_keys dans set_llm_config). - Confirmation avant suppression des clés API utilisateur (deleteUserKey). - Correctif : chaîne JS de confirm("…") sur deux lignes provoquait une erreur de syntaxe → le script alpine:init ne s'exécutait pas et la page paramètres restait figée sur « Agent & AI » ; la chaîne est désormais sur une ligne. --- app/routers/agent.py | 1 + app/services/llm_config.py | 9 ++++++++- app/templates/settings.html | 28 ++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/app/routers/agent.py b/app/routers/agent.py index 5136411..16b454f 100644 --- a/app/routers/agent.py +++ b/app/routers/agent.py @@ -850,6 +850,7 @@ async def update_provider_config(request: Request): model=(body.get("model") or "").strip() or None, api_key=body.get("api_key"), api_base=(body.get("api_base") or "").strip() or None, + clear_keys=(provider == "offline"), ) llm = LLMClient() return { diff --git a/app/services/llm_config.py b/app/services/llm_config.py index 9a2dbb4..1f249c4 100644 --- a/app/services/llm_config.py +++ b/app/services/llm_config.py @@ -80,7 +80,8 @@ def get_llm_config() -> dict: def set_llm_config(*, provider: str | None = None, model: str | None = None, - api_key: str | None = None, api_base: str | None = None) -> dict: + api_key: str | None = None, api_base: str | None = None, + clear_keys: bool = False) -> dict: """Upsert the runtime LLM config row (id=1) and return the new effective config. An empty `api_key`/`api_base` keeps the stored value (so an admin can tweak @@ -103,6 +104,12 @@ def set_llm_config(*, provider: str | None = None, model: str | None = None, cfg["last_error"] = "" if api_base is not None and api_base.strip(): cfg["api_base"] = api_base.strip() + if clear_keys: + cfg["api_key"] = "" + cfg["api_base"] = "" + cfg["verified"] = 0 + cfg["verified_model"] = "" + cfg["last_error"] = "" with get_conn() as conn: conn.execute( diff --git a/app/templates/settings.html b/app/templates/settings.html index fdf619b..f5f1324 100644 --- a/app/templates/settings.html +++ b/app/templates/settings.html @@ -600,6 +600,7 @@ 🔌 Tester la connexion Test… +
@@ -1107,6 +1108,8 @@ document.addEventListener('alpine:init', function() { finally { f.testing = false; } }, async deleteUserKey(id) { + var pname = id.charAt(0).toUpperCase() + id.slice(1); + if (!confirm('Supprimer la clé API pour ' + pname + ' ?\nLe fournisseur ne sera plus disponible dans le panneau Agent.')) return; var f = this.keyForm(id); f.deleting = true; f.msg = ''; f.ok = false; try { @@ -1185,6 +1188,31 @@ document.addEventListener('alpine:init', function() { } catch(e) { this.llmMsg = 'Erreur réseau'; } finally { this.llmSaving = false; } }, + async resetGlobalLlm() { + if (!confirm("Réinitialiser le fournisseur par défaut à « hors-ligne » ?\nTous les utilisateurs perdront l'accès au fournisseur IA actuel.")) return; + this.llmSaving = true; + this.llmMsg = ''; this.llmMsgOk = false; + try { + var r = await this.adminFetch('/api/agent/providers', { + method: 'PATCH', + headers: {'Content-Type':'application/json'}, + body: JSON.stringify({provider: 'offline', model: '', api_key: '', api_base: ''}) + }); + var d = await r.json(); + if (r.ok) { + this.llmForm = {provider: 'offline', model: '', api_key: '', api_base: ''}; + this.llmHasKey = false; + this.llmDefaultProvider = 'offline'; + this.llmProviderModels = []; + this.llmMsgOk = true; + this.llmMsg = 'Fournisseur réinitialisé : mode hors-ligne actif.'; + this.syncLlmStatus(); + } else { + this.llmMsg = d.detail || 'Erreur lors de la réinitialisation'; + } + } catch(e) { this.llmMsg = 'Erreur réseau'; } + finally { this.llmSaving = false; } + }, async testLlm() { if (!this.llmForm.provider) return; this.llmTesting = true;