diff --git a/apps/desktop/src/DocumentPreview.tsx b/apps/desktop/src/DocumentPreview.tsx index 672b663..09e8a71 100644 --- a/apps/desktop/src/DocumentPreview.tsx +++ b/apps/desktop/src/DocumentPreview.tsx @@ -58,7 +58,7 @@ function DocumentPreview({ isOpen, onClose, documentUrl, filename, highlightText const page = await pdf.getPage(i); const textContent = await page.getTextContent(); const pageText = normalizeText( - textContent.items.map((item: { str?: string }) => item.str || '').join(' ') + textContent.items.map((item) => ('str' in item ? item.str : '')).join(' ') ); if (pageText.includes(searchSnippet)) { setPageNumber(i); diff --git a/apps/desktop/src/components/layout/SourcePanel.tsx b/apps/desktop/src/components/layout/SourcePanel.tsx index 1a49557..0d211b5 100644 --- a/apps/desktop/src/components/layout/SourcePanel.tsx +++ b/apps/desktop/src/components/layout/SourcePanel.tsx @@ -27,7 +27,7 @@ export function SourcePanel({ onSourceClick }: SourcePanelProps) {
{activeSources.map((source, i) => { - const nbId = (source as Record).notebook_id as string | undefined; + const nbId = source.notebook_id; const nbName = nbId ? notebooks.find((nb) => nb.notebook_id === nbId)?.title : null; return ( diff --git a/apps/desktop/src/components/ui/SetupWizard.tsx b/apps/desktop/src/components/ui/SetupWizard.tsx index 8d20cb2..42310fc 100644 --- a/apps/desktop/src/components/ui/SetupWizard.tsx +++ b/apps/desktop/src/components/ui/SetupWizard.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react'; -import { fetchConfig, uploadDocument } from '../../api'; +import { uploadDocument } from '../../api'; import { useAppStore } from '../../store/app-store'; import { useNotebooks } from '../../hooks/useNotebooks'; import { showToast } from './Toast'; @@ -34,7 +34,6 @@ export function SetupWizard({ onComplete }: { onComplete: () => void }) { const [ollamaStatus, setOllamaStatus] = useState({ state: 'checking' }); const [selectedModel, setSelectedModel] = useState(null); const [uploading, setUploading] = useState(false); - const [uploadedFilename, setUploadedFilename] = useState(null); const fileInputRef = useRef(null); const { refresh: refreshNotebooks } = useNotebooks(); @@ -95,7 +94,6 @@ export function SetupWizard({ onComplete }: { onComplete: () => void }) { const result = await uploadDocument(file); useAppStore.getState().setActiveNotebookId(result.notebook_id); await refreshNotebooks(); - setUploadedFilename(file.name); showToast(`${file.name} indexed successfully`, 'success'); // Mark wizard complete and hand off diff --git a/apps/desktop/src/components/ui/ZoteroImport.tsx b/apps/desktop/src/components/ui/ZoteroImport.tsx index 211de6d..09b6a13 100644 --- a/apps/desktop/src/components/ui/ZoteroImport.tsx +++ b/apps/desktop/src/components/ui/ZoteroImport.tsx @@ -1,5 +1,4 @@ import { useEffect, useState } from 'react'; -import { useAppStore } from '../../store/app-store'; import { useNotebooks } from '../../hooks/useNotebooks'; import { showToast } from './Toast'; import './zotero-import.css'; diff --git a/apps/desktop/src/hooks/useChat.ts b/apps/desktop/src/hooks/useChat.ts index ed56838..34e5b30 100644 --- a/apps/desktop/src/hooks/useChat.ts +++ b/apps/desktop/src/hooks/useChat.ts @@ -47,7 +47,7 @@ export function useChat() { const sources: SourceChunk[] = (event.sources ?? []).map((src) => ({ ...src, document_name: src.source_path.split(/[/\\]/).pop() ?? src.source_path, - relevance_score: (src as Record).relevance_score as number | undefined, + relevance_score: src.relevance_score, })); s.setActiveSources(sources); // Capture conversation_id from backend (created on first message) diff --git a/apps/desktop/src/types.ts b/apps/desktop/src/types.ts index 9c48dc7..d425e3f 100644 --- a/apps/desktop/src/types.ts +++ b/apps/desktop/src/types.ts @@ -21,6 +21,8 @@ export interface StreamSource { source_path: string; preview: string; distance?: number | null; + relevance_score?: number; + notebook_id?: string; } export type ChatStreamEvent = @@ -94,6 +96,7 @@ export interface SourceChunk { distance?: number | null; document_name: string; relevance_score?: number; + notebook_id?: string; } export interface CreateNotebookRequest { diff --git a/backend/notebooklm_backend/models/chat.py b/backend/notebooklm_backend/models/chat.py index 76c2d30..5ac3fcb 100644 --- a/backend/notebooklm_backend/models/chat.py +++ b/backend/notebooklm_backend/models/chat.py @@ -14,7 +14,10 @@ class ChatRequest(BaseModel): prompt: str history: List[ChatMessage] | None = None notebook_id: str | None = Field(None, description="Optional notebook ID for RAG-enabled chat") - notebook_ids: List[str] | None = Field(None, description="Optional list of notebook IDs for cross-notebook synthesis") + notebook_ids: List[str] | None = Field( + None, + description="Optional list of notebook IDs for cross-notebook synthesis", + ) conversation_id: str | None = Field(None, description="Optional conversation ID for persistence") diff --git a/backend/notebooklm_backend/routes/chat.py b/backend/notebooklm_backend/routes/chat.py index aadddb5..7f20377 100644 --- a/backend/notebooklm_backend/routes/chat.py +++ b/backend/notebooklm_backend/routes/chat.py @@ -46,7 +46,6 @@ async def event_generator(): accumulated_reply = "" sources_data: list[dict] | None = None conversation_id = payload.conversation_id - persist_warning = False try: # Create conversation on first message if no conversation_id provided diff --git a/backend/notebooklm_backend/services/conversation_store.py b/backend/notebooklm_backend/services/conversation_store.py index 7a9df0e..bc8518f 100644 --- a/backend/notebooklm_backend/services/conversation_store.py +++ b/backend/notebooklm_backend/services/conversation_store.py @@ -5,8 +5,7 @@ import uuid from contextlib import contextmanager from datetime import datetime, timezone -from dataclasses import dataclass, field -from pathlib import Path +from dataclasses import dataclass from typing import Iterable from ..config import AppConfig diff --git a/backend/tests/test_conversation_store.py b/backend/tests/test_conversation_store.py index aefec72..6627c76 100644 --- a/backend/tests/test_conversation_store.py +++ b/backend/tests/test_conversation_store.py @@ -143,9 +143,9 @@ def test_messages_ordered_by_created_at(store): def test_conversations_ordered_by_updated_at(store): c1 = store.create_conversation(notebook_id="nb1", title="Older") - c2 = store.create_conversation(notebook_id="nb1", title="Newer") + store.create_conversation(notebook_id="nb1", title="Newer") - # c2 was created after c1, so it should appear first (DESC order) + # The newer conversation was created after c1, so it should appear first (DESC order) convs = store.list_conversations("nb1") assert convs[0].title == "Newer" assert convs[1].title == "Older" diff --git a/backend/tests/test_cross_notebook.py b/backend/tests/test_cross_notebook.py index 595b0e8..e5bc5eb 100644 --- a/backend/tests/test_cross_notebook.py +++ b/backend/tests/test_cross_notebook.py @@ -2,7 +2,7 @@ import pytest from notebooklm_backend.config import AppConfig -from notebooklm_backend.services.vector_store import VectorStoreManager, create_vector_store +from notebooklm_backend.services.vector_store import create_vector_store from notebooklm_backend.services.chunking import TextChunk