diff --git a/cortex/routers/chat.py b/cortex/routers/chat.py index 14cc3fb..6977db8 100644 --- a/cortex/routers/chat.py +++ b/cortex/routers/chat.py @@ -18,6 +18,20 @@ import event_bus router = APIRouter() +def _backend_label(backend: str, username: str) -> str: + """Human-readable label for the model that handled a request.""" + if backend == "claude": + return "Claude" + if backend == "gemini": + return "Gemini" + if backend == "local": + cfg = model_registry.get_best_local_model(username) + if cfg: + return cfg.get("label") or cfg.get("model_name") or "Local" + return "Local" + return backend.title() + + class ChatRequest(BaseModel): message: str session_id: str | None = None @@ -105,6 +119,7 @@ async def _stream_chat(req: ChatRequest): "response": response_text, "session_id": session_id, "backend": actual_backend, + "backend_label": _backend_label(actual_backend, user), "fallback_used": actual_backend != requested, } yield f"data: {json.dumps(payload)}\n\n" diff --git a/cortex/static/app.js b/cortex/static/app.js index 920585e..9960580 100644 --- a/cortex/static/app.js +++ b/cortex/static/app.js @@ -949,6 +949,7 @@ include_mid: memMid, include_short: memShort, off_record: current_mode === 'otr', + model: primaryBackend, user: CORTEX_USER, persona: CORTEX_PERSONA, }), @@ -984,10 +985,15 @@ const assistHistIdx = currentHistory.length; currentHistory.push({ role: 'assistant', content: data.response }); attachHistoryControls(thinkingDiv, assistHistIdx); - if (data.fallback_used) { - addMessage('system', - `⚡ ${primaryBackend} unavailable — answered by ${data.backend}`); - } + + // Model tag — always shown, amber if fallback was used + const modelTag = document.createElement('div'); + modelTag.className = 'model-tag' + (data.fallback_used ? ' fallback' : ''); + const label = data.backend_label || data.backend || ''; + modelTag.textContent = data.fallback_used + ? `⚡ fallback → ${label}` + : label; + thinkingDiv.appendChild(modelTag); } else if (data.type === 'error') { throw new Error(data.message); } diff --git a/cortex/static/style.css b/cortex/static/style.css index 6fdbc1b..d6c13cb 100644 --- a/cortex/static/style.css +++ b/cortex/static/style.css @@ -552,6 +552,20 @@ .copy-btn:hover { color: var(--text); border-color: var(--muted); } .copy-btn.copied { color: var(--success); border-color: var(--success-dim); } + /* Model tag — shown at the bottom of every assistant message */ + .model-tag { + display: block; + font-size: 0.67rem; + color: #334155; + margin-top: 0.55rem; + padding-top: 0.4rem; + border-top: 1px solid #1e2030; + text-align: right; + letter-spacing: 0.02em; + font-weight: 500; + } + .model-tag.fallback { color: #f59e0b; } + /* Note messages */ .message.note-private { align-self: flex-end;