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