diff --git a/ui/src/styles/components.css b/ui/src/styles/components.css index 27dfe62d1..9a93cbaae 100644 --- a/ui/src/styles/components.css +++ b/ui/src/styles/components.css @@ -1484,3 +1484,23 @@ flex-wrap: wrap; gap: 8px; } + +/* Chat controls label input */ +.chat-controls__label { + width: 120px; + padding: 4px 8px; + font-size: 13px; + border: 1px solid var(--border); + border-radius: 4px; + background: var(--surface); + color: var(--text); +} + +.chat-controls__label:focus { + outline: none; + border-color: var(--primary); +} + +.chat-controls__label::placeholder { + color: var(--muted); +} diff --git a/ui/src/ui/app-render.helpers.ts b/ui/src/ui/app-render.helpers.ts index c2190e1c9..d2b2d3e5e 100644 --- a/ui/src/ui/app-render.helpers.ts +++ b/ui/src/ui/app-render.helpers.ts @@ -6,6 +6,7 @@ import { iconForTab, pathForTab, titleForTab, type Tab } from "./navigation"; import { icons } from "./icons"; import { loadChatHistory } from "./controllers/chat"; import { refreshChat } from "./app-chat"; +import { patchSession } from "./controllers/sessions"; import { syncUrlWithSessionKey } from "./app-settings"; import type { SessionsListResult } from "./types"; import type { ThemeMode } from "./theme"; @@ -46,6 +47,10 @@ export function renderChatControls(state: AppViewState) { state.sessionsResult, mainSessionKey, ); + const activeSession = state.sessionsResult?.sessions?.find( + (row) => row.key === state.sessionKey, + ); + const sessionLabel = activeSession?.label ?? ""; const disableThinkingToggle = state.onboarding; const disableFocusToggle = state.onboarding; const showThinking = state.onboarding ? false : state.settings.chatShowThinking; @@ -81,13 +86,32 @@ export function renderChatControls(state: AppViewState) { ${repeat( sessionOptions, (entry) => entry.key, - (entry) => - html``, + (entry) => { + const base = entry.displayName ?? entry.key; + // Only append label if it differs from displayName + const showLabel = entry.label && entry.label !== entry.displayName; + const text = showLabel ? `${base} — ${entry.label}` : base; + return html``; + }, )} + { + const value = (e.target as HTMLInputElement).value.trim(); + void patchSession( + state as Parameters[0], + state.sessionKey, + { label: value || null }, + ); + }} + />