diff --git a/src/components/ChatInterface.jsx b/src/components/ChatInterface.jsx index b3238fb6..42aaa80b 100755 --- a/src/components/ChatInterface.jsx +++ b/src/components/ChatInterface.jsx @@ -24,6 +24,7 @@ import ClaudeLogo from './ClaudeLogo.jsx'; import ClaudeStatus from './ClaudeStatus'; import { MicButton } from './MicButton.jsx'; import { api } from '../utils/api'; +import ThinkingModeSelector, { thinkingModes } from './ThinkingModeSelector.jsx'; // Memoized message component to prevent unnecessary re-renders const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFileOpen, onShowSettings, autoExpandTools, showRawParameters }) => { @@ -924,6 +925,7 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess const [selectedCommandIndex, setSelectedCommandIndex] = useState(-1); const [slashPosition, setSlashPosition] = useState(-1); const [claudeStatus, setClaudeStatus] = useState(null); + const [thinkingMode, setThinkingMode] = useState('none'); // Memoized diff calculation to prevent recalculating on every render @@ -1624,6 +1626,13 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess e.preventDefault(); if (!input.trim() || isLoading || !selectedProject) return; + // Apply thinking mode prefix if selected + let messageContent = input; + const selectedThinkingMode = thinkingModes.find(mode => mode.id === thinkingMode); + if (selectedThinkingMode && selectedThinkingMode.prefix) { + messageContent = `${selectedThinkingMode.prefix}: ${input}`; + } + const userMessage = { type: 'user', content: input, @@ -1676,7 +1685,7 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess // Send command to Claude CLI via WebSocket sendMessage({ type: 'claude-command', - command: input, + command: messageContent, options: { projectPath: selectedProject.path, cwd: selectedProject.fullPath, @@ -1689,6 +1698,7 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess setInput(''); setIsTextareaExpanded(false); + setThinkingMode('none'); // Reset thinking mode after sending // Clear the saved draft since message was sent if (selectedProject) { localStorage.removeItem(`draft_input_${selectedProject.name}`); @@ -1955,6 +1965,13 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess + {/* Thinking Mode Selector */} + + {/* Scroll to bottom button - positioned next to mode indicator */} {isUserScrolledUp && chatMessages.length > 0 && ( { + const handleClickOutside = (event) => { + if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { + setIsOpen(false); + if (onClose) onClose(); + } + }; + + document.addEventListener('mousedown', handleClickOutside); + return () => document.removeEventListener('mousedown', handleClickOutside); + }, [onClose]); + + const currentMode = thinkingModes.find(mode => mode.id === selectedMode) || thinkingModes[0]; + const IconComponent = currentMode.icon || Brain; + + return ( + + setIsOpen(!isOpen)} + className={`w-10 h-10 sm:w-10 sm:h-10 rounded-full flex items-center justify-center transition-all duration-200 ${ + selectedMode === 'none' + ? 'bg-gray-100 hover:bg-gray-200 dark:bg-gray-700 dark:hover:bg-gray-600' + : 'bg-blue-100 hover:bg-blue-200 dark:bg-blue-900 dark:hover:bg-blue-800' + }`} + title={`Thinking mode: ${currentMode.name}`} + > + + + + {isOpen && ( + + + + + Thinking Mode + + { + setIsOpen(false); + if (onClose) onClose(); + }} + className="p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded" + > + + + + + Extended thinking gives Claude more time to evaluate alternatives + + + + + {thinkingModes.map((mode) => { + const ModeIcon = mode.icon; + const isSelected = mode.id === selectedMode; + + return ( + { + onModeChange(mode.id); + setIsOpen(false); + if (onClose) onClose(); + }} + className={`w-full px-4 py-3 text-left hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors ${ + isSelected ? 'bg-gray-50 dark:bg-gray-700' : '' + }`} + > + + + {ModeIcon ? : } + + + + + {mode.name} + + {isSelected && ( + + Active + + )} + + + {mode.description} + + {mode.prefix && ( + + {mode.prefix} + + )} + + + + ); + })} + + + + + Tip: Higher thinking modes take more time but provide more thorough analysis + + + + )} + + ); +} + +export default ThinkingModeSelector; +export { thinkingModes }; \ No newline at end of file
+ Extended thinking gives Claude more time to evaluate alternatives +
+ {mode.description} +
+ {mode.prefix} +
+ Tip: Higher thinking modes take more time but provide more thorough analysis +