From 54411a9a96d54c6a4aea51110fa61c93709eaa97 Mon Sep 17 00:00:00 2001 From: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Date: Tue, 27 Oct 2026 14:27:53 -0700 Subject: [PATCH] fix(chat): open chat name settings from naming failures (#34533) * fix(chat): link naming failures to chat name settings * fix(chat): hide naming settings link when controls are unavailable --- .../NativeChatNamingFailure.fixture.tsx | 21 +++++++++++ .../tab-bar/NativeChatNamingFailure.test.tsx | 35 +++++++++++++++++-- .../tab-bar/NativeChatNamingFailure.tsx | 21 +++++++++-- src/renderer/src/i18n/locales/en.json | 1 + 4 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 src/renderer/src/components/tab-bar/NativeChatNamingFailure.fixture.tsx diff --git a/src/renderer/src/components/tab-bar/NativeChatNamingFailure.fixture.tsx b/src/renderer/src/components/tab-bar/NativeChatNamingFailure.fixture.tsx new file mode 100644 index 00000000000..9a4533ea577 --- /dev/null +++ b/src/renderer/src/components/tab-bar/NativeChatNamingFailure.fixture.tsx @@ -0,0 +1,21 @@ +import { defineFixture } from '../../component-fixtures/component-fixture' +import { NativeChatNamingErrorBlock } from './NativeChatNamingFailure' + +export const failed = defineFixture({ + width: 288, + render: () => ( +
+ {}, + dialogOpen: false, + setDialogOpen: () => {}, + readFullOutput: async () => null + }} + /> +
+ ) +}) diff --git a/src/renderer/src/components/tab-bar/NativeChatNamingFailure.test.tsx b/src/renderer/src/components/tab-bar/NativeChatNamingFailure.test.tsx index 7c50bd4d2d4..ffdd413048a 100644 --- a/src/renderer/src/components/tab-bar/NativeChatNamingFailure.test.tsx +++ b/src/renderer/src/components/tab-bar/NativeChatNamingFailure.test.tsx @@ -10,9 +10,20 @@ import { useNativeChatNamingFailure } from './use-native-chat-naming-failure' const client = vi.hoisted(() => ({ supported: false, + web: false, emit: (_event: AgentSessionStatusEvent) => {}, regenerate: vi.fn<() => Promise>() })) +const settings = vi.hoisted(() => ({ + openSettingsPage: vi.fn(), + openSettingsTarget: vi.fn() +})) +vi.mock('@/store', () => ({ + useAppStore: { getState: () => settings } +})) +vi.mock('@/lib/web-client-location', () => ({ + isWebClientLocation: () => client.web +})) vi.mock('@/runtime/structured-agent-session-client', () => ({ subscribeStructuredAgentSessionStatus: async (_target: unknown, emit: typeof client.emit) => { client.emit = emit @@ -60,6 +71,7 @@ async function hoverChatTab(): Promise { describe('chat tab naming failure', () => { beforeEach(() => { vi.useFakeTimers() + vi.clearAllMocks() client.regenerate.mockResolvedValue(true) }) afterEach(() => { @@ -68,13 +80,30 @@ describe('chat tab naming failure', () => { vi.useRealTimers() }) - it.each([true, false])( - 'shows the error, with Regenerate name when the host has it: %s', - async (supported) => { + it.each([ + { supported: true, web: false }, + { supported: false, web: false }, + { supported: true, web: true }, + { supported: false, web: true } + ])( + 'shows recovery actions for host regeneration support=$supported, web=$web', + async ({ supported, web }) => { client.supported = supported + client.web = web await hoverChatTab() expect(screen.getAllByText("Couldn't name this chat").length).toBeGreaterThan(0) expect(screen.getAllByRole('button', { name: 'view error' }).length).toBeGreaterThan(0) + const settingsButtons = screen.queryAllByRole('button', { name: 'Settings' }) + expect(settingsButtons.length > 0).toBe(!web) + if (!web) { + fireEvent.click(settingsButtons[0]) + expect(settings.openSettingsPage).toHaveBeenCalledOnce() + expect(settings.openSettingsTarget).toHaveBeenCalledExactlyOnceWith({ + pane: 'chat', + repoId: null, + sectionId: 'chat-names' + }) + } const regenerate = screen.queryAllByRole('button', { name: 'Regenerate name' }) expect(regenerate.length > 0).toBe(supported) if (supported) { diff --git a/src/renderer/src/components/tab-bar/NativeChatNamingFailure.tsx b/src/renderer/src/components/tab-bar/NativeChatNamingFailure.tsx index aa17f2d81cd..a998b910e30 100644 --- a/src/renderer/src/components/tab-bar/NativeChatNamingFailure.tsx +++ b/src/renderer/src/components/tab-bar/NativeChatNamingFailure.tsx @@ -1,5 +1,7 @@ -import { AlertCircle, RefreshCw } from 'lucide-react' +import { AlertCircle, RefreshCw, Settings } from 'lucide-react' import { Button } from '@/components/ui/button' +import { useAppStore } from '@/store' +import { isWebClientLocation } from '@/lib/web-client-location' import { NameGenerationFailedDialog } from '../sidebar/AutoRenameFailedDialog' import { translate } from '@/i18n/i18n' import type { NativeChatNamingFailureControls } from './use-native-chat-naming-failure' @@ -27,7 +29,7 @@ export function NativeChatNamingErrorBlock({ 'The chat-name agent stopped with an error, so the chat keeps its first message as its name.' )}

-
+
+ )}
) diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json index ec12d851838..649e8b9c30c 100644 --- a/src/renderer/src/i18n/locales/en.json +++ b/src/renderer/src/i18n/locales/en.json @@ -21457,6 +21457,7 @@ "title": "Couldn't name this chat", "description": "The chat-name agent stopped with an error, so the chat keeps its first message as its name.", "viewError": "view error", + "settings": "Settings", "dialogTitle": "Chat auto-name failed", "dialogDescriptionStart": "Orca couldn't generate a name for", "dialogDescriptionEnd": "from its first message."