fix(client): suppress run/stop button flicker during CLI restart transitions
ModelSelector and PermissionMode changes trigger a server-side CLI
restart (handler.ts:521 restartSessionWithRuntimeConfig). The server
emits status:'thinking' with verb 'Switching provider and model...' or
'Restarting session...' to keep the spinner spinning during the ~3s
restart window. ChatInput's isActive=`chatState !== 'idle' && hasMessages`
guard let the run button flash to a red 「stop」 affordance during that
window for any session with prior messages — confusing because hitting
stop has nothing to interrupt.
Add a statusVerb prefix check so isActive stays false during these
system transitions:
isSystemRestartTransition =
statusVerb.startsWith('Switching provider and model') ||
statusVerb.startsWith('Restarting session')
isActive = chatState !== 'idle' && hasMessages && !isSystemRestartTransition
Match by prefix so any future suffix (e.g. " (CLI starting...)") still
trips the guard.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -61,6 +61,7 @@ export function ChatInput({ variant = 'default' }: ChatInputProps) {
|
||||
const activeTabId = useTabStore((s) => s.activeTabId)
|
||||
const sessionState = useChatStore((s) => activeTabId ? s.sessions[activeTabId] : undefined)
|
||||
const chatState = sessionState?.chatState ?? 'idle'
|
||||
const statusVerb = sessionState?.statusVerb ?? ''
|
||||
const slashCommands = sessionState?.slashCommands ?? []
|
||||
const composerPrefill = sessionState?.composerPrefill ?? null
|
||||
const activeSession = useSessionStore((state) => activeTabId ? state.sessions.find((session) => session.id === activeTabId) ?? null : null)
|
||||
@@ -69,12 +70,19 @@ export function ChatInput({ variant = 'default' }: ChatInputProps) {
|
||||
const hasMessages = useChatStore((s) => activeTabId ? (s.sessions[activeTabId]?.messages?.length ?? 0) > 0 : false)
|
||||
|
||||
const isMemberSession = !!memberInfo
|
||||
// Bug fix: ModelSelector / runtime config changes briefly flip
|
||||
// chatState off-idle (CLI reconnect / startup), which used to make the
|
||||
// run button render as a red 「stop」 even on an empty session. Gate by
|
||||
// hasMessages so 「stop」 only appears once we actually have something
|
||||
// running for the user to stop.
|
||||
const isActive = chatState !== 'idle' && hasMessages
|
||||
// Bug fix: ModelSelector / permission-mode changes trigger a server-side
|
||||
// CLI restart that briefly flips chatState off-idle with one of the
|
||||
// verbs below. There is no inference to stop during that window — the
|
||||
// user just has to wait a couple seconds — so don't render the red
|
||||
// 「stop」 button regardless of hasMessages. Match the verbs as
|
||||
// prefixes since server may append context (e.g. " (CLI starting...)").
|
||||
const isSystemRestartTransition =
|
||||
statusVerb.startsWith('Switching provider and model') ||
|
||||
statusVerb.startsWith('Restarting session')
|
||||
// Also: empty sessions can't be active for the user, even if chatState
|
||||
// briefly flips during initial CLI startup.
|
||||
const isActive =
|
||||
chatState !== 'idle' && hasMessages && !isSystemRestartTransition
|
||||
const isWorkspaceMissing = activeSession?.workDirExists === false
|
||||
const canSubmit = !isWorkspaceMissing && (input.trim().length > 0 || (!isMemberSession && attachments.length > 0))
|
||||
const isHeroComposer = variant === 'hero' && !isMemberSession
|
||||
|
||||
Reference in New Issue
Block a user