diff --git a/frontend/src/components/ChatPanel.vue b/frontend/src/components/ChatPanel.vue index 3be41ef..48c05e2 100644 --- a/frontend/src/components/ChatPanel.vue +++ b/frontend/src/components/ChatPanel.vue @@ -299,12 +299,22 @@ defineExpose({ focus, prefill, send })
- + > + +
+ New Briefing Update +
+ + @@ -523,6 +533,28 @@ defineExpose({ focus, prefill, send }) justify-content: flex-end; } +/* Briefing slot separator */ +.briefing-slot-separator { + display: flex; + align-items: center; + gap: 0.75rem; + margin: 1.25rem 0 0.5rem; + color: var(--color-text-muted, #888); + font-size: 0.7rem; + font-weight: 600; + letter-spacing: 0.08em; + text-transform: uppercase; + opacity: 0.7; +} +.briefing-slot-separator::before, +.briefing-slot-separator::after { + content: ''; + flex: 1; + height: 1px; + background: var(--color-border, #333); + opacity: 0.5; +} + /* Context sidebar */ .context-sidebar { width: 200px; diff --git a/frontend/src/types/chat.ts b/frontend/src/types/chat.ts index 9d97812..162dd99 100644 --- a/frontend/src/types/chat.ts +++ b/frontend/src/types/chat.ts @@ -28,6 +28,7 @@ export interface Message { context_note_id: number | null; context_note_title?: string | null; tool_calls?: ToolCallRecord[] | null; + metadata?: Record | null; created_at: string; timing?: GenerationTiming; thinking?: string; diff --git a/src/fabledassistant/services/llm.py b/src/fabledassistant/services/llm.py index 67abd71..178e501 100644 --- a/src/fabledassistant/services/llm.py +++ b/src/fabledassistant/services/llm.py @@ -607,6 +607,25 @@ async def build_context( f"\n\n--- Earlier Conversation ---\n{history_summary}\n--- End Earlier Conversation ---" ) + # Detect briefing conversation — used for both system prompt instruction and article injection + _is_briefing_conv = False + if conv_id is not None: + from fabledassistant.models import async_session as _async_session + from fabledassistant.models.conversation import Conversation as _Conversation + async with _async_session() as _sess: + _conv = await _sess.get(_Conversation, conv_id) + if _conv and getattr(_conv, "conversation_type", None) == "briefing": + _is_briefing_conv = True + + if _is_briefing_conv: + system_content += ( + "\n\nYou are in a briefing conversation. " + "The conversation history contains today's briefing — news stories, weather, and tasks. " + "When the user asks about a topic, person, or event from the briefing, answer directly " + "from the conversation history and the article context that follows. " + "Do NOT search the web for information that is already present in the briefing." + ) + context_meta: dict = { "context_note_id": None, "context_note_title": None, @@ -769,16 +788,10 @@ async def build_context( ) # Briefing article context for follow-up Q&A - if conv_id is not None: - from fabledassistant.models import async_session as _async_session - from fabledassistant.models.conversation import Conversation - - async with _async_session() as _sess: - _conv = await _sess.get(Conversation, conv_id) - if _conv and getattr(_conv, "conversation_type", None) == "briefing": - article_context = await _build_briefing_article_context(conv_id) - if article_context: - user_context_parts.append(article_context.strip()) + if _is_briefing_conv: + article_context = await _build_briefing_article_context(conv_id) # type: ignore[arg-type] + if article_context: + user_context_parts.append(article_context.strip()) # Build final user message — context prefix (if any) followed by the actual message if user_context_parts: