diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 0679069..a65debf 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -95,6 +95,9 @@ // Add to conversations list conversationsState.add(conversation); + // Update browser tab title + currentTitle = title; + // Set up chat state for the new conversation chatState.conversationId = conversationId; @@ -416,10 +419,14 @@ userMessage: string, assistantMessage: string ): Promise { + console.log('[NewChat] generateSmartTitle called:', { conversationId, userMessage: userMessage.substring(0, 50) }); try { // Use a small, fast model for title generation if available, otherwise use selected const model = modelsState.selectedId; - if (!model) return; + if (!model) { + console.log('[NewChat] No model selected, skipping title generation'); + return; + } // Strip thinking blocks from assistant message for cleaner title generation const cleanedAssistant = assistantMessage @@ -427,28 +434,44 @@ .replace(/[\s\S]*?<\/thinking>/g, '') .trim(); + console.log('[NewChat] cleanedAssistant length:', cleanedAssistant.length); + + // Build prompt - use assistant content if available, otherwise just user message + const promptContent = cleanedAssistant.length > 0 + ? `User: ${userMessage.substring(0, 200)}\n\nAssistant: ${cleanedAssistant.substring(0, 300)}` + : `User message: ${userMessage.substring(0, 400)}`; + + console.log('[NewChat] Generating title with model:', model); + const response = await ollamaClient.chat({ model, messages: [ { role: 'system', - content: 'Generate a very short, concise title (3-6 words max) for this conversation. Output ONLY the title, no quotes, no explanation.' + content: 'Generate a very short, concise title (3-6 words max) for this conversation. Output ONLY the title, no quotes, no explanation, no thinking.' }, { role: 'user', - content: `User: ${userMessage.substring(0, 200)}\n\nAssistant: ${cleanedAssistant.substring(0, 300)}` + content: promptContent } ] }); + console.log('[NewChat] Title generation response:', response.message.content); + + // Strip any thinking blocks from the title response and clean it up const newTitle = response.message.content + .replace(/[\s\S]*?<\/think>/g, '') + .replace(/[\s\S]*?<\/thinking>/g, '') .trim() .replace(/^["']|["']$/g, '') // Remove quotes + .replace(/^Title:\s*/i, '') // Remove "Title:" prefix if present .substring(0, 50); if (newTitle && newTitle.length > 0) { await updateConversation(conversationId, { title: newTitle }); conversationsState.update(conversationId, { title: newTitle }); + currentTitle = newTitle; console.log('[NewChat] Updated title to:', newTitle); } } catch (error) { @@ -456,8 +479,15 @@ // Silently fail - keep the original title } } + + // Track current chat title for browser tab + let currentTitle = $state(null); + + {currentTitle ? `${currentTitle} - Ollama WebUI` : 'Ollama WebUI'} + +
diff --git a/frontend/src/routes/chat/[id]/+page.svelte b/frontend/src/routes/chat/[id]/+page.svelte index 089eaa9..36cf2e8 100644 --- a/frontend/src/routes/chat/[id]/+page.svelte +++ b/frontend/src/routes/chat/[id]/+page.svelte @@ -99,6 +99,10 @@ ); + + {conversation?.title ?? 'Chat'} - Ollama WebUI + +
{#if isLoading}