From fd28b89b000072e113be90c831135392d75e270c Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Sun, 9 Aug 2026 17:35:54 -0700
Subject: [PATCH] fix(dashboard): preserve inspector input and state
---
.../dashboard-popout/AgentChatPanel.test.tsx | 26 +++++++++++++++++++
.../dashboard-popout/AgentChatPanel.tsx | 10 ++++---
.../dashboard-popout/AgentKanbanCard.test.tsx | 13 ++++++++++
.../dashboard-popout/AgentKanbanCard.tsx | 1 +
src/shared/dashboard-snapshot.ts | 2 +-
5 files changed, 48 insertions(+), 4 deletions(-)
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