From 80b3d8c272bceed0cabf2c44c564904787320dd3 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sat, 7 Feb 2026 15:07:59 +0000 Subject: [PATCH] feat: show active model ID in API config selector bottom bar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Display the model ID alongside the config name in the ApiConfigSelector trigger button (e.g. "default · claude-sonnet-4-20250514") so users can immediately see which model is active for the current mode without clicking anything. Also enhances the tooltip to show provider info when the trigger text is truncated. Closes #11290 --- .../src/components/chat/ChatTextArea.tsx | 11 +++++-- .../chat/__tests__/ChatTextArea.spec.tsx | 33 +++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/webview-ui/src/components/chat/ChatTextArea.tsx b/webview-ui/src/components/chat/ChatTextArea.tsx index 654f2e1011e..c2e9bd92cab 100644 --- a/webview-ui/src/components/chat/ChatTextArea.tsx +++ b/webview-ui/src/components/chat/ChatTextArea.tsx @@ -106,11 +106,16 @@ export const ChatTextArea = forwardRef( } = useExtensionState() // Find the ID and display text for the currently selected API configuration. - const { currentConfigId, displayName } = useMemo(() => { + const { currentConfigId, displayName, tooltipContent } = useMemo(() => { const currentConfig = listApiConfigMeta?.find((config) => config.name === currentApiConfigName) + const configName = currentApiConfigName || "" + const modelId = currentConfig?.modelId return { currentConfigId: currentConfig?.id || "", - displayName: currentApiConfigName || "", // Use the name directly for display. + displayName: modelId ? `${configName} · ${modelId}` : configName, + tooltipContent: modelId + ? `${configName}${currentConfig?.apiProvider ? ` (${currentConfig.apiProvider})` : ""} · ${modelId}` + : configName, } }, [listApiConfigMeta, currentApiConfigName]) @@ -1310,7 +1315,7 @@ export const ChatTextArea = forwardRef( value={currentConfigId} displayName={displayName} disabled={selectApiConfigDisabled} - title={t("chat:selectApiConfig")} + title={tooltipContent || t("chat:selectApiConfig")} onChange={handleApiConfigChange} triggerClassName="min-w-[28px] text-ellipsis overflow-hidden flex-shrink" listApiConfigMeta={listApiConfigMeta || []} diff --git a/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx index 0b63a68f4ec..8e2128a6940 100644 --- a/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx @@ -1057,6 +1057,39 @@ describe("ChatTextArea", () => { expect(apiConfigDropdown).toHaveAttribute("disabled") }) + it("should display model ID alongside config name when modelId is available", () => { + ;(useExtensionState as ReturnType).mockReturnValue({ + filePaths: [], + openedTabs: [], + taskHistory: [], + cwd: "/test/workspace", + currentApiConfigName: "my-config", + listApiConfigMeta: [ + { id: "cfg1", name: "my-config", apiProvider: "anthropic", modelId: "claude-sonnet-4-20250514" }, + ], + }) + + render() + const apiConfigDropdown = getApiConfigDropdown() + expect(apiConfigDropdown).toHaveTextContent("my-config · claude-sonnet-4-20250514") + }) + + it("should display only config name when modelId is not available", () => { + ;(useExtensionState as ReturnType).mockReturnValue({ + filePaths: [], + openedTabs: [], + taskHistory: [], + cwd: "/test/workspace", + currentApiConfigName: "my-config", + listApiConfigMeta: [{ id: "cfg1", name: "my-config" }], + }) + + render() + const apiConfigDropdown = getApiConfigDropdown() + expect(apiConfigDropdown).toHaveTextContent("my-config") + expect(apiConfigDropdown).not.toHaveTextContent("·") + }) + describe("enter key behavior", () => { it("should send on Enter and allow newline on Shift+Enter in default mode", () => { const onSend = vi.fn()