fix(agent): validation robuste des modeles Nvidia (payload production + repli 404/410) + logo noir/blanc
Validation: - _validate_chat_models utilise le payload de production (temperature 0.2, sans max_tokens) : un 200 a la validation == 200 a l'usage reel. - Race corrigee : payload reconstruit par modele (plus de noms croises entre requetes concurrentes) — la v5.1.8 retombait par intermittence sur la liste brute (68 modeles dont la plupart en 404/410). - Retente une fois sur timeout/5xx (les modeles lents mais fonctionnels survivent) ; rejette les 4xx (404 inconnu, 410 retire) ; garde les 429. - Verifie en live contre l'API NVIDIA : 12 modeles valides au lieu de 68. Repli runtime: - LLMClient._http_complete : sur 404/410, retente une fois avec le modele par defaut du provider et marque un notice dans LLMResponse. - AgentEngine emet un evenement SSE "notice" (bandeau .fd-ap-notice dans le panneau Agent, reset a chaque conversation) ; le modele reel est persistee. UI: - FAB (rond bas droite) et logo header du panneau : rond noir/blanc qui suit le theme clair/sombre (--text-primary / --bg-primary), eclair monochrome SVG a la place de l'emoji robot. Tests: - 2 nouveaux tests (429 garde / 410 retire ; repli runtime sur 410). - 278 tests passent.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{# ════════════ FlowDeck Agent panel v4.13.0 — Notion-AI-style sidebar ════════════ #}
|
||||
<style>
|
||||
#fd-agent-fab{position:fixed;right:22px;bottom:22px;width:54px;height:54px;border-radius:50%;background:var(--accent,#2383E2);color:#fff;border:none;font-size:24px;cursor:pointer;box-shadow:0 8px 26px rgba(35,131,226,.5);display:flex;align-items:center;justify-content:center;z-index:1700;transition:transform .15s,box-shadow .15s}
|
||||
#fd-agent-fab:hover{transform:scale(1.06);box-shadow:0 12px 34px rgba(35,131,226,.62)}
|
||||
#fd-agent-fab{position:fixed;right:22px;bottom:22px;width:54px;height:54px;border-radius:50%;background:var(--text-primary,#37352F);color:var(--bg-primary,#fff);border:none;cursor:pointer;box-shadow:0 8px 26px rgba(0,0,0,.35);display:flex;align-items:center;justify-content:center;z-index:1700;transition:transform .15s,box-shadow .15s}
|
||||
#fd-agent-fab:hover{transform:scale(1.06);box-shadow:0 12px 34px rgba(0,0,0,.45)}
|
||||
#fd-agent-panel{position:fixed;top:0;right:0;bottom:0;width:470px;max-width:100vw;background:var(--bg-primary,#191919);border-left:1px solid var(--border,rgba(255,255,255,.1));z-index:1850;display:flex;flex-direction:column;box-shadow:-16px 0 48px rgba(0,0,0,.55);transform:translateX(102%);transition:transform .24s cubic-bezier(.16,1,.3,1)}
|
||||
#fd-agent-panel.open{transform:translateX(0)}
|
||||
#fd-agent-panel ::-webkit-scrollbar{width:8px;height:8px}
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
/* Header */
|
||||
.fd-ap-head{display:flex;align-items:center;gap:12px;padding:16px 18px 12px}
|
||||
.fd-ap-logo{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--accent,#2383E2),#5b8def);color:#fff;display:flex;align-items:center;justify-content:center;font-size:19px;flex-shrink:0;box-shadow:0 4px 12px rgba(35,131,226,.35)}
|
||||
.fd-ap-logo{width:36px;height:36px;border-radius:50%;background:var(--text-primary,#37352F);color:var(--bg-primary,#fff);display:flex;align-items:center;justify-content:center;flex-shrink:0;box-shadow:0 2px 8px rgba(0,0,0,.25)}
|
||||
.fd-ap-head-main{flex:1;min-width:0}
|
||||
.fd-ap-title{font-size:15px;font-weight:600;color:var(--text,#f0f0f0);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.fd-ap-sub{font-size:11.5px;color:var(--text-dim,#9aa);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
@@ -64,6 +64,7 @@
|
||||
.fd-proposal-note{font-size:11px;color:var(--text-dim,#999)}
|
||||
.fd-agent-thinking{font-size:12.5px;color:var(--text-dim,#999);padding:10px 12px;border-radius:9px;background:rgba(255,255,255,.04);margin:4px 0 8px;font-style:italic}
|
||||
.fd-ap-err{color:#ef8a8a;font-size:12px;padding:4px 2px}
|
||||
.fd-ap-notice{color:var(--text-secondary,#ccc);font-size:12px;padding:7px 10px;margin:2px 0 8px;border-radius:9px;background:rgba(128,128,128,.12);border:1px solid var(--border,rgba(255,255,255,.12))}
|
||||
|
||||
/* Composer */
|
||||
.fd-ap-composer{padding:10px 14px 14px;border-top:1px solid var(--border,rgba(255,255,255,.09));position:relative}
|
||||
@@ -191,12 +192,12 @@
|
||||
</script>
|
||||
|
||||
{# ── Floating button ── #}
|
||||
<button id="fd-agent-fab" title="FlowDeck Agent (Ctrl+J)" onclick="window.fdAgent&&window.fdAgent.toggle()">🤖</button>
|
||||
<button id="fd-agent-fab" title="FlowDeck Agent (Ctrl+J)" onclick="window.fdAgent&&window.fdAgent.toggle()"><svg viewBox="0 0 24 24" width="26" height="26" fill="currentColor" aria-hidden="true"><path d="M12 3l1.9 5.8a2 2 0 0 0 1.3 1.3L21 12l-5.8 1.9a2 2 0 0 0-1.3 1.3L12 21l-1.9-5.8a2 2 0 0 0-1.3-1.3L3 12l5.8-1.9a2 2 0 0 0 1.3-1.3L12 3Z"/></svg></button>
|
||||
|
||||
{# ── Panel ── #}
|
||||
<div id="fd-agent-panel" class="fd-ap" :class="{open: open}" x-data="agentPanel()" @keydown.escape.window="close()" role="dialog" aria-label="Agent FlowDeck">
|
||||
<div class="fd-ap-head">
|
||||
<span class="fd-ap-logo">🤖</span>
|
||||
<span class="fd-ap-logo"><svg viewBox="0 0 24 24" width="19" height="19" fill="currentColor" aria-hidden="true"><path d="M12 3l1.9 5.8a2 2 0 0 0 1.3 1.3L21 12l-5.8 1.9a2 2 0 0 0-1.3 1.3L12 21l-1.9-5.8a2 2 0 0 0-1.3-1.3L3 12l5.8-1.9a2 2 0 0 0 1.3-1.3L12 3Z"/></svg></span>
|
||||
<div class="fd-ap-head-main">
|
||||
<div class="fd-ap-title">How can I help you today?</div>
|
||||
<div class="fd-ap-sub" x-text="providerModelLabel"></div>
|
||||
@@ -276,6 +277,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<div class="fd-agent-thinking" x-show="streaming">L'agent réfléchit et agit… <span x-text="liveReasoning"></span></div>
|
||||
<div class="fd-ap-notice" x-show="notice" x-cloak x-text="notice"></div>
|
||||
<div class="fd-ap-err" x-show="errorMsg" x-text="errorMsg"></div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -412,7 +414,7 @@
|
||||
open: false, modelOpen: false, tab: 'chat',
|
||||
agents: [], conversations: [], currentConv: null,
|
||||
messages: [], input: '', streaming: false, liveReasoning: '',
|
||||
provider: 'offline', providerAvailable: false, errorMsg: '',
|
||||
provider: 'offline', providerAvailable: false, errorMsg: '', notice: '',
|
||||
allProviders: [], providers: [], providerModels: [], llmProvider: 'offline',
|
||||
llmModel: '', llmKeys: [], defaultProvider: 'offline',
|
||||
activeContext: null, ctxPinnedKey: null,
|
||||
@@ -756,7 +758,7 @@
|
||||
.then(function(r){return r.json()}).then(function(d){
|
||||
var conv = {id:d.id, title:d.title, updated_at:new Date().toISOString()};
|
||||
self.conversations.unshift(conv); self.currentConv = conv;
|
||||
self.messages = []; self.errorMsg=''; self.tab='chat';
|
||||
self.messages = []; self.errorMsg=''; self.notice=''; self.tab='chat';
|
||||
self.contextChips = []; self.mentionOpen = false;
|
||||
self.$nextTick(function(){ self.resizeInput(); });
|
||||
}).catch(function(){});
|
||||
@@ -773,7 +775,7 @@
|
||||
}).then(function(r){return r.json()}).then(function(d){
|
||||
var conv = {id:d.id, title:d.title, updated_at:new Date().toISOString()};
|
||||
self.conversations.unshift(conv); self.currentConv = conv;
|
||||
self.messages = []; self.errorMsg=''; self.tab='chat';
|
||||
self.messages = []; self.errorMsg=''; self.notice=''; self.tab='chat';
|
||||
self.contextChips = []; self.mentionOpen = false;
|
||||
self._ensuring = null;
|
||||
return conv;
|
||||
@@ -1682,6 +1684,7 @@
|
||||
self.messages.push({id:'f-'+Date.now(), role:'assistant', content: ev.content});
|
||||
if(window.__fdInsertAI){ try{ var h=window.__fdInsertAI; window.__fdInsertAI=null; h(ev.content||''); }catch(e){} }
|
||||
}
|
||||
else if(ev.type==='notice'){ self.notice = ev.message; }
|
||||
else if(ev.type==='error'){ self.errorMsg = ev.message; }
|
||||
}catch(e){}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user