fix: show configured badge on selected model chip

This commit is contained in:
renatomott
2026-04-29 21:38:41 -03:00
committed by Hermes Agent
parent 2169759c50
commit 38c5fd86bf
4 changed files with 43 additions and 3 deletions
+1
View File
@@ -401,6 +401,7 @@
<button class="composer-model-chip" id="composerModelChip" type="button" onclick="toggleModelDropdown()" title="Conversation model">
<span class="composer-model-icon" aria-hidden="true"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/><path d="M15 2v2"/><path d="M15 20v2"/><path d="M2 15h2"/><path d="M2 9h2"/><path d="M20 15h2"/><path d="M20 9h2"/><path d="M9 2v2"/><path d="M9 20v2"/></svg></span>
<span class="composer-model-label" id="composerModelLabel"></span>
<span class="composer-model-badge" id="composerModelBadge" hidden></span>
<span class="composer-model-chevron" aria-hidden="true"><svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></span>
</button>
<select id="modelSelect" class="composer-model-select" title="Conversation model" aria-hidden="true" tabindex="-1">
+5 -1
View File
@@ -838,10 +838,14 @@
.reasoning-option:hover{background:rgba(255,255,255,.07);}
.reasoning-option.selected{background:var(--accent-bg);}
.composer-model-wrap{position:relative;flex:0 1 auto;min-width:0;}
.composer-model-chip{display:inline-flex;align-items:center;gap:8px;max-width:220px;padding:8px 10px 8px 12px;border-radius:999px;border:1px solid transparent;background-color:transparent;color:var(--muted);font-weight:500;cursor:pointer;transition:color .15s,background-color .15s,border-color .15s;}
.composer-model-chip{display:inline-flex;align-items:center;gap:8px;max-width:280px;padding:8px 10px 8px 12px;border-radius:999px;border:1px solid transparent;background-color:transparent;color:var(--muted);font-weight:500;cursor:pointer;transition:color .15s,background-color .15s,border-color .15s;}
.composer-model-chip:hover{color:var(--text);background-color:var(--hover-bg);}
.composer-model-chip.active{color:var(--text);background:var(--accent-bg);border-color:var(--accent-bg);}
.composer-model-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.composer-model-badge{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;padding:2px 7px;border-radius:999px;font-size:10px;font-weight:700;letter-spacing:.02em;text-transform:uppercase;border:1px solid transparent;}
.composer-model-badge[hidden]{display:none;}
.composer-model-badge--primary{background:rgba(50,184,198,.16);border-color:rgba(50,184,198,.32);color:#8fe7ef;}
.composer-model-badge--fallback{background:rgba(255,184,77,.14);border-color:rgba(255,184,77,.28);color:#ffd18a;}
.composer-model-icon,.composer-model-chevron{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;line-height:1;}
.composer-model-select{position:absolute!important;left:-9999px!important;width:1px!important;height:1px!important;opacity:0!important;pointer-events:none!important;}
.composer-right{display:flex;gap:8px;align-items:center;flex-shrink:0;}
+17 -1
View File
@@ -337,12 +337,28 @@ function syncModelChip(){
const sel=$('modelSelect');
const chip=$('composerModelChip');
const label=$('composerModelLabel');
const badgeEl=$('composerModelBadge');
const dd=$('composerModelDropdown');
if(!sel||!chip||!label) return;
// Don't show a model label until boot has finished loading to prevent flash of wrong default
if(!S._bootReady){ label.textContent=''; chip.title='Conversation model'; return; }
if(!S._bootReady){
label.textContent='';
chip.title='Conversation model';
if(badgeEl){
badgeEl.textContent='';
badgeEl.hidden=true;
badgeEl.className='composer-model-badge';
}
return;
}
const opt=_selectedModelOption();
label.textContent=opt?opt.textContent:getModelLabel(sel.value||'');
const badge=_getConfiguredModelBadge(sel.value||'',window._configuredModelBadges||{});
if(badgeEl){
badgeEl.textContent=badge&&badge.label?badge.label:'';
badgeEl.hidden=!badgeEl.textContent;
badgeEl.className='composer-model-badge'+(badge&&badge.role?` composer-model-badge--${badge.role}`:'');
}
chip.title=sel.value||'Conversation model';
chip.classList.toggle('active',!!(dd&&dd.classList.contains('open')));
}
+20 -1
View File
@@ -89,7 +89,11 @@ def test_get_available_models_cache_preserves_configured_model_badges(tmp_path,
def test_ui_renders_model_badges_from_api_payload():
js = (Path(__file__).resolve().parent.parent / "static" / "ui.js").read_text(encoding="utf-8")
root = Path(__file__).resolve().parent.parent
js = (root / "static" / "ui.js").read_text(encoding="utf-8")
html = (root / "static" / "index.html").read_text(encoding="utf-8")
css = (root / "static" / "style.css").read_text(encoding="utf-8")
assert "window._configuredModelBadges=data.configured_model_badges||{};" in js, (
"populateModelDropdown() deve guardar configured_model_badges do /api/models "
"para que o dropdown reflita a cadeia configurada atual."
@@ -102,3 +106,18 @@ def test_ui_renders_model_badges_from_api_payload():
"A UI precisa de um helper de matching resiliente para religar badges mesmo quando "
"o update do catálogo mudar prefixos/formas do model ID."
)
assert 'id="composerModelBadge"' in html, (
"O chip principal do modelo precisa de um container dedicado para exibir o badge "
"do modelo selecionado fora do dropdown."
)
assert "composer-model-badge" in css, (
"O badge do chip principal precisa de estilo próprio para ficar visível ao lado "
"do nome do modelo selecionado."
)
assert "const badge=_getConfiguredModelBadge(sel.value||'',window._configuredModelBadges||{});" in js, (
"syncModelChip() deve buscar o badge configurado do modelo selecionado e projetá-lo "
"no chip principal da composer."
)
assert "badgeEl.textContent=badge&&badge.label?badge.label:'';" in js, (
"syncModelChip() deve preencher o texto do badge visível no chip principal quando houver metadata configurada."
)