Skip to content

Feat/lightspeed notebook chat#2754

Open
its-mitesh-kumar wants to merge 7 commits intoredhat-developer:mainfrom
its-mitesh-kumar:feat/lightspeed-notebook-chat
Open

Feat/lightspeed notebook chat#2754
its-mitesh-kumar wants to merge 7 commits intoredhat-developer:mainfrom
its-mitesh-kumar:feat/lightspeed-notebook-chat

Conversation

@its-mitesh-kumar
Copy link
Copy Markdown
Member

@its-mitesh-kumar its-mitesh-kumar commented Apr 13, 2026

Description

Depends on this #2704 , this should be merged only after #2704 got merged.

Depends on this backend PR too. https://github.com/redhat-developer/rhdh-plugins/pull/2742/changes

Fixed

Configuration

Add config in the app-config

lightspeed:
  aiNotebooks:
    enabled: true
    queryDefaults:
      model: llama3.2:3b # Set the model to use for AI Notebooks
      provider_id: ollama # Set the provider ID to use for AI Notebooks
    sessionDefaults:
      provider_id: notebooks # Set the provider ID to use for AI Notebooks
      embedding_model: sentence-transformers/sentence-transformers/all-mpnet-base-v2 # Set the embedding model to use for AI Notebooks
      embedding_dimension: 768 # Set the embedding dimension to use for AI Notebooks

UI after changes

https://github.com/user-attachments/assets/85fa5f26-cfcb-4b5a-8aea-4a8e5e8ab042
https://github.com/user-attachments/assets/d6beaf03-1151-4baa-8ee9-c650237a9fd7

✔️ Checklist

  • A changeset describing the change and affected packages. (more info)
  • Added or Updated documentation
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)

Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

This pull request adds a new top-level directory under workspaces/. Please follow Submitting a Pull Request for a New Workspace in CONTRIBUTING.md.

@rhdh-qodo-merge
Copy link
Copy Markdown

Review Summary by Qodo

Add notebook chat feature with document management and UI components

✨ Enhancement 🧪 Tests 📝 Documentation

Grey Divider

Walkthroughs

Description
• Implemented comprehensive notebook chat feature with document management capabilities
• Added NotebooksApiClient with new methods for session and document operations: createSession,
  uploadDocument, listDocuments, deleteDocument, getDocumentStatus, and querySession
• Extended NotebooksAPI interface with document operations and session management
• Created notebook-specific types for documents, sessions, and responses
• Implemented file upload validation utilities with support for file type, size, and count
  constraints
• Added React Query hooks for notebook operations: useCreateNotebook, useUploadDocument,
  useDocumentStatusPolling, useNotebookDocuments, and useCreateNotebookMessage
• Built complete UI components for notebook functionality: NotebookView, AddDocumentModal,
  DocumentSidebar, OverwriteConfirmModal, FileTypeIcon, UploadResourceScreen
• Integrated notebook view into main LightSpeedChat component with notebook creation and selection
• Added comprehensive test coverage for utilities, hooks, and components
• Provided translations in 6 languages (English, Japanese, German, French, Spanish, Italian) for all
  notebook UI elements
• Enhanced useConversationMessages hook with createMessageOverride parameter for custom message
  creation logic
• Configured backend notebook query defaults and metadata handling
Diagram
flowchart LR
  A["NotebooksApiClient"] -- "session & document methods" --> B["NotebooksAPI Interface"]
  B -- "uses" --> C["Notebook Types"]
  D["File Upload Utils"] -- "validates" --> E["AddDocumentModal"]
  E -- "uploads via" --> A
  F["useCreateNotebook"] -- "creates" --> A
  G["useUploadDocument"] -- "uploads" --> A
  H["useDocumentStatusPolling"] -- "tracks" --> A
  I["useNotebookDocuments"] -- "lists" --> A
  J["useCreateNotebookMessage"] -- "queries" --> A
  E --> K["NotebookView"]
  L["DocumentSidebar"] -- "displays" --> K
  M["OverwriteConfirmModal"] -- "confirms" --> K
  K -- "integrated into" --> N["LightSpeedChat"]
  O["Translations"] -- "supports" --> K
Loading

Grey Divider

File Changes

1. workspaces/lightspeed/plugins/lightspeed/src/api/NotebooksApiClient.ts ✨ Enhancement +144/-19

Expand NotebooksApiClient with document and session management

• Refactored error handling into a reusable handleResponseError method
• Added fetchFormData method for handling FormData uploads with 202 status support
• Implemented new API methods: createSession, uploadDocument, listDocuments, deleteDocument,
 getDocumentStatus, and querySession
• Enhanced fetchJson to handle empty responses gracefully

workspaces/lightspeed/plugins/lightspeed/src/api/NotebooksApiClient.ts


2. workspaces/lightspeed/plugins/lightspeed/src/api/notebooksApi.ts ✨ Enhancement +27/-1

Extend NotebooksAPI interface with document operations

• Added createSession method to the NotebooksAPI interface
• Extended API with document operations: uploadDocument, listDocuments, deleteDocument,
 getDocumentStatus
• Added querySession method for streaming responses

workspaces/lightspeed/plugins/lightspeed/src/api/notebooksApi.ts


3. workspaces/lightspeed/plugins/lightspeed/src/types.ts ✨ Enhancement +73/-0

Add notebook document and session response types

• Added conversation_id field to NotebookSessionMetadata
• Introduced new types: NotebookDocumentSourceType, SessionDocument, UploadDocumentResponse,
 DocumentStatus, SessionResponse, DocumentListResponse

workspaces/lightspeed/plugins/lightspeed/src/types.ts


View more (35)
4. workspaces/lightspeed/plugins/lightspeed/src/const.ts ⚙️ Configuration changes +28/-0

Add notebook upload configuration constants

• Added notebook constraints: NOTEBOOK_MAX_FILES (10), NOTEBOOK_MAX_FILE_SIZE_BYTES (25 MB),
 UNTITLED_NOTEBOOK_NAME
• Defined NOTEBOOK_ALLOWED_EXTENSIONS mapping MIME types to file extensions
• Created NOTEBOOK_EXTENSION_TO_FILE_TYPE mapping for file type conversion

workspaces/lightspeed/plugins/lightspeed/src/const.ts


5. workspaces/lightspeed/plugins/lightspeed/src/utils/notebook-upload-utils.ts ✨ Enhancement +94/-0

Create notebook file upload validation utilities

• Implemented file validation functions: validateFileType, validateFileSize, validateFileCount
• Created validateFiles function returning valid files and error messages
• Added getNotebookAcceptedFileTypes helper for file input accept attributes

workspaces/lightspeed/plugins/lightspeed/src/utils/notebook-upload-utils.ts


6. workspaces/lightspeed/plugins/lightspeed/src/utils/__tests__/notebook-upload-utils.test.ts 🧪 Tests +153/-0

Add notebook upload validation unit tests

• Comprehensive test coverage for file type validation (case-insensitive, extension checking)
• Tests for file size validation against 25 MB limit
• Tests for file count validation against maximum file limit
• Tests for combined validation scenarios and error reporting

workspaces/lightspeed/plugins/lightspeed/src/utils/tests/notebook-upload-utils.test.ts


7. workspaces/lightspeed/plugins/lightspeed/src/utils/__tests__/notebooks-utils.test.ts 🧪 Tests +62/-0

Add notebook utilities unit tests

• Tests for formatUpdatedLabel function with various date scenarios
• Coverage for today, yesterday, days ago, and older date formatting
• Tests for invalid date handling

workspaces/lightspeed/plugins/lightspeed/src/utils/tests/notebooks-utils.test.ts


8. workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useCreateNotebook.ts ✨ Enhancement +49/-0

Add useCreateNotebook hook for session creation

• Created hook for notebook creation mutation using React Query
• Handles session creation with name and optional description
• Invalidates sessions query on successful creation

workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useCreateNotebook.ts


9. workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useUploadDocument.ts ✨ Enhancement +59/-0

Add useUploadDocument hook for file uploads

• Implemented mutation hook for document uploads
• Converts file extensions to appropriate file types
• Invalidates document list query on successful upload

workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useUploadDocument.ts


10. workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useDocumentStatusPolling.ts ✨ Enhancement +79/-0

Add useDocumentStatusPolling hook for upload tracking

• Created hook for polling document processing status
• Implements adaptive polling with 5-second intervals
• Stops polling when document reaches terminal state (completed, failed, cancelled)
• Returns polling results with status and document metadata

workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useDocumentStatusPolling.ts


11. workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useNotebookDocuments.ts ✨ Enhancement +36/-0

Add useNotebookDocuments hook for document listing

• Created query hook for fetching documents in a notebook session
• Implements caching with 1-minute stale time
• Conditionally enabled based on session ID availability

workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useNotebookDocuments.ts


12. workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useCreateNotebookMessage.ts ✨ Enhancement +51/-0

Add useCreateNotebookMessage hook for queries

• Implemented mutation hook for querying notebook sessions
• Returns readable stream for streaming responses
• Includes error handling and logging

workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useCreateNotebookMessage.ts


13. workspaces/lightspeed/plugins/lightspeed/src/hooks/useCreateCoversationMessage.ts ✨ Enhancement +1/-1

Export CreateMessageVariables type

• Exported CreateMessageVariables type for external use

workspaces/lightspeed/plugins/lightspeed/src/hooks/useCreateCoversationMessage.ts


14. workspaces/lightspeed/plugins/lightspeed/src/hooks/useConversationMessages.ts ✨ Enhancement +9/-2

Add createMessageOverride parameter to useConversationMessages

• Added optional createMessageOverride parameter for custom message creation
• Allows notebook view to use its own message creation logic

workspaces/lightspeed/plugins/lightspeed/src/hooks/useConversationMessages.ts


15. workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/NotebookView.tsx ✨ Enhancement +641/-0

Add NotebookView component with chat and documents

• Comprehensive notebook view component with chat interface
• Implements document sidebar with collapsible state and file management
• Handles file uploads with validation, overwrite confirmation, and status polling
• Displays toast alerts for upload success/failure
• Integrates with conversation messages and welcome prompts

workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/NotebookView.tsx


16. workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/AddDocumentModal.tsx ✨ Enhancement +198/-0

Add AddDocumentModal for file uploads

• Modal component for adding documents to notebooks
• Implements drag-and-drop file upload with PatternFly components
• Validates files and displays error alerts
• Handles duplicate file detection and confirmation flow

workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/AddDocumentModal.tsx


17. workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/DocumentSidebar.tsx ✨ Enhancement +193/-0

Add DocumentSidebar component

• Sidebar component displaying notebook documents and upload status
• Shows document count and file type icons
• Displays spinners for in-progress uploads
• Collapsible with add document button

workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/DocumentSidebar.tsx


18. workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/OverwriteConfirmModal.tsx ✨ Enhancement +167/-0

Add OverwriteConfirmModal for duplicate handling

• Modal for confirming file overwrites
• Displays list of files to be overwritten with file type icons
• Provides overwrite and cancel actions

workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/OverwriteConfirmModal.tsx


19. workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/FileTypeIcon.tsx ✨ Enhancement +80/-0

Add FileTypeIcon component for file visualization

• Component rendering file type badges with color coding
• Supports multiple file types with distinct colors
• Displays file extension or "?" for unknown types

workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/FileTypeIcon.tsx


20. workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/SidebarCollapseIcon.tsx ✨ Enhancement +61/-0

Add sidebar control icons

• SVG icon components for sidebar collapse, expand, and add actions
• Reusable icon components with customizable styling

workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/SidebarCollapseIcon.tsx


21. workspaces/lightspeed/plugins/lightspeed/src/components/__tests__/NotebookCard.test.tsx 🧪 Tests +151/-0

Add NotebookCard component tests

• Tests for notebook card rendering and interactions
• Coverage for menu toggle, rename, delete, and click actions
• Tests for document count display

workspaces/lightspeed/plugins/lightspeed/src/components/tests/NotebookCard.test.tsx


22. workspaces/lightspeed/plugins/lightspeed/src/components/__tests__/DocumentSidebar.test.tsx 🧪 Tests +142/-0

Add DocumentSidebar component tests

• Tests for document sidebar rendering and state management
• Coverage for collapsed state, document display, and upload progress
• Tests for button interactions and file filtering

workspaces/lightspeed/plugins/lightspeed/src/components/tests/DocumentSidebar.test.tsx


23. workspaces/lightspeed/plugins/lightspeed/src/components/__tests__/OverwriteConfirmModal.test.tsx 🧪 Tests +153/-0

Add OverwriteConfirmModal component tests

• Tests for overwrite confirmation modal rendering and interactions
• Coverage for file list display and button actions
• Tests for modal visibility and close behavior

workspaces/lightspeed/plugins/lightspeed/src/components/tests/OverwriteConfirmModal.test.tsx


24. workspaces/lightspeed/plugins/lightspeed/src/components/__tests__/FileTypeIcon.test.tsx 🧪 Tests +84/-0

Add FileTypeIcon component tests

• Tests for file type icon rendering with various file extensions
• Coverage for color mapping and unknown file types
• Tests for edge cases like multiple dots and hidden files

workspaces/lightspeed/plugins/lightspeed/src/components/tests/FileTypeIcon.test.tsx


25. workspaces/lightspeed/plugins/lightspeed/src/components/LightSpeedChat.tsx ✨ Enhancement +106/-19

Integrate notebook view into main chat component

• Added notebook creation and selection state management
• Integrated NotebookView component for active notebook display
• Filtered conversations to exclude notebook-associated conversations
• Added hover effect styling to notebook cards
• Conditionally render chat header only when chat panel is active

workspaces/lightspeed/plugins/lightspeed/src/components/LightSpeedChat.tsx


26. workspaces/lightspeed/plugins/lightspeed/src/translations/ref.ts 📝 Documentation +34/-0

Add English notebook translation keys

• Added 36 new translation keys for notebook UI
• Covers notebook view, upload modal, overwrite modal, and error messages
• Supports file type information and user guidance

workspaces/lightspeed/plugins/lightspeed/src/translations/ref.ts


27. workspaces/lightspeed/plugins/lightspeed/src/translations/ja.ts 📝 Documentation +36/-0

Add Japanese notebook translations

• Added 36 Japanese translations for notebook features
• Includes UI labels, modal titles, error messages, and guidance text

workspaces/lightspeed/plugins/lightspeed/src/translations/ja.ts


28. workspaces/lightspeed/plugins/lightspeed/src/translations/de.ts 📝 Documentation +36/-0

Add German notebook translations

• Added 36 German translations for notebook features
• Covers all notebook UI elements and error messages

workspaces/lightspeed/plugins/lightspeed/src/translations/de.ts


29. workspaces/lightspeed/plugins/lightspeed/src/translations/fr.ts 📝 Documentation +36/-0

Add French notebook translations

• Added 36 French translations for notebook features
• Includes complete UI and error message translations

workspaces/lightspeed/plugins/lightspeed/src/translations/fr.ts


30. workspaces/lightspeed/plugins/lightspeed/src/translations/es.ts 📝 Documentation +36/-0

Add Spanish notebook translations

• Added 36 Spanish translations for notebook features
• Covers all notebook UI elements and error messages

workspaces/lightspeed/plugins/lightspeed/src/translations/es.ts


31. workspaces/lightspeed/plugins/lightspeed/src/translations/it.ts 📝 Documentation +36/-0

Add Italian notebook translations

• Added 36 Italian translations for notebook features
• Includes complete UI and error message translations

workspaces/lightspeed/plugins/lightspeed/src/translations/it.ts


32. workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/notebooksRouters.ts ⚙️ Configuration changes +11/-0

Configure notebook query defaults and metadata

• Added configuration reading for notebook model and provider defaults
• Enhanced query request body with model, provider, vector store IDs, and media type
• Preserves existing conversation ID in session metadata

workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/notebooksRouters.ts


33. workspaces/lightspeed/.changeset/thin-humans-sparkle.md 📝 Documentation +5/-0

Add changeset for notebook feature release

• Changeset documenting minor version bump for notebook feature additions
• Describes new notebook creation, document upload, and UI components

workspaces/lightspeed/.changeset/thin-humans-sparkle.md


34. workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/UploadResourceScreen.tsx ✨ Enhancement +79/-0

New upload resource screen component for notebooks

• New component created to display an upload resource screen with a catalog icon and call-to-action
 button
• Implements Material-UI and PatternFly styling with centered layout and custom icon styling
• Accepts onUploadClick callback prop to handle upload button interactions
• Uses translation hook for internationalized text content

workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/UploadResourceScreen.tsx


35. workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/NotebooksTab.tsx ✨ Enhancement +11/-1

Add notebook selection and creation callbacks

• Added two new callback props: onSelectNotebook and onCreateNotebook to the component interface
• Wired onCreateNotebook handler to both primary action buttons (in header and empty state)
• Passed onSelectNotebook callback to NotebookCard component for notebook selection handling

workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/NotebooksTab.tsx


36. workspaces/lightspeed/plugins/lightspeed/src/components/__tests__/LightspeedChat.test.tsx 🧪 Tests +16/-0

Add notebooks API mocking to test setup

• Added import for notebooksApiRef from the notebooks API module
• Created mockNotebooksApi object with mock implementations for all notebooks API methods (create,
 list, rename, delete, upload, query sessions)
• Registered mockNotebooksApi in the test provider's API configuration

workspaces/lightspeed/plugins/lightspeed/src/components/tests/LightspeedChat.test.tsx


37. workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/NotebookCard.tsx ✨ Enhancement +12/-3

Enable notebook card click handling with event propagation control

• Added onClick callback prop to handle notebook card selection
• Made card clickable by adding isClickable prop and onClick handler that invokes the callback
• Added event propagation stoppage in dropdown menu items to prevent triggering card click when
 using rename/delete actions

workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/NotebookCard.tsx


38. workspaces/lightspeed/plugins/lightspeed/report-alpha.api.md 📝 Documentation +23/-0

Add notebook view translation keys to API documentation

• Added 25 new translation keys for notebook view functionality including title, close, documents
 management, upload modal, and overwrite modal
• Keys cover UI labels, placeholders, error messages, and action buttons for notebook operations
• Extends the lightspeed translation reference with comprehensive notebook-related i18n strings

workspaces/lightspeed/plugins/lightspeed/report-alpha.api.md


Grey Divider

Qodo Logo

@rhdh-qodo-merge
Copy link
Copy Markdown

rhdh-qodo-merge bot commented Apr 13, 2026

Code Review by Qodo

🐞 Bugs (6)   📘 Rule violations (0)   📎 Requirement gaps (0)   🖥 UI issues (0)   🎨 UX Issues (0)
🐞\ ≡ Correctness (4) ☼ Reliability (2)

Grey Divider


Action required

1. Stream reader locked twice 🐞
Description
NotebooksApiClient.querySession() calls response.body.getReader() in the error path and then calls
getReader() again to return a reader, which will throw because the stream is already locked and also
may let non-OK responses proceed without throwing.
Code

workspaces/lightspeed/plugins/lightspeed/src/api/NotebooksApiClient.ts[R223-236]

+    if (!response.ok) {
+      const reader = response.body.getReader();
+      const { done, value } = await reader.read();
+      const text = done ? '' : new TextDecoder('utf-8').decode(value);
+      const errorMessage = JSON.parse(text);
+      if (errorMessage?.error) {
+        throw new Error(
+          `failed to query notebook session: ${errorMessage.error}`,
+        );
+      }
+    }
+
+    return response.body.getReader();
+  }
Evidence
The implementation creates a reader in the !ok branch (locking the stream) and then attempts to
create a second reader from the same response.body. Per Web Streams semantics, a ReadableStream can
only be locked to one reader at a time, so the second getReader() will throw; additionally, if the
error payload isn't JSON or lacks .error, the function falls through and tries to return a reader
for an error response.

workspaces/lightspeed/plugins/lightspeed/src/api/NotebooksApiClient.ts[205-236]
workspaces/lightspeed/plugins/lightspeed/src/api/NotebooksApiClient.ts[223-235]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`NotebooksApiClient.querySession()` locks the response stream by calling `response.body.getReader()` in the error branch and then calls `getReader()` again, which will throw at runtime. It also doesn't reliably throw for non-OK responses.

### Issue Context
This method is used for notebook chat streaming; failed requests should surface a clean error without breaking the stream API.

### Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed/src/api/NotebooksApiClient.ts[205-236]

### Suggested fix
- If `!response.ok`, read the error via `await response.text()` (or reuse a single reader and `releaseLock()`), then `throw` unconditionally.
- Only call `response.body.getReader()` once (in the success path) and return that reader.
- Wrap JSON parsing of error text in `try/catch` and fall back to raw text when not JSON.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Empty model/provider forced 🐞
Description
The notebooks backend query route always overwrites req.body.model/provider from config and defaults
missing config to empty strings, which violates the system's own non-empty model/provider
requirement and can cause all notebook queries to fail when queryDefaults are not configured.
Code

workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/notebooksRouters.ts[R411-414]

+      req.body.model = notebookModel;
+      req.body.provider = notebookProvider;
      req.body.vector_store_ids = [sessionId];
+      req.body.media_type = 'application/json';
Evidence
Router initialization sets notebookModel/notebookProvider to '' when config is absent, and the
query handler unconditionally assigns those to req.body.model and req.body.provider. Elsewhere
in the backend, validateCompletionsRequest enforces model/provider must be non-empty strings,
demonstrating empty strings are considered invalid in this system.

workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/notebooksRouters.ts[75-82]
workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/notebooksRouters.ts[411-414]
workspaces/lightspeed/plugins/lightspeed-backend/src/service/validation.ts[21-44]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Notebook query requests are forced to include `model` and `provider` values from config, but the code defaults them to empty strings and always overwrites the request body. This creates invalid requests when config is missing.

### Issue Context
The backend already treats empty `model`/`provider` as invalid (`validateCompletionsRequest`). Notebook queries should either:
- fail fast with a clear configuration error, or
- avoid setting these fields unless valid values are present.

### Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/notebooksRouters.ts[75-82]
- workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/notebooksRouters.ts[411-414]

### Suggested fix
- Change defaults to `undefined` (or use `config.getString(...)` and throw on startup if missing).
- In the handler, only assign `req.body.model/provider` when the configured value is a non-empty string; otherwise return `400/500` with a clear message indicating missing `lightspeed.aiNotebooks.queryDefaults.*`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. DOCX/ODT upload corrupted 🐞
Description
The frontend accepts .docx/.odt and maps them to fileType 'txt', but the backend only supports
parsing txt/md/log as UTF-8 text, so these binary formats will be ingested as garbage content.
Code

workspaces/lightspeed/plugins/lightspeed/src/const.ts[R40-62]

+export const NOTEBOOK_ALLOWED_EXTENSIONS: Record<string, string[]> = {
+  'text/plain': ['.txt', '.log'],
+  'text/markdown': ['.md'],
+  'application/pdf': ['.pdf'],
+  'application/json': ['.json'],
+  'application/x-yaml': ['.yaml', '.yml'],
+  'application/vnd.openxmlformats-officedocument.wordprocessingml.document': [
+    '.docx',
+  ],
+  'application/vnd.oasis.opendocument.text': ['.odt'],
+};
+
+export const NOTEBOOK_EXTENSION_TO_FILE_TYPE: Record<string, string> = {
+  '.txt': 'txt',
+  '.md': 'md',
+  '.pdf': 'pdf',
+  '.json': 'json',
+  '.yaml': 'yaml',
+  '.yml': 'yaml',
+  '.log': 'log',
+  '.docx': 'txt',
+  '.odt': 'txt',
+};
Evidence
UI allowlist includes .docx/.odt and the upload hook derives fileType from extension; both
.docx and .odt map to 'txt'. On the backend, supported file types do not include docx/odt, and
the text parser for txt/md/log is buffer.toString('utf-8'), which will misinterpret binary
documents.

workspaces/lightspeed/plugins/lightspeed/src/const.ts[40-62]
workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useUploadDocument.ts[34-52]
workspaces/lightspeed/plugins/lightspeed-backend/src/service/constant.ts[36-48]
workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/documents/fileParser.ts[41-59]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The UI currently allows `.docx`/`.odt` uploads and maps them to `fileType='txt'`, but the backend parses `txt` as UTF-8 text, corrupting binary document content.

### Issue Context
Backend supported types are `md/txt/pdf/json/yaml/yml/log/url` and text parsing is `buffer.toString('utf-8')`.

### Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed/src/const.ts[40-62]
- workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useUploadDocument.ts[34-52]
- workspaces/lightspeed/plugins/lightspeed-backend/src/service/constant.ts[36-48]
- workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/documents/fileParser.ts[41-59]

### Suggested fix
Choose one:
1) **Disallow docx/odt**: remove `.docx`/`.odt` from `NOTEBOOK_ALLOWED_EXTENSIONS` and `NOTEBOOK_EXTENSION_TO_FILE_TYPE`, and update the upload modal `infoText` translations accordingly.
2) **Add real backend support**: extend `SupportedFileType` and implement docx/odt parsing (e.g., extract text) instead of treating as plain UTF-8 text.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Upload size limit mismatch 🐞
Description
The frontend validates uploads up to 25MB, but the backend enforces a 20MB multer limit, causing
files between 20–25MB to pass UI validation and then fail server-side.
Code

workspaces/lightspeed/plugins/lightspeed/src/const.ts[R36-38]

+export const NOTEBOOK_MAX_FILES = 10;
+export const NOTEBOOK_MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024; // 25 MB
+export const UNTITLED_NOTEBOOK_NAME = 'Untitled Notebook';
Evidence
Frontend uses NOTEBOOK_MAX_FILE_SIZE_BYTES = 25MB for validation while the backend uses
DEFAULT_MAX_FILE_SIZE_MB = 20MB as the multer fileSize limit, so the client-side check is not
aligned with server enforcement.

workspaces/lightspeed/plugins/lightspeed/src/const.ts[36-38]
workspaces/lightspeed/plugins/lightspeed-backend/src/service/constant.ts[27-33]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Client-side validation allows 25MB uploads, but server rejects anything over 20MB.

### Issue Context
Backend multer limit is authoritative; UI should match it to prevent confusing failures.

### Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed/src/const.ts[36-38]
- workspaces/lightspeed/plugins/lightspeed-backend/src/service/constant.ts[27-33]

### Suggested fix
- Either lower `NOTEBOOK_MAX_FILE_SIZE_BYTES` to 20MB, or raise backend multer `DEFAULT_MAX_FILE_SIZE_MB` to 25MB.
- Ensure any user-facing copy (translations) reflects the chosen limit.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Overwrite blocked by max 🐞
Description
validateFiles() rejects uploads when existingCount + files.length exceeds NOTEBOOK_MAX_FILES even if
the files are duplicates that would be overwritten and not increase document count.
Code

workspaces/lightspeed/plugins/lightspeed/src/utils/notebook-upload-utils.ts[R49-59]

+export const validateFiles = (
+  files: File[],
+  existingCount: number = 0,
+): FileValidationResult => {
+  const errors: string[] = [];
+  const valid: File[] = [];
+
+  if (!validateFileCount(existingCount, files.length)) {
+    errors.push('notebook.upload.error.tooManyFiles');
+    return { valid: [], errors };
+  }
Evidence
The count check runs before duplicates are identified; AddDocumentModal passes
existingDocumentNames.length and only later partitions valid into new vs duplicate files. This
means overwriting a file in a full notebook is incorrectly blocked.

workspaces/lightspeed/plugins/lightspeed/src/utils/notebook-upload-utils.ts[49-59]
workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/AddDocumentModal.tsx[95-113]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The max-files validation counts all dropped files even if some are duplicates that would overwrite existing documents.

### Issue Context
`AddDocumentModal` determines duplicates after calling `validateFiles`, so `validateFiles` cannot currently account for overwrites.

### Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed/src/utils/notebook-upload-utils.ts[49-59]
- workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/AddDocumentModal.tsx[95-113]

### Suggested fix
- Move the file-count validation to after duplicate detection in `AddDocumentModal` and validate only `newFiles.length`, OR
- Extend `validateFiles` to accept existing names (or a duplicate predicate) so it can compute `netNewCount` and validate `existingCount + netNewCount`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Completed uploads never removed 🐞
Description
NotebookView removes failed/cancelled uploads from state but never removes completed uploads from
pendingUploads/uploadingFileNames, causing unbounded state growth and relying on indirect filtering
to hide completed entries.
Code

workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/NotebookView.tsx[R386-417]

+    for (const result of completedOrFailed) {
+      processedIds.current.add(result.documentId);
+      if (result.status !== 'completed') {
+        idsToRemove.add(result.documentId);
+        namesToRemove.add(result.fileName);
+      } else {
+        newCompletedNames.add(result.fileName);
+      }
+
+      if (result.status === 'completed') {
+        newAlerts.push({
+          key: Date.now() + result.documentId,
+          title: (t as Function)('notebook.upload.success', {
+            fileName: result.fileName,
+          }) as string,
+          variant: 'success',
+        });
+      } else {
+        newAlerts.push({
+          key: Date.now() + result.documentId,
+          title: (t as Function)('notebook.upload.failed', {
+            fileName: result.fileName,
+          }) as string,
+          variant: 'danger',
+        });
+      }
+    }
+
+    setPendingUploads(prev => prev.filter(u => !idsToRemove.has(u.documentId)));
+    setUploadingFileNames(prev =>
+      prev.filter(name => !namesToRemove.has(name)),
+    );
Evidence
In the polling effect, only non-completed results add entries to idsToRemove/namesToRemove, and
the state updates remove only those. Completed uploads are only added to completedFileNames,
leaving pendingUploads and uploadingFileNames to grow over time.

workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/NotebookView.tsx[369-417]
workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/NotebookView.tsx[431-431]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Successful uploads are never removed from `pendingUploads` / `uploadingFileNames`, which can grow without bound and can keep `hasDocuments` true even when documents are not present.

### Issue Context
The UI currently hides spinners via `completedFileNames`, but the underlying arrays still retain completed entries.

### Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed/src/components/notebooks/NotebookView.tsx[369-425]

### Suggested fix
- For `status === 'completed'`, also add `documentId` to `idsToRemove` and `fileName` to `namesToRemove`, then remove them from `pendingUploads`/`uploadingFileNames` just like failed/cancelled.
- Optionally clear `completedFileNames` entries once the document list refresh includes the uploaded document.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@sonarqubecloud
Copy link
Copy Markdown

Comment on lines +223 to +236
if (!response.ok) {
const reader = response.body.getReader();
const { done, value } = await reader.read();
const text = done ? '' : new TextDecoder('utf-8').decode(value);
const errorMessage = JSON.parse(text);
if (errorMessage?.error) {
throw new Error(
`failed to query notebook session: ${errorMessage.error}`,
);
}
}

return response.body.getReader();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Stream reader locked twice 🐞 Bug ≡ Correctness

NotebooksApiClient.querySession() calls response.body.getReader() in the error path and then calls
getReader() again to return a reader, which will throw because the stream is already locked and also
may let non-OK responses proceed without throwing.
Agent Prompt
### Issue description
`NotebooksApiClient.querySession()` locks the response stream by calling `response.body.getReader()` in the error branch and then calls `getReader()` again, which will throw at runtime. It also doesn't reliably throw for non-OK responses.

### Issue Context
This method is used for notebook chat streaming; failed requests should surface a clean error without breaking the stream API.

### Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed/src/api/NotebooksApiClient.ts[205-236]

### Suggested fix
- If `!response.ok`, read the error via `await response.text()` (or reuse a single reader and `releaseLock()`), then `throw` unconditionally.
- Only call `response.body.getReader()` once (in the success path) and return that reader.
- Wrap JSON parsing of error text in `try/catch` and fall back to raw text when not JSON.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +411 to +414
req.body.model = notebookModel;
req.body.provider = notebookProvider;
req.body.vector_store_ids = [sessionId];
req.body.media_type = 'application/json';
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Empty model/provider forced 🐞 Bug ≡ Correctness

The notebooks backend query route always overwrites req.body.model/provider from config and defaults
missing config to empty strings, which violates the system's own non-empty model/provider
requirement and can cause all notebook queries to fail when queryDefaults are not configured.
Agent Prompt
### Issue description
Notebook query requests are forced to include `model` and `provider` values from config, but the code defaults them to empty strings and always overwrites the request body. This creates invalid requests when config is missing.

### Issue Context
The backend already treats empty `model`/`provider` as invalid (`validateCompletionsRequest`). Notebook queries should either:
- fail fast with a clear configuration error, or
- avoid setting these fields unless valid values are present.

### Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/notebooksRouters.ts[75-82]
- workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/notebooksRouters.ts[411-414]

### Suggested fix
- Change defaults to `undefined` (or use `config.getString(...)` and throw on startup if missing).
- In the handler, only assign `req.body.model/provider` when the configured value is a non-empty string; otherwise return `400/500` with a clear message indicating missing `lightspeed.aiNotebooks.queryDefaults.*`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +40 to +62
export const NOTEBOOK_ALLOWED_EXTENSIONS: Record<string, string[]> = {
'text/plain': ['.txt', '.log'],
'text/markdown': ['.md'],
'application/pdf': ['.pdf'],
'application/json': ['.json'],
'application/x-yaml': ['.yaml', '.yml'],
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': [
'.docx',
],
'application/vnd.oasis.opendocument.text': ['.odt'],
};

export const NOTEBOOK_EXTENSION_TO_FILE_TYPE: Record<string, string> = {
'.txt': 'txt',
'.md': 'md',
'.pdf': 'pdf',
'.json': 'json',
'.yaml': 'yaml',
'.yml': 'yaml',
'.log': 'log',
'.docx': 'txt',
'.odt': 'txt',
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Docx/odt upload corrupted 🐞 Bug ≡ Correctness

The frontend accepts .docx/.odt and maps them to fileType 'txt', but the backend only supports
parsing txt/md/log as UTF-8 text, so these binary formats will be ingested as garbage content.
Agent Prompt
### Issue description
The UI currently allows `.docx`/`.odt` uploads and maps them to `fileType='txt'`, but the backend parses `txt` as UTF-8 text, corrupting binary document content.

### Issue Context
Backend supported types are `md/txt/pdf/json/yaml/yml/log/url` and text parsing is `buffer.toString('utf-8')`.

### Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed/src/const.ts[40-62]
- workspaces/lightspeed/plugins/lightspeed/src/hooks/notebooks/useUploadDocument.ts[34-52]
- workspaces/lightspeed/plugins/lightspeed-backend/src/service/constant.ts[36-48]
- workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/documents/fileParser.ts[41-59]

### Suggested fix
Choose one:
1) **Disallow docx/odt**: remove `.docx`/`.odt` from `NOTEBOOK_ALLOWED_EXTENSIONS` and `NOTEBOOK_EXTENSION_TO_FILE_TYPE`, and update the upload modal `infoText` translations accordingly.
2) **Add real backend support**: extend `SupportedFileType` and implement docx/odt parsing (e.g., extract text) instead of treating as plain UTF-8 text.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

config.getOptionalString(
'lightspeed.aiNotebooks.queryDefaults.provider_id',
) ?? '';

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JslYoon You were not reading the default models so I have added these code, let me know it looks good to you, or I can remove it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant