feat: wire ModelSelectorBar + message queue into ChatInterface

This commit is contained in:
Zac Gaetano 2026-05-30 10:02:00 -04:00
parent b637f0287d
commit f7be8ff31d

View file

@ -14,6 +14,7 @@ import { useSessionStore } from '../../../stores/useSessionStore';
import ChatMessagesPane from './subcomponents/ChatMessagesPane'; import ChatMessagesPane from './subcomponents/ChatMessagesPane';
import ChatComposer from './subcomponents/ChatComposer'; import ChatComposer from './subcomponents/ChatComposer';
import ModelSelectorBar from './subcomponents/ModelSelectorBar';
type PendingViewSession = { type PendingViewSession = {
@ -72,6 +73,10 @@ function ChatInterface({
setCodexModel, setCodexModel,
geminiModel, geminiModel,
setGeminiModel, setGeminiModel,
claudeModelOptions,
codexModelOptions,
geminiModelOptions,
cursorModelOptions,
permissionMode, permissionMode,
pendingPermissionRequests, pendingPermissionRequests,
setPendingPermissionRequests, setPendingPermissionRequests,
@ -171,6 +176,7 @@ function ChatInterface({
handleGrantToolPermission, handleGrantToolPermission,
handleInputFocusChange, handleInputFocusChange,
isInputFocused, isInputFocused,
messageQueue,
} = useChatComposerState({ } = useChatComposerState({
selectedProject, selectedProject,
selectedSession, selectedSession,
@ -205,13 +211,11 @@ function ChatInterface({
}); });
// On WebSocket reconnect, re-fetch the current session's messages from the server // On WebSocket reconnect, re-fetch the current session's messages from the server
// so missed streaming events are shown. Also reset isLoading.
const handleWebSocketReconnect = useCallback(async () => { const handleWebSocketReconnect = useCallback(async () => {
if (!selectedProject || !selectedSession) return; if (!selectedProject || !selectedSession) return;
const providerVal = (localStorage.getItem('selected-provider') as LLMProvider) || 'claude'; const providerVal = (localStorage.getItem('selected-provider') as LLMProvider) || 'claude';
await sessionStore.refreshFromServer(selectedSession.id, { await sessionStore.refreshFromServer(selectedSession.id, {
provider: (selectedSession.__provider || providerVal) as LLMProvider, provider: (selectedSession.__provider || providerVal) as LLMProvider,
// Use DB projectId; legacy folder-derived projectName is no longer accepted here.
projectId: selectedProject.projectId, projectId: selectedProject.projectId,
projectPath: selectedProject.fullPath || selectedProject.path || '', projectPath: selectedProject.fullPath || selectedProject.path || '',
}); });
@ -299,6 +303,23 @@ function ChatInterface({
return ( return (
<PermissionContext.Provider value={permissionContextValue}> <PermissionContext.Provider value={permissionContextValue}>
<div className="flex h-full flex-col"> <div className="flex h-full flex-col">
{/* Floating model selector bar — always visible above messages */}
<ModelSelectorBar
provider={provider}
claudeModel={claudeModel}
setClaudeModel={setClaudeModel}
cursorModel={cursorModel}
setCursorModel={setCursorModel}
codexModel={codexModel}
setCodexModel={setCodexModel}
geminiModel={geminiModel}
setGeminiModel={setGeminiModel}
claudeModelOptions={claudeModelOptions}
codexModelOptions={codexModelOptions}
geminiModelOptions={geminiModelOptions}
cursorModelOptions={cursorModelOptions}
/>
<ChatMessagesPane <ChatMessagesPane
scrollContainerRef={scrollContainerRef} scrollContainerRef={scrollContainerRef}
onWheel={handleScroll} onWheel={handleScroll}
@ -410,6 +431,7 @@ function ChatInterface({
})} })}
isTextareaExpanded={isTextareaExpanded} isTextareaExpanded={isTextareaExpanded}
sendByCtrlEnter={sendByCtrlEnter} sendByCtrlEnter={sendByCtrlEnter}
messageQueue={messageQueue}
/> />
</div> </div>