feat: display model name badge in header for active session

Shows the model (e.g. claude-opus-4-6) as a subtle chip next to the
session label in the header. Hovering reveals agent ID if available.
Model and agentId are now extracted from sessions.list response.
This commit is contained in:
Nicolas Varrot
2026-02-12 12:06:12 +00:00
parent 4312a71bc9
commit 96f28836cd
4 changed files with 27 additions and 2 deletions

View File

@@ -195,3 +195,16 @@
- Webchat → icône chat/bulle - Webchat → icône chat/bulle
- Fallback générique pour les channels non-vanilla (ex: TeamSpeak) → icône par défaut (bulle ou globe) - Fallback générique pour les channels non-vanilla (ex: TeamSpeak) → icône par défaut (bulle ou globe)
- Utiliser des SVG ou une lib d'icônes (lucide-react, react-icons, etc.) - Utiliser des SVG ou une lib d'icônes (lucide-react, react-icons, etc.)
## Item #24
- **Date:** 2026-02-12
- **Priority:** medium
- **Status:** pending
- **Description:** Display agent and model info in the UI
- **Details:**
- Show the OpenClaw agent ID (e.g. "main") and the model being used (e.g. "claude-opus-4-6") somewhere in the UI
- Investigate what data `sessions.list` and the connect response return — look for `agentId`, `model`, `defaultModel` or similar fields
- Good placement options: in the header bar near the session name, or in a small info tooltip/popover
- If the gateway doesn't expose this info via WebSocket, check if there's another endpoint or if it can be inferred from the session key
- Keep it subtle/non-intrusive — small text or an info icon that reveals details on hover
- This helps users know which agent/model is handling their conversation

View File

@@ -1,4 +1,4 @@
import { Menu, Sparkles, LogOut, Volume2, VolumeOff } from 'lucide-react'; import { Menu, Sparkles, LogOut, Volume2, VolumeOff, Cpu } from 'lucide-react';
import type { ConnectionStatus, Session } from '../types'; import type { ConnectionStatus, Session } from '../types';
import { useT } from '../hooks/useLocale'; import { useT } from '../hooks/useLocale';
import { LanguageSelector } from './LanguageSelector'; import { LanguageSelector } from './LanguageSelector';
@@ -30,7 +30,15 @@ export function Header({ status, sessionKey, onToggleSidebar, activeSessionData,
<span className="font-semibold text-zinc-300 text-sm tracking-wide">{t('header.title')}</span> <span className="font-semibold text-zinc-300 text-sm tracking-wide">{t('header.title')}</span>
<Sparkles className="h-3.5 w-3.5 text-cyan-300/60" /> <Sparkles className="h-3.5 w-3.5 text-cyan-300/60" />
</div> </div>
<span className="text-xs text-zinc-500 truncate block">{sessionLabel}</span> <div className="flex items-center gap-2 min-w-0">
<span className="text-xs text-zinc-500 truncate">{sessionLabel}</span>
{activeSessionData?.model && (
<span className="inline-flex items-center gap-1 text-[10px] text-zinc-500 bg-white/5 rounded-full px-2 py-0.5 shrink-0" title={`Model: ${activeSessionData.model}${activeSessionData.agentId ? ` · Agent: ${activeSessionData.agentId}` : ''}`}>
<Cpu className="h-2.5 w-2.5" />
<span className="truncate max-w-[120px]">{activeSessionData.model.replace(/^.*\//, '')}</span>
</span>
)}
</div>
</div> </div>
</div> </div>
<div className="flex items-center gap-2 text-sm"> <div className="flex items-center gap-2 text-sm">

View File

@@ -94,6 +94,8 @@ export function useGateway() {
outputTokens: s.outputTokens as number | undefined, outputTokens: s.outputTokens as number | undefined,
channel: (s.lastChannel || s.channel) as string | undefined, channel: (s.lastChannel || s.channel) as string | undefined,
kind: s.kind as string | undefined, kind: s.kind as string | undefined,
model: s.model as string | undefined,
agentId: s.agentId as string | undefined,
}))); })));
} }
} catch { } catch {

View File

@@ -27,6 +27,8 @@ export interface Session {
outputTokens?: number; outputTokens?: number;
channel?: string; channel?: string;
kind?: string; kind?: string;
model?: string;
agentId?: string;
} }
export type ConnectionStatus = 'disconnected' | 'connecting' | 'connected'; export type ConnectionStatus = 'disconnected' | 'connecting' | 'connected';