| ... | ... | @@ -51,7 +51,7 @@ import { |
| 51 | 51 | } from "../session-logic"; |
| 52 | 52 | import { isScrollContainerNearBottom } from "../chat-scroll"; |
| 53 | 53 | import { useStore } from "../store"; |
| 54 | | import type { ChatImageAttachment, Thread } from "../types"; |
| 54 | import type { ChatImageAttachment } from "../types"; |
| 55 | 55 | import BranchToolbar from "./BranchToolbar"; |
| 56 | 56 | import GitActionsControl from "./GitActionsControl"; |
| 57 | 57 | import { |
| ... | ... | @@ -168,6 +168,7 @@ export default function ChatView() { |
| 168 | 168 | |
| 169 | 169 | const activeThread = state.threads.find((t) => t.id === state.activeThreadId); |
| 170 | 170 | const activeThreadId = activeThread?.id ?? null; |
| 171 | const activeSessionId = activeThread?.session?.sessionId; |
| 171 | 172 | const activeProject = state.projects.find((p) => p.id === activeThread?.projectId); |
| 172 | 173 | const selectedModel = resolveModelSlug( |
| 173 | 174 | activeThread?.model ?? activeProject?.model ?? DEFAULT_MODEL, |
| ... | ... | @@ -895,28 +896,28 @@ export default function ChatView() { |
| 895 | 896 | |
| 896 | 897 | const onRespondToApproval = useCallback( |
| 897 | 898 | async (requestId: string, decision: ProviderApprovalDecision) => { |
| 898 | | if (!api || !activeThread?.session) return; |
| 899 | if (!api || !activeSessionId || !activeThreadId) return; |
| 899 | 900 | |
| 900 | 901 | setRespondingRequestIds((existing) => |
| 901 | 902 | existing.includes(requestId) ? existing : [...existing, requestId], |
| 902 | 903 | ); |
| 903 | 904 | try { |
| 904 | 905 | await api.providers.respondToRequest({ |
| 905 | | sessionId: activeThread.session.sessionId, |
| 906 | sessionId: activeSessionId, |
| 906 | 907 | requestId, |
| 907 | 908 | decision, |
| 908 | 909 | }); |
| 909 | 910 | } catch (err) { |
| 910 | 911 | dispatch({ |
| 911 | 912 | type: "SET_ERROR", |
| 912 | | threadId: activeThread.id, |
| 913 | threadId: activeThreadId, |
| 913 | 914 | error: err instanceof Error ? err.message : "Failed to submit approval decision.", |
| 914 | 915 | }); |
| 915 | 916 | } finally { |
| 916 | 917 | setRespondingRequestIds((existing) => existing.filter((id) => id !== requestId)); |
| 917 | 918 | } |
| 918 | 919 | }, |
| 919 | | [activeThread?.id, activeThread?.session, api, dispatch], |
| 920 | [activeSessionId, activeThreadId, api, dispatch], |
| 920 | 921 | ); |
| 921 | 922 | |
| 922 | 923 | const onModelSelect = useCallback( |
| ... | ... | @@ -1015,7 +1016,7 @@ export default function ChatView() { |
| 1015 | 1016 | onScroll={onMessagesScroll} |
| 1016 | 1017 | > |
| 1017 | 1018 | <MessagesTimeline |
| 1018 | | activeThread={activeThread} |
| 1019 | hasMessages={activeThread.messages.length > 0} |
| 1019 | 1020 | isWorking={isWorking} |
| 1020 | 1021 | timelineEntries={timelineEntries} |
| 1021 | 1022 | completionDividerBeforeEntryId={completionDividerBeforeEntryId} |
| ... | ... | @@ -1413,7 +1414,7 @@ const PendingApprovalsPanel = memo(function PendingApprovalsPanel({ |
| 1413 | 1414 | }); |
| 1414 | 1415 | |
| 1415 | 1416 | interface MessagesTimelineProps { |
| 1416 | | activeThread: Thread; |
| 1417 | hasMessages: boolean; |
| 1417 | 1418 | isWorking: boolean; |
| 1418 | 1419 | timelineEntries: ReturnType<typeof deriveTimelineEntries>; |
| 1419 | 1420 | completionDividerBeforeEntryId: string | null; |
| ... | ... | @@ -1427,7 +1428,7 @@ interface MessagesTimelineProps { |
| 1427 | 1428 | } |
| 1428 | 1429 | |
| 1429 | 1430 | const MessagesTimeline = memo(function MessagesTimeline({ |
| 1430 | | activeThread, |
| 1431 | hasMessages, |
| 1431 | 1432 | isWorking, |
| 1432 | 1433 | timelineEntries, |
| 1433 | 1434 | completionDividerBeforeEntryId, |
| ... | ... | @@ -1439,7 +1440,7 @@ const MessagesTimeline = memo(function MessagesTimeline({ |
| 1439 | 1440 | onImageExpand, |
| 1440 | 1441 | messagesEndRef, |
| 1441 | 1442 | }: MessagesTimelineProps) { |
| 1442 | | if (activeThread.messages.length === 0 && !isWorking) { |
| 1443 | if (!hasMessages && !isWorking) { |
| 1443 | 1444 | return ( |
| 1444 | 1445 | <div className="flex h-full items-center justify-center"> |
| 1445 | 1446 | <p className="text-sm text-muted-foreground/30">Send a message to start the conversation.</p> |