From c1670cfd8540d898d08c12d3cba7fbe354ebbc7c Mon Sep 17 00:00:00 2001 From: MaheshtheDev <38828053+MaheshtheDev@users.noreply.github.com> Date: Sun, 9 Nov 2025 07:29:01 +0000 Subject: [PATCH] fix: hydration issue and selected model in chat (#568) - Fixes the Hydration issue on the model selector - Add ability to show the Model --- apps/web/components/model-selector.tsx | 44 +------------ .../components/views/chat/chat-messages.tsx | 24 ++++--- apps/web/lib/models.tsx | 65 +++++++++++++++++++ 3 files changed, 82 insertions(+), 51 deletions(-) create mode 100644 apps/web/lib/models.tsx diff --git a/apps/web/components/model-selector.tsx b/apps/web/components/model-selector.tsx index d0e29974..f71e7d58 100644 --- a/apps/web/components/model-selector.tsx +++ b/apps/web/components/model-selector.tsx @@ -4,26 +4,7 @@ import { useState } from "react" import { Button } from "@repo/ui/components/button" import { ChevronDown } from "lucide-react" import { motion } from "motion/react" - -const models = [ - { - id: "gpt-5", - name: "GPT 5", - description: "OpenAI's latest model", - }, - { - id: "claude-sonnet-4.5", - name: "Claude Sonnet 4.5", - description: "Anthropic's advanced model", - }, - { - id: "gemini-2.5-pro", - name: "Gemini 2.5 Pro", - description: "Google's most capable model", - }, -] as const - -type ModelId = (typeof models)[number]["id"] +import { models, type ModelId, ModelIcon } from "@/lib/models" interface ModelSelectorProps { selectedModel?: ModelId @@ -54,28 +35,7 @@ export function ModelSelector({ onClick={() => !disabled && setIsOpen(!isOpen)} disabled={disabled} > - - - - - - - - - - + {currentModel.name} diff --git a/apps/web/components/views/chat/chat-messages.tsx b/apps/web/components/views/chat/chat-messages.tsx index 22bc8a2a..ff4eca34 100644 --- a/apps/web/components/views/chat/chat-messages.tsx +++ b/apps/web/components/views/chat/chat-messages.tsx @@ -19,6 +19,7 @@ import { Streamdown } from "streamdown" import { TextShimmer } from "@/components/text-shimmer" import { usePersistentChat, useProject } from "@/stores" import { useGraphHighlights } from "@/stores/highlights" +import { modelNames, ModelIcon } from "@/lib/models" import { Spinner } from "../../spinner" interface MemoryResult { @@ -242,14 +243,7 @@ export function ChatMessages() { const [input, setInput] = useState("") const [selectedModel, setSelectedModel] = useState< "gpt-5" | "claude-sonnet-4.5" | "gemini-2.5-pro" - >( - (sessionStorage.getItem(storageKey) as - | "gpt-5" - | "claude-sonnet-4.5" - | "gemini-2.5-pro") || - "gemini-2.5-pro" || - "gemini-2.5-pro", - ) + >("gemini-2.5-pro") const activeChatIdRef = useRef(null) const shouldGenerateTitleRef = useRef(false) const hasRunInitialMessageRef = useRef(false) @@ -293,6 +287,7 @@ export function ChatMessages() { }, [currentChatId, id]) useEffect(() => { + if (typeof window === "undefined") return if (currentChatId) { const savedModel = sessionStorage.getItem(storageKey) as | "gpt-5" @@ -309,6 +304,7 @@ export function ChatMessages() { }, [currentChatId, storageKey]) useEffect(() => { + if (typeof window === "undefined") return if (currentChatId && !hasRunInitialMessageRef.current) { // Check if there's an initial message from the home page in sessionStorage const storageKey = `chat-initial-${currentChatId}` @@ -637,7 +633,17 @@ export function ChatMessages() { className="w-full text-foreground placeholder:text-muted-foreground rounded-md outline-none resize-none text-base leading-relaxed px-3 py-3 bg-transparent" rows={3} /> - + + + + + {modelNames[selectedModel]} + + = { + "gpt-5": "GPT 5", + "claude-sonnet-4.5": "Claude Sonnet 4.5", + "gemini-2.5-pro": "Gemini 2.5 Pro", +} + +interface ModelIconProps { + width?: number + height?: number + className?: string +} + +export function ModelIcon({ + width = 24, + height = 24, + className, +}: ModelIconProps) { + return ( + + Model icon + + + + + + + + + + ) +}