diff --git a/frontend/src/components/source/SessionManager.tsx b/frontend/src/components/source/SessionManager.tsx index cec74fa..001a42b 100644 --- a/frontend/src/components/source/SessionManager.tsx +++ b/frontend/src/components/source/SessionManager.tsx @@ -1,16 +1,16 @@ 'use client' -import { useState } from 'react' +import { useState, useMemo } from 'react' import { Button } from '@/components/ui/button' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Input } from '@/components/ui/input' import { ScrollArea } from '@/components/ui/scroll-area' import { Badge } from '@/components/ui/badge' -import { - MessageSquare, - Plus, - Trash2, - Edit2, +import { + MessageSquare, + Plus, + Trash2, + Edit2, Check, X, Clock @@ -27,6 +27,7 @@ import { AlertDialogTitle, } from '@/components/ui/alert-dialog' import { BaseChatSession } from '@/lib/types/api' +import { useModels } from '@/lib/hooks/use-models' interface SessionManagerProps { sessions: BaseChatSession[] @@ -53,6 +54,16 @@ export function SessionManager({ const [editTitle, setEditTitle] = useState('') const [deleteConfirmId, setDeleteConfirmId] = useState(null) + const { data: models } = useModels() + + // Helper to get model name from ID + const getModelName = useMemo(() => { + return (modelId: string) => { + const model = models?.find(m => m.id === modelId) + return model?.name || 'Custom Model' + } + }, [models]) + const handleCreateSession = () => { if (newSessionTitle.trim()) { onCreateSession(newSessionTitle.trim()) @@ -211,14 +222,14 @@ export function SessionManager({ {formatDistanceToNow(new Date(session.created), { addSuffix: true })} - {session.message_count && session.message_count > 0 && ( + {session.message_count != null && session.message_count > 0 && ( {session.message_count} messages )} {session.model_override && ( - {session.model_override} + {getModelName(session.model_override)} )} diff --git a/open_notebook/domain/base.py b/open_notebook/domain/base.py index 83c1b3d..f9992e2 100644 --- a/open_notebook/domain/base.py +++ b/open_notebook/domain/base.py @@ -25,6 +25,7 @@ T = TypeVar("T", bound="ObjectModel") class ObjectModel(BaseModel): id: Optional[str] = None table_name: ClassVar[str] = "" + nullable_fields: ClassVar[set[str]] = set() # Fields that can be saved as None created: Optional[datetime] = None updated: Optional[datetime] = None @@ -167,7 +168,11 @@ class ObjectModel(BaseModel): def _prepare_save_data(self) -> Dict[str, Any]: data = self.model_dump() - return {key: value for key, value in data.items() if value is not None} + return { + key: value + for key, value in data.items() + if value is not None or key in self.__class__.nullable_fields + } async def delete(self) -> bool: if self.id is None: diff --git a/open_notebook/domain/notebook.py b/open_notebook/domain/notebook.py index cf096bd..2f589a6 100644 --- a/open_notebook/domain/notebook.py +++ b/open_notebook/domain/notebook.py @@ -389,6 +389,7 @@ class Note(ObjectModel): class ChatSession(ObjectModel): table_name: ClassVar[str] = "chat_session" + nullable_fields: ClassVar[set[str]] = {"model_override"} title: Optional[str] = None model_override: Optional[str] = None