diff --git a/src/renderer/src/components/dashboard-popout/AgentChatPanel.test.tsx b/src/renderer/src/components/dashboard-popout/AgentChatPanel.test.tsx index 65bff4f6a1f..5f009fdb693 100644 --- a/src/renderer/src/components/dashboard-popout/AgentChatPanel.test.tsx +++ b/src/renderer/src/components/dashboard-popout/AgentChatPanel.test.tsx @@ -149,6 +149,32 @@ describe('AgentChatPanel', () => { expect(screen.getByLabelText('Reply to this agent')).toHaveValue('hello') }) + it.each([ + ['an active composition', { isComposing: true }], + ['the legacy IME key code', { keyCode: 229 }] + ])('does not submit the Enter that confirms %s', (_label, keyboardInit) => { + render() + + const input = screen.getByLabelText('Reply to this agent') + fireEvent.change(input, { target: { value: 'unfinished conversion' } }) + fireEvent.keyDown(input, { key: 'Enter', ...keyboardInit }) + + expect(terminalInput).not.toHaveBeenCalled() + expect(input).toHaveValue('unfinished conversion') + }) + + it('shows acknowledged completions with the dashboard idle state', () => { + render( + + ) + + expect(screen.getByLabelText('Idle')).toBeInTheDocument() + expect(screen.queryByLabelText('Done')).not.toBeInTheDocument() + }) + it('withholds the composer when the agent has no live pane', () => { render() diff --git a/src/renderer/src/components/dashboard-popout/AgentChatPanel.tsx b/src/renderer/src/components/dashboard-popout/AgentChatPanel.tsx index db99ff1e7ea..23b11a4b924 100644 --- a/src/renderer/src/components/dashboard-popout/AgentChatPanel.tsx +++ b/src/renderer/src/components/dashboard-popout/AgentChatPanel.tsx @@ -15,8 +15,12 @@ import { selectNativeChatViewState } from '@/components/native-chat/native-chat- import { NATIVE_CHAT_SUBMIT_DELAY_MS } from '../../../../shared/native-chat-answer-stepping' import { translate } from '@/i18n/i18n' import { formatAgentTypeLabel } from '@/lib/agent-status' +import { isImeCompositionKeyDown } from '@/lib/ime-composition-keyboard-event' import { cn } from '@/lib/utils' -import type { DashboardCard } from '../../../../shared/dashboard-snapshot' +import { + dashboardCardDisplayState, + type DashboardCard +} from '../../../../shared/dashboard-snapshot' import { resolveAgentChatPanelMode, type AgentChatPanelMode } from './agent-chat-panel-mode' type AgentChatPanelProps = { @@ -183,7 +187,7 @@ function AgentChatComposer({ card }: { card: DashboardCard }): React.JSX.Element setFailedSend(null) }} onKeyDown={(event) => { - if (event.key === 'Enter' && !event.shiftKey) { + if (event.key === 'Enter' && !event.shiftKey && !isImeCompositionKeyDown(event)) { event.preventDefault() void send() } @@ -260,7 +264,7 @@ export function AgentChatPanel({ )} >
- +

{agentName(card)} diff --git a/src/renderer/src/components/dashboard-popout/AgentKanbanCard.test.tsx b/src/renderer/src/components/dashboard-popout/AgentKanbanCard.test.tsx index f4bf79c8ef3..b95b47020c7 100644 --- a/src/renderer/src/components/dashboard-popout/AgentKanbanCard.test.tsx +++ b/src/renderer/src/components/dashboard-popout/AgentKanbanCard.test.tsx @@ -337,6 +337,19 @@ describe('AgentKanbanCard', () => { fireEvent.click(screen.getByText('Review the change')) expect(onOpenTerminal).toHaveBeenLastCalledWith(windowsCard) + + const ctrlEnterCard = { + ...windowsCard, + terminalInput: { ...windowsCard.terminalInput, ctrlEnterCsiU: true } + } + rerender( + + + + ) + + fireEvent.click(screen.getByText('Review the change')) + expect(onOpenTerminal).toHaveBeenLastCalledWith(ctrlEnterCard) }) it('updates the relative age when the UI language changes', async () => { diff --git a/src/renderer/src/components/dashboard-popout/AgentKanbanCard.tsx b/src/renderer/src/components/dashboard-popout/AgentKanbanCard.tsx index b949925e3fb..047f48c076c 100644 --- a/src/renderer/src/components/dashboard-popout/AgentKanbanCard.tsx +++ b/src/renderer/src/components/dashboard-popout/AgentKanbanCard.tsx @@ -91,6 +91,7 @@ function sameTerminalInput( a.localWindowsConpty === b.localWindowsConpty && a.osRelease === b.osRelease && a.windowsShiftEnterEncoding === b.windowsShiftEnterEncoding && + a.ctrlEnterCsiU === b.ctrlEnterCsiU && a.kittyKeyboardAdvertised === b.kittyKeyboardAdvertised) ) } diff --git a/src/shared/dashboard-snapshot.ts b/src/shared/dashboard-snapshot.ts index f786e6bb404..c0f45f4b7e5 100644 --- a/src/shared/dashboard-snapshot.ts +++ b/src/shared/dashboard-snapshot.ts @@ -104,7 +104,7 @@ export type DashboardCard = { /** Optional for preload compatibility with snapshots produced before Agent Map. * Also keeps the inspector from reading remote transcript paths locally. */ hostKind?: DashboardCardHostKind - /** Effective renderer mode for this agent's terminal tab. */ + /** Initial dashboard inspector mode derived from the user's Chat UI default. */ viewMode?: DashboardCardViewMode /** Exact owner used by in-window workspace actions when IDs collide across hosts. */ executionHostId?: ExecutionHostId