diff --git a/packages/ui/src/components/chat/ChatInput.tsx b/packages/ui/src/components/chat/ChatInput.tsx index 8d375160..1c5a40f1 100644 --- a/packages/ui/src/components/chat/ChatInput.tsx +++ b/packages/ui/src/components/chat/ChatInput.tsx @@ -419,7 +419,6 @@ const ChatInputComponent: React.FC = ({ const ensureGitStatus = useGitStore((state) => state.ensureStatus); const fetchGitStatus = useGitStore((state) => state.fetchStatus); const clearGitDiffCache = useGitStore((state) => state.clearDiffCache); - const [showAbortStatus, setShowAbortStatus] = React.useState(false); const setSessionAutoAccept = usePermissionStore((state) => state.setSessionAutoAccept); const [isNarrowComposer, setIsNarrowComposer] = React.useState(false); const [attachmentPreview, setAttachmentPreview] = React.useState({ @@ -697,7 +696,6 @@ const ChatInputComponent: React.FC = ({ attachments, }; }, [resolveInlineFileMention]); - const abortTimeoutRef = React.useRef | null>(null); const prevWasAbortedRef = React.useRef(false); // Issue linking state @@ -1721,29 +1719,15 @@ const ChatInputComponent: React.FC = ({ containerRef: dropZoneRef, }); - const startAbortIndicator = React.useCallback(() => { - if (abortTimeoutRef.current) { - clearTimeout(abortTimeoutRef.current); - abortTimeoutRef.current = null; - } - - setShowAbortStatus(true); - - abortTimeoutRef.current = setTimeout(() => { - setShowAbortStatus(false); - abortTimeoutRef.current = null; - }, 1800); - }, []); const handleAbort = React.useCallback(() => { clearAbortPrompt(); - startAbortIndicator(); // btw mode: the stop button stops the fork's turn, not the main // session's. const abortTarget = isBtwActive && btwSessionId ? btwSessionId : currentSessionId; void abortCurrentOperation(abortTarget || undefined); - }, [abortCurrentOperation, btwSessionId, clearAbortPrompt, currentSessionId, isBtwActive, startAbortIndicator]); + }, [abortCurrentOperation, btwSessionId, clearAbortPrompt, currentSessionId, isBtwActive]); const handleCycleAgent = React.useCallback((direction: 1 | -1 = 1) => { const nextAgentName = getCycledPrimaryAgentName(agents, currentAgentName, direction); @@ -2592,31 +2576,15 @@ const ChatInputComponent: React.FC = ({ handlePermissionAutoAcceptToggle(); }); + // Acknowledging the abort record is what lets the working chip resume for + // the next run; the old "Aborted" banner that used to accompany it is gone. React.useEffect(() => { - const pendingAbortBanner = Boolean(abortPromptSessionId) && abortPromptSessionId === currentSessionId; - if (!prevWasAbortedRef.current && pendingAbortBanner && !showAbortStatus) { - startAbortIndicator(); - if (currentSessionId) { - acknowledgeSessionAbort(currentSessionId); - } + const pendingAbort = Boolean(abortPromptSessionId) && abortPromptSessionId === currentSessionId; + if (!prevWasAbortedRef.current && pendingAbort && currentSessionId) { + acknowledgeSessionAbort(currentSessionId); } - prevWasAbortedRef.current = pendingAbortBanner; - }, [ - abortPromptSessionId, - acknowledgeSessionAbort, - currentSessionId, - showAbortStatus, - startAbortIndicator, - ]); - - React.useEffect(() => { - return () => { - if (abortTimeoutRef.current) { - clearTimeout(abortTimeoutRef.current); - abortTimeoutRef.current = null; - } - }; - }, []); + prevWasAbortedRef.current = pendingAbort; + }, [abortPromptSessionId, acknowledgeSessionAbort, currentSessionId]); return ( <> @@ -2687,7 +2655,6 @@ const ChatInputComponent: React.FC = ({ directory={currentSessionDirectoryForSync ?? currentDirectory} /> = ({ todo }) => { const EMPTY_TODOS: TodoItem[] = []; interface ComposerStatusBarProps { - showAbortStatus?: boolean; showTodos?: boolean; leftAccessory?: React.ReactNode; } export const ComposerStatusBar: React.FC = ({ - showAbortStatus, showTodos = true, leftAccessory, }) => { @@ -186,7 +184,7 @@ export const ComposerStatusBar: React.FC = ({ const hasTodoContent = showTodos && statusSummary.left > 0; const hasLeftAccessory = Boolean(leftAccessory); - const hasContent = Boolean(showAbortStatus) || hasTodoContent || hasLeftAccessory; + const hasContent = hasTodoContent || hasLeftAccessory; const popoverRef = React.useRef(null); React.useEffect(() => { @@ -252,16 +250,7 @@ export const ComposerStatusBar: React.FC = ({
{/* Left: abort status | pending-changes accessory */}
- {showAbortStatus ? ( -
- - -
- ) : leftAccessory ? ( - leftAccessory - ) : null} + {leftAccessory ?? null}
{/* Right: todos dropdown */} diff --git a/packages/ui/src/components/chat/StatusRow.tsx b/packages/ui/src/components/chat/StatusRow.tsx index a577a3d2..0b1efbb9 100644 --- a/packages/ui/src/components/chat/StatusRow.tsx +++ b/packages/ui/src/components/chat/StatusRow.tsx @@ -1,11 +1,9 @@ import React from "react"; import { useSessionUIStore } from '@/sync/session-ui-store'; import { WorkingPlaceholder } from "./message/parts/WorkingPlaceholder"; -import { Icon } from "@/components/icon/Icon"; -import { useI18n } from "@/lib/i18n"; // The floating assistant-status chip that hovers above the composer while the -// agent works ("Claude is working…", abort notice). ONLY that. The composer's +// agent works ("Claude is working…"). ONLY that. The composer's // own bar — pending changes, todos dropdown — is ComposerStatusBar: they used // to share this component, and every restyle of this chip (glass, placement) // silently dragged the composer bar and its dropdown along with it. @@ -17,10 +15,8 @@ interface StatusRowProps { statusText?: string | null; isGenericStatus?: boolean; isWaitingForPermission?: boolean; - wasAborted?: boolean; abortActive?: boolean; retryInfo?: { attempt?: number; next?: number } | null; - showAbortStatus?: boolean; agentName?: string; modelName?: string | null; providerId?: string | null; @@ -31,19 +27,16 @@ export const StatusRow: React.FC = ({ statusText = null, isGenericStatus, isWaitingForPermission, - wasAborted, abortActive, retryInfo, - showAbortStatus, agentName, modelName, providerId, }) => { - const { t } = useI18n(); const currentSessionId = useSessionUIStore((state) => state.currentSessionId); - const shouldRenderPlaceholder = !showAbortStatus && (wasAborted || !abortActive); - const hasContent = isWorking || Boolean(wasAborted) || Boolean(showAbortStatus); + const shouldRenderPlaceholder = !abortActive; + const hasContent = isWorking; if (!hasContent) { return null; @@ -63,14 +56,7 @@ export const StatusRow: React.FC = ({ a shrink-to-fit wrapper around it always collapsed to zero. */}
- {showAbortStatus ? ( -
- - -
- ) : shouldRenderPlaceholder ? ( + {shouldRenderPlaceholder ? ( { - const currentSessionId = useSessionUIStore((state) => state.currentSessionId); - const abortRecord = useSessionUIStore( - React.useCallback((state) => { - if (!currentSessionId) { - return null; - } - return state.sessionAbortFlags?.get(currentSessionId) ?? null; - }, [currentSessionId]), - ); const { activeModel, working } = useAssistantStatus(); const currentAgentName = useConfigStore((state) => state.currentAgentName); const providers = useConfigStore((state) => state.providers); @@ -35,16 +25,13 @@ export const StatusRowContainer: React.FC = React.memo(() => { return getProviderModelDisplayName(provider, activeModel.modelId) || null; }, [activeModel, providers]); - const wasAborted = Boolean(abortRecord && !abortRecord.acknowledged); - return ( = { "chat.statusRow.tasksTitle": "Tareas", "chat.statusRow.modelStatus": "{model} · {status}", "chat.statusRow.summary.activeLeft": "{active} activas · {left} restantes", - "chat.statusRow.aborted": "Interrumpido", "chat.revertIndicator.redo": "Rehacer", "chat.revertIndicator.redoAria": "Rehacer — restaurar mensajes revertidos", "chat.revertPopover.title": "Revertidos", diff --git a/packages/ui/src/lib/i18n/messages/fr.ts b/packages/ui/src/lib/i18n/messages/fr.ts index 573aed79..147b644f 100644 --- a/packages/ui/src/lib/i18n/messages/fr.ts +++ b/packages/ui/src/lib/i18n/messages/fr.ts @@ -1826,7 +1826,6 @@ export const dict = { 'chat.statusRow.tasksTitle': 'Tâches', 'chat.statusRow.modelStatus': '{model} · {status}', 'chat.statusRow.summary.activeLeft': '{active} actif · {left} gauche', - 'chat.statusRow.aborted': 'Avorté', 'chat.revertIndicator.redo': 'Refaire', 'chat.revertIndicator.redoAria': 'Rétablir : restaurer les messages annulés', 'chat.revertPopover.title': 'Rétabli', diff --git a/packages/ui/src/lib/i18n/messages/ja.ts b/packages/ui/src/lib/i18n/messages/ja.ts index 2b474a39..9bc2aaee 100644 --- a/packages/ui/src/lib/i18n/messages/ja.ts +++ b/packages/ui/src/lib/i18n/messages/ja.ts @@ -2080,7 +2080,6 @@ export const dict: Record = { 'chat.statusRow.tasksTitle': 'タスク', 'chat.statusRow.modelStatus': '{model} · {status}', 'chat.statusRow.summary.activeLeft': '{active}アクティブ · {left}残り', - 'chat.statusRow.aborted': '中止されました', 'chat.revertIndicator.redo': 'やり直し', 'chat.revertIndicator.redoAria': 'やり直し — 元に戻したメッセージを復元', 'chat.revertPopover.title': '元に戻しました', diff --git a/packages/ui/src/lib/i18n/messages/ko.ts b/packages/ui/src/lib/i18n/messages/ko.ts index 439f8ba6..f89cd65f 100644 --- a/packages/ui/src/lib/i18n/messages/ko.ts +++ b/packages/ui/src/lib/i18n/messages/ko.ts @@ -2086,7 +2086,6 @@ export const dict: Record = { 'chat.statusRow.tasksTitle': '작업', 'chat.statusRow.modelStatus': '{model} · {status}', 'chat.statusRow.summary.activeLeft': '{active}개 활성 · {left}개 남음', - 'chat.statusRow.aborted': '중단됨', 'chat.revertIndicator.redo': '다시 실행', 'chat.revertIndicator.redoAria': '다시 실행 — 되돌린 메시지 복원', 'chat.revertPopover.title': '되돌림', diff --git a/packages/ui/src/lib/i18n/messages/pl.ts b/packages/ui/src/lib/i18n/messages/pl.ts index 76610ba7..a729a278 100644 --- a/packages/ui/src/lib/i18n/messages/pl.ts +++ b/packages/ui/src/lib/i18n/messages/pl.ts @@ -776,7 +776,6 @@ export const dict: Record = { 'chat.statusRow.tasksTitle': 'Zadania', 'chat.statusRow.modelStatus': '{model} · {status}', 'chat.statusRow.summary.activeLeft': '{active} aktywne · {left} pozostało', - 'chat.statusRow.aborted': 'Przerwane', 'chat.revertIndicator.redo': 'Ponów', 'chat.revertIndicator.redoAria': 'Ponów — przywróć cofnięte wiadomości', 'chat.revertPopover.title': 'Cofnięte', diff --git a/packages/ui/src/lib/i18n/messages/pt-BR.ts b/packages/ui/src/lib/i18n/messages/pt-BR.ts index 0f63edb1..4a8a9f32 100644 --- a/packages/ui/src/lib/i18n/messages/pt-BR.ts +++ b/packages/ui/src/lib/i18n/messages/pt-BR.ts @@ -2062,7 +2062,6 @@ export const dict: Record = { "chat.statusRow.tasksTitle": "Tarefas", "chat.statusRow.modelStatus": "{model} · {status}", "chat.statusRow.summary.activeLeft": "{active} ativas · {left} restantes", - "chat.statusRow.aborted": "Interrompido", "chat.revertIndicator.redo": "Refazer", "chat.revertIndicator.redoAria": "Refazer — restaurar mensagens revertidas", "chat.revertPopover.title": "Revertidas", diff --git a/packages/ui/src/lib/i18n/messages/uk.ts b/packages/ui/src/lib/i18n/messages/uk.ts index 35f91a31..b94dfb15 100644 --- a/packages/ui/src/lib/i18n/messages/uk.ts +++ b/packages/ui/src/lib/i18n/messages/uk.ts @@ -2062,7 +2062,6 @@ export const dict: Record = { "chat.statusRow.tasksTitle": "завдання", "chat.statusRow.modelStatus": "{model} · {status}", "chat.statusRow.summary.activeLeft": "Активних: {active} · залишилось: {left}", - "chat.statusRow.aborted": "Перервано", "chat.revertIndicator.redo": "Повторити", "chat.revertIndicator.redoAria": "Повторити — відновити відкочені повідомлення", "chat.revertPopover.title": "Відкочено", diff --git a/packages/ui/src/lib/i18n/messages/zh-CN.ts b/packages/ui/src/lib/i18n/messages/zh-CN.ts index 7072ef26..6af651a2 100644 --- a/packages/ui/src/lib/i18n/messages/zh-CN.ts +++ b/packages/ui/src/lib/i18n/messages/zh-CN.ts @@ -2050,7 +2050,6 @@ export const dict: Record = { 'chat.statusRow.tasksTitle': '任务', 'chat.statusRow.modelStatus': '{model} · {status}', 'chat.statusRow.summary.activeLeft': '{active} 个活跃 · 剩余 {left} 个', - 'chat.statusRow.aborted': '已中止', 'chat.revertIndicator.redo': '重做', 'chat.revertIndicator.redoAria': '重做 — 恢复已撤回的消息', 'chat.revertPopover.title': '已撤回', diff --git a/packages/ui/src/lib/i18n/messages/zh-TW.ts b/packages/ui/src/lib/i18n/messages/zh-TW.ts index 17861ebd..89b9b996 100644 --- a/packages/ui/src/lib/i18n/messages/zh-TW.ts +++ b/packages/ui/src/lib/i18n/messages/zh-TW.ts @@ -2054,7 +2054,6 @@ export const dict: Record = { 'chat.statusRow.tasksTitle': '任務', 'chat.statusRow.modelStatus': '{model} · {status}', 'chat.statusRow.summary.activeLeft': '{active} 個活躍 · 剩餘 {left} 個', - 'chat.statusRow.aborted': '已中止', 'chat.revertIndicator.redo': '重做', 'chat.revertIndicator.redoAria': '重做 — 恢復已收回的訊息', 'chat.revertPopover.title': '已收回',