diff --git a/desktop/src/components/chat/AskUserQuestion.tsx b/desktop/src/components/chat/AskUserQuestion.tsx index 4ec8d6a5..3178d237 100644 --- a/desktop/src/components/chat/AskUserQuestion.tsx +++ b/desktop/src/components/chat/AskUserQuestion.tsx @@ -1,5 +1,5 @@ import { useMemo, useRef, useState } from 'react' -import { useChatStore } from '../../stores/chatStore' +import { listPendingPermissions, useChatStore } from '../../stores/chatStore' import { useTabStore } from '../../stores/tabStore' import { useTranslation } from '../../i18n' import { Button } from '../shared/Button' @@ -68,7 +68,10 @@ export function AskUserQuestion({ sessionId, toolUseId, input, result }: Props) const { respondToPermission } = useChatStore() const activeTabId = useTabStore((s) => s.activeTabId) const targetSessionId = sessionId ?? activeTabId - const pendingPermission = useChatStore((s) => targetSessionId ? s.sessions[targetSessionId]?.pendingPermission : undefined) + const pendingRequest = useChatStore((s) => targetSessionId + ? listPendingPermissions(s.sessions[targetSessionId]) + .find((permission) => permission.toolUseId === toolUseId) ?? null + : null) const t = useTranslation() const questions = parseInput(input) const inputObject = (input && typeof input === 'object') ? input as Record : {} @@ -93,7 +96,6 @@ export function AskUserQuestion({ sessionId, toolUseId, input, result }: Props) const hasStructuredAnswers = Object.keys(resultAnswers).length > 0 const hasTerminalResult = hasStructuredAnswers || resultText.length > 0 - const pendingRequest = pendingPermission?.toolUseId === toolUseId ? pendingPermission : null const answeredText = useMemo(() => { if (hasStructuredAnswers) { return questions diff --git a/desktop/src/components/chat/MessageList.tsx b/desktop/src/components/chat/MessageList.tsx index 42a4b6d9..6b5eface 100644 --- a/desktop/src/components/chat/MessageList.tsx +++ b/desktop/src/components/chat/MessageList.tsx @@ -3,7 +3,7 @@ import { createPortal } from 'react-dom' import { ArrowDown, BookMarked, Bot, CheckCircle2, ChevronDown, ChevronRight, CircleStop, FileStack, LoaderCircle, MessageCircle, Settings, Target, XCircle } from 'lucide-react' import { ApiError } from '../../api/client' import { sessionsApi, type SessionTurnCheckpoint } from '../../api/sessions' -import { useChatStore } from '../../stores/chatStore' +import { listPendingPermissions, useChatStore } from '../../stores/chatStore' import { useSessionStore } from '../../stores/sessionStore' import { useWorkspaceChatContextStore } from '../../stores/workspaceChatContextStore' import { SETTINGS_TAB_ID, useTabStore } from '../../stores/tabStore' @@ -1378,9 +1378,8 @@ export function MessageList({ sessionId, compact = false }: MessageListProps = { const agentTaskNotifications = sessionState?.agentTaskNotifications ?? EMPTY_AGENT_TASK_NOTIFICATIONS const hasRunningBackgroundTasks = hasAnyRunningBackgroundTasks(sessionState?.backgroundAgentTasks) const activeAskUserQuestionToolUseId = - sessionState?.pendingPermission?.toolName === 'AskUserQuestion' - ? sessionState.pendingPermission.toolUseId - : null + listPendingPermissions(sessionState) + .find((permission) => permission.toolName === 'AskUserQuestion')?.toolUseId ?? null const shouldFollowContentResize = streamingText.trim().length > 0 || chatState === 'streaming' || diff --git a/desktop/src/components/chat/PermissionDialog.tsx b/desktop/src/components/chat/PermissionDialog.tsx index 703cf8de..681fa5b9 100644 --- a/desktop/src/components/chat/PermissionDialog.tsx +++ b/desktop/src/components/chat/PermissionDialog.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { useChatStore } from '../../stores/chatStore' +import { getPendingPermission, useChatStore } from '../../stores/chatStore' import { useTabStore } from '../../stores/tabStore' import { useTranslation } from '../../i18n' import type { TranslationKey } from '../../i18n' @@ -122,9 +122,11 @@ export function PermissionDialog({ sessionId, requestId, toolName, input, descri const { respondToPermission } = useChatStore() const activeTabId = useTabStore((s) => s.activeTabId) const targetSessionId = sessionId ?? activeTabId - const pendingPermission = useChatStore((s) => targetSessionId ? s.sessions[targetSessionId]?.pendingPermission : undefined) + const pendingPermission = useChatStore((s) => targetSessionId + ? getPendingPermission(s.sessions[targetSessionId], requestId) + : undefined) const t = useTranslation() - const isPending = pendingPermission?.requestId === requestId + const isPending = Boolean(pendingPermission) const [showRaw, setShowRaw] = useState(false) if (isExitPlanModeTool(toolName)) { @@ -145,13 +147,18 @@ export function PermissionDialog({ sessionId, requestId, toolName, input, descri const preview = renderPermissionPreview(toolName, input) const title = getPermissionTitle(toolName, input, t) const allowRawToggle = !preview + const permissionContext = (details.primary || description || toolName).slice(0, 160) return ( -
+
{/* Header */}
{isPending && ( - + )} @@ -198,7 +206,7 @@ export function PermissionDialog({ sessionId, requestId, toolName, input, descri
{details.primary && toolName !== 'Bash' ? (
- + {details.primary} @@ -209,7 +217,7 @@ export function PermissionDialog({ sessionId, requestId, toolName, input, descri ) : details.primary ? (
- + {details.primary} @@ -227,7 +235,7 @@ export function PermissionDialog({ sessionId, requestId, toolName, input, descri onClick={() => setShowRaw(!showRaw)} className="mt-2 flex cursor-pointer items-center gap-1 text-[11px] text-[var(--color-text-accent)] hover:underline" > - + {showRaw ? t('permission.hideDetails') : t('permission.showFullInput')} @@ -247,9 +255,10 @@ export function PermissionDialog({ sessionId, requestId, toolName, input, descri