chore: remove specs
This commit is contained in:
parent
8219ccbc05
commit
6b5734c9cf
3 changed files with 0 additions and 565 deletions
|
|
@ -1,245 +0,0 @@
|
|||
# Feature: Chat Message Actions (Save to Note & Copy)
|
||||
|
||||
## Feature Description
|
||||
Add action buttons to AI messages in the notebook chat interface that allow users to:
|
||||
1. Save an AI response as a new note in the current notebook
|
||||
2. Copy the AI message content to clipboard
|
||||
|
||||
This feature replicates the functionality from the Streamlit app where users could click a "💾 New Note" button on AI messages. The new React implementation will provide a more modern, accessible interface with two key actions: saving messages as notes and copying message content.
|
||||
|
||||
## User Story
|
||||
As a notebook user
|
||||
I want to save valuable AI responses as notes and copy message content
|
||||
So that I can preserve important insights in my notebook for future reference and share content with others
|
||||
|
||||
## Problem Statement
|
||||
Currently in the React frontend, users can only read AI responses in the chat interface but cannot easily preserve them as permanent notes or share them. In the previous Streamlit version, users could click a button to save AI messages as notes, which was a valuable workflow for capturing insights. Users also need the ability to quickly copy message content for use in other applications.
|
||||
|
||||
## Solution Statement
|
||||
Add two action buttons to AI messages in the ChatPanel component:
|
||||
1. A "Save to Note" button that creates a new AI-type note with the message content
|
||||
2. A "Copy" button that copies the message content to the clipboard
|
||||
|
||||
These buttons will appear on hover/focus for AI messages, maintaining a clean interface while providing easy access to these actions. When a note is created, the notes list will automatically refresh to show the new note immediately.
|
||||
|
||||
## Relevant Files
|
||||
Use these files to implement the feature:
|
||||
|
||||
- **[frontend/src/components/source/ChatPanel.tsx](frontend/src/components/source/ChatPanel.tsx)** - Main chat panel component that renders messages. This is where we'll add the action buttons to AI messages.
|
||||
|
||||
- **[frontend/src/app/(dashboard)/notebooks/components/ChatColumn.tsx](frontend/src/app/(dashboard)/notebooks/components/ChatColumn.tsx)** - Notebook chat column wrapper that manages the notebook chat state. We'll need to pass the notebookId down for note creation.
|
||||
|
||||
- **[frontend/src/lib/hooks/useNotebookChat.ts](frontend/src/lib/hooks/useNotebookChat.ts)** - Hook that manages notebook chat state. We may need to add logic here to trigger note refreshes.
|
||||
|
||||
- **[frontend/src/lib/hooks/use-notes.ts](frontend/src/lib/hooks/use-notes.ts)** - Hook providing the `useCreateNote` mutation for creating notes. We'll use this existing functionality.
|
||||
|
||||
- **[frontend/src/lib/api/notes.ts](frontend/src/lib/api/notes.ts)** - Notes API client with `create` method that calls `POST /notes`.
|
||||
|
||||
- **[frontend/src/lib/types/api.ts](frontend/src/lib/types/api.ts)** - TypeScript type definitions including `CreateNoteRequest` and `NoteResponse`.
|
||||
|
||||
- **[frontend/src/app/(dashboard)/notebooks/components/NotesColumn.tsx](frontend/src/app/(dashboard)/notebooks/components/NotesColumn.tsx)** - Notes column component that displays the list of notes. This will automatically refresh when new notes are created due to React Query cache invalidation.
|
||||
|
||||
### New Files
|
||||
No new files need to be created. We'll enhance existing components with new functionality.
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: Foundation
|
||||
1. Review the existing ChatPanel component structure to understand message rendering
|
||||
2. Identify where AI message actions should be added in the component hierarchy
|
||||
3. Confirm the note creation API flow and data requirements
|
||||
4. Review clipboard API browser compatibility
|
||||
|
||||
### Phase 2: Core Implementation
|
||||
1. Create a new MessageActions component to render the action buttons
|
||||
2. Implement "Save to Note" functionality using the existing `useCreateNote` hook
|
||||
3. Implement "Copy to Clipboard" functionality using the Clipboard API
|
||||
4. Add proper error handling and user feedback (toasts)
|
||||
5. Style the action buttons to appear on hover/focus for a clean UX
|
||||
|
||||
### Phase 3: Integration
|
||||
1. Integrate MessageActions into ChatPanel's AI message rendering
|
||||
2. Pass necessary props (notebookId) through the component hierarchy
|
||||
3. Ensure notes list refreshes automatically after note creation via React Query cache invalidation
|
||||
4. Test the complete workflow end-to-end
|
||||
5. Handle edge cases (clipboard permissions, note creation failures, etc.)
|
||||
|
||||
## Step by Step Tasks
|
||||
|
||||
### Step 1: Create MessageActions Component
|
||||
- Create a new component file at `frontend/src/components/source/MessageActions.tsx`
|
||||
- Implement two buttons: "Save to Note" and "Copy"
|
||||
- Use lucide-react icons: `Save` for save to note, `Copy` for copy
|
||||
- Add hover/focus states for better UX
|
||||
- Make the component appear on message hover using CSS
|
||||
|
||||
### Step 2: Add Note Creation Functionality
|
||||
- Import and use `useCreateNote` hook from `use-notes.ts`
|
||||
- Implement `handleSaveToNote` function that:
|
||||
- Calls the create note mutation with the message content
|
||||
- Sets `note_type: "ai"`
|
||||
- Includes the `notebook_id` from props
|
||||
- Shows success toast on completion
|
||||
- Shows error toast on failure
|
||||
|
||||
### Step 3: Add Copy to Clipboard Functionality
|
||||
- Implement `handleCopyToClipboard` function using `navigator.clipboard.writeText()`
|
||||
- Add fallback for older browsers using `document.execCommand('copy')`
|
||||
- Show success toast: "Message copied to clipboard"
|
||||
- Show error toast if clipboard access fails
|
||||
- Handle clipboard permissions gracefully
|
||||
|
||||
### Step 4: Update ChatPanel to Support Actions
|
||||
- Modify the ChatPanel component to accept an optional `notebookId` prop
|
||||
- Pass `notebookId` to the AI message rendering section
|
||||
- Integrate MessageActions component into the AI message container
|
||||
- Position the action buttons appropriately (top-right corner of message bubble)
|
||||
- Ensure actions only appear for AI messages, not human messages
|
||||
|
||||
### Step 5: Update ChatColumn to Pass NotebookId
|
||||
- Modify `ChatColumn.tsx` to pass `notebookId` prop to `ChatPanel`
|
||||
- Verify the prop is correctly threaded through the component hierarchy
|
||||
|
||||
### Step 6: Handle Thinking Content
|
||||
- Review how thinking content is parsed and displayed (based on Streamlit implementation)
|
||||
- Ensure the "Save to Note" action saves the full message content including thinking blocks
|
||||
- Ensure the "Copy" action copies the full content including thinking blocks
|
||||
|
||||
### Step 7: Add Loading States
|
||||
- Add loading state to "Save to Note" button while note creation is in progress
|
||||
- Disable both buttons during note creation to prevent duplicate submissions
|
||||
- Show spinner icon during loading
|
||||
|
||||
### Step 8: Test Edge Cases
|
||||
- Test with messages containing markdown formatting
|
||||
- Test with messages containing source references
|
||||
- Test with very long messages
|
||||
- Test with messages containing thinking content
|
||||
- Test clipboard functionality in different browsers
|
||||
- Test note creation failure scenarios
|
||||
- Test when notebook_id is not provided (graceful degradation)
|
||||
|
||||
### Step 9: Verify Cache Invalidation
|
||||
- Confirm that creating a note automatically refreshes the notes list
|
||||
- Verify that the new note appears immediately in the NotesColumn
|
||||
- Test that React Query's cache invalidation is working correctly
|
||||
- Ensure no manual page refresh is needed
|
||||
|
||||
### Step 10: Run Validation Commands
|
||||
- Execute all validation commands listed in the "Validation Commands" section
|
||||
- Fix any issues or regressions discovered
|
||||
- Verify zero test failures
|
||||
- Ensure the feature works correctly in development and production builds
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
- Test MessageActions component in isolation
|
||||
- Test save to note button triggers correct API call
|
||||
- Test copy button calls clipboard API
|
||||
- Test loading states during async operations
|
||||
- Test error handling for failed operations
|
||||
- Test that buttons are only rendered for AI messages
|
||||
|
||||
### Integration Tests
|
||||
- Test the complete flow from chat message to saved note
|
||||
- Send a message in notebook chat
|
||||
- Click "Save to Note" on AI response
|
||||
- Verify note appears in notes list
|
||||
- Verify note has correct content and type ("ai")
|
||||
- Test clipboard functionality
|
||||
- Click "Copy" button
|
||||
- Verify content is in clipboard
|
||||
- Verify success toast appears
|
||||
|
||||
### Edge Cases
|
||||
- Message with markdown formatting (verify formatting is preserved in note)
|
||||
- Message with source references (verify references are preserved)
|
||||
- Very long messages (verify full content is saved/copied)
|
||||
- Messages with thinking content (verify thinking blocks are included)
|
||||
- Clipboard permission denied (verify graceful error handling)
|
||||
- Note creation API failure (verify error toast and no crash)
|
||||
- Missing notebookId prop (verify graceful degradation)
|
||||
- Multiple rapid clicks on save button (verify only one note is created)
|
||||
- Network timeout during note creation (verify appropriate error message)
|
||||
|
||||
## Acceptance Criteria
|
||||
1. ✅ AI messages in notebook chat display two action buttons on hover: "Save to Note" and "Copy"
|
||||
2. ✅ Clicking "Save to Note" creates a new AI-type note with the message content
|
||||
3. ✅ The newly created note appears immediately in the NotesColumn without requiring a page refresh
|
||||
4. ✅ Clicking "Copy" copies the message content to the clipboard
|
||||
5. ✅ Success toasts appear when actions complete successfully
|
||||
6. ✅ Error toasts appear when actions fail with helpful error messages
|
||||
7. ✅ Buttons show loading states during async operations
|
||||
8. ✅ Full message content (including thinking blocks) is saved/copied
|
||||
9. ✅ Markdown formatting and source references are preserved
|
||||
10. ✅ Action buttons only appear on AI messages, not human messages
|
||||
11. ✅ The feature works in all major browsers (Chrome, Firefox, Safari, Edge)
|
||||
12. ✅ No regressions in existing chat functionality
|
||||
|
||||
## Validation Commands
|
||||
Execute every command to validate the feature works correctly with zero regressions.
|
||||
|
||||
### Frontend Commands
|
||||
- `cd frontend && npm run build` - Verify frontend builds without errors
|
||||
- `cd frontend && npm run typecheck` - Ensure no TypeScript errors (if type checking is configured)
|
||||
- `cd frontend && npm run lint` - Verify code follows linting standards (if linting is configured)
|
||||
|
||||
### Backend Commands (ensure no regressions)
|
||||
- `cd /Users/luisnovo/dev/projetos/open-notebook/open-notebook && uv run python -m pytest tests/ -v` - Run all backend tests to ensure no API regressions
|
||||
|
||||
### Manual Testing Steps
|
||||
1. Start the development environment:
|
||||
- `make database` - Start SurrealDB
|
||||
- `make api` - Start FastAPI backend
|
||||
- `cd frontend && npm run dev` - Start Next.js frontend
|
||||
2. Navigate to a notebook page
|
||||
3. Send a message in the chat
|
||||
4. Hover over the AI response message
|
||||
5. Verify both "Save to Note" and "Copy" buttons appear
|
||||
6. Click "Save to Note" and verify:
|
||||
- Loading state appears briefly
|
||||
- Success toast shows "Note created successfully"
|
||||
- New note appears in the Notes column
|
||||
- Note contains the AI message content
|
||||
- Note is marked as "AI Generated"
|
||||
7. Click "Copy" and verify:
|
||||
- Success toast shows "Message copied to clipboard"
|
||||
- Paste in another application to confirm content was copied
|
||||
8. Test with various message types (markdown, with references, long messages)
|
||||
9. Test error scenarios (disconnect network and try to save)
|
||||
10. Verify existing chat functionality still works (sending messages, sessions, etc.)
|
||||
|
||||
## Clarification Needed
|
||||
None at this time. The requirements are clear based on the existing Streamlit implementation and the codebase structure.
|
||||
|
||||
## Notes
|
||||
|
||||
### Implementation Details
|
||||
- The note creation API (`POST /notes`) already handles auto-generating titles for AI notes, so we don't need to provide a title when creating notes from chat messages
|
||||
- React Query automatically invalidates the notes cache when a new note is created (via `useCreateNote` hook), so the NotesColumn will refresh automatically
|
||||
- The existing `useCreateNote` hook already shows success/error toasts, so we get that functionality for free
|
||||
|
||||
### Browser Compatibility
|
||||
- The Clipboard API (`navigator.clipboard.writeText()`) is supported in all modern browsers
|
||||
- We should include a fallback using `document.execCommand('copy')` for older browsers
|
||||
- Consider checking for clipboard permissions before attempting to copy
|
||||
|
||||
### Future Enhancements
|
||||
- Add keyboard shortcuts (e.g., Cmd/Ctrl + S to save message to note)
|
||||
- Add option to edit the note title before saving
|
||||
- Add option to select which notebook to save to (for multi-notebook scenarios)
|
||||
- Add "Share" button to share message via native share API
|
||||
- Add "Regenerate" button to re-run the query with the same context
|
||||
|
||||
### Design Considerations
|
||||
- Action buttons should be subtle and only appear on hover to maintain clean UI
|
||||
- Use consistent iconography with the rest of the application
|
||||
- Ensure buttons are accessible (keyboard navigation, screen readers)
|
||||
- Consider mobile UX where hover states don't exist (show buttons always on mobile)
|
||||
|
||||
### Performance Considerations
|
||||
- Note creation should be fast (< 1 second in most cases due to title generation)
|
||||
- Show loading states immediately on button click for user feedback
|
||||
- Clipboard operations are synchronous and very fast (< 100ms)
|
||||
- React Query's cache invalidation is efficient and won't cause unnecessary re-renders
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
# Bug: Notebook Chat Context Not Being Sent to API
|
||||
|
||||
## Bug Description
|
||||
The notebook chat functionality in the React frontend is failing to send proper context to the LLM. When users toggle sources/notes to include them in chat context (shown by blue icons and "1 full" indicator), the AI agent does not recognize the context and responds as if no context was provided. The context selection UI works correctly (showing selections), but the actual content is not being passed to the API endpoint.
|
||||
|
||||
**Symptoms:**
|
||||
- Context toggle UI shows correct selections (blue icons)
|
||||
- Context indicator displays "1 full" or similar status
|
||||
- AI agent responds without knowledge of the selected context
|
||||
- No errors in console or API logs
|
||||
|
||||
**Expected Behavior:**
|
||||
- Selected sources/notes should be sent to the API with their actual content
|
||||
- API should use "insights" or "full content" from the sources/notes based on selection mode
|
||||
- AI agent should have access to the context and respond accordingly
|
||||
- Context indicator should show token/character counts
|
||||
|
||||
**Actual Behavior:**
|
||||
- Context is sent to API but with literal strings "insights" or "full content" instead of actual data
|
||||
- AI agent receives no actual content to work with
|
||||
- Token/character counts are not displayed
|
||||
|
||||
## Problem Statement
|
||||
The `buildContext` function in [useNotebookChat.ts](frontend/src/lib/hooks/useNotebookChat.ts:123-147) is building context objects with literal string values ("insights", "full content") instead of actually retrieving the content from the sources and notes. The API endpoint expects a format similar to what the Streamlit implementation uses, where the context contains actual content data that can be processed.
|
||||
|
||||
## Solution Statement
|
||||
Modify the frontend to match the Streamlit implementation's two-step approach:
|
||||
1. **Step 1**: Send context configuration (source/note IDs + their selection modes) to `/chat/context` endpoint
|
||||
2. **Step 2**: Use the returned context object (containing actual fetched content + metadata) when calling `/chat/execute`
|
||||
3. **Step 3**: Display token/character counts from the context response in a compact, informative UI
|
||||
|
||||
Currently, the React frontend skips both steps and sends literal placeholder strings directly to `/chat/execute`, which is why the AI has no actual content to work with.
|
||||
|
||||
## Steps to Reproduce
|
||||
1. Open a notebook in the React frontend at `/notebooks/[id]`
|
||||
2. Add at least one source or note to the notebook
|
||||
3. Toggle the context selection for a source/note to "full" (blue icon)
|
||||
4. Observe the context indicator shows "1 full" or similar but no token/char counts
|
||||
5. Send a message in the chat asking about the content
|
||||
6. Observe: AI responds without knowledge of the content
|
||||
|
||||
## Root Cause Analysis
|
||||
The bug occurs in [useNotebookChat.ts:123-147](frontend/src/lib/hooks/useNotebookChat.ts:123-147) where the `buildContext` function creates a context object with literal strings:
|
||||
|
||||
```typescript
|
||||
return {
|
||||
sources: sources
|
||||
.filter(source => {
|
||||
const mode = contextSelections.sources[source.id]
|
||||
return mode && mode !== 'off'
|
||||
})
|
||||
.map(source => {
|
||||
const mode = contextSelections.sources[source.id]
|
||||
return {
|
||||
id: source.id,
|
||||
content: mode === 'insights' ? 'insights' : 'full content' // ❌ LITERAL STRINGS
|
||||
}
|
||||
}),
|
||||
notes: notes
|
||||
.filter(note => {
|
||||
const mode = contextSelections.notes[note.id]
|
||||
return mode && mode !== 'off'
|
||||
})
|
||||
.map(note => ({
|
||||
id: note.id,
|
||||
content: 'full content' // ❌ LITERAL STRING
|
||||
}))
|
||||
}
|
||||
```
|
||||
|
||||
**Why this is wrong:**
|
||||
|
||||
1. **The `/chat/execute` endpoint needs actual content**: The API expects `request.context` to contain the actual fetched content from sources/notes, which gets injected into the LLM prompt template at [prompts/chat.jinja:17-22](prompts/chat.jinja:17-22)
|
||||
|
||||
2. **The correct flow** (from Streamlit [pages/stream_app/chat.py:22-61](pages/stream_app/chat.py:22-61)):
|
||||
- Build `context_config`: Map source/note IDs → status strings ("insights", "full content", "not in")
|
||||
- Call `/chat/context` with notebook_id + context_config → Get back actual content + token/char counts
|
||||
- Call `/chat/execute` with the actual content context
|
||||
|
||||
3. **The `/chat/context` endpoint** ([api/routers/chat.py:391-496](api/routers/chat.py:391-496)) does the heavy lifting:
|
||||
- Takes source/note IDs and their modes as input
|
||||
- Fetches actual Source and Note objects from database
|
||||
- Calls `source.get_context(context_size="short"/"long")` based on mode
|
||||
- Calls `note.get_context(context_size="long")`
|
||||
- Returns structured context with **actual text content + token_count + char_count**
|
||||
|
||||
**The React frontend is bypassing the `/chat/context` endpoint entirely and sending placeholder strings like "insights" and "full content" directly to `/chat/execute`, so the LLM receives literal strings instead of actual document content.**
|
||||
|
||||
## Relevant Files
|
||||
|
||||
### Files to Modify
|
||||
|
||||
- **[frontend/src/lib/hooks/useNotebookChat.ts:123-147](frontend/src/lib/hooks/useNotebookChat.ts:123-147)** - Contains the broken `buildContext` function that needs to be completely rewritten to use the API's `/chat/context` endpoint
|
||||
|
||||
- **[frontend/src/lib/api/chat.ts:62-68](frontend/src/lib/api/chat.ts:62-68)** - Already has `buildContext` API function, needs to be used by the hook
|
||||
|
||||
- **[frontend/src/lib/types/api.ts:208-223](frontend/src/lib/types/api.ts:208-223)** - Type definitions for `BuildContextRequest` and `BuildContextResponse` need to be verified/updated to match backend expectations
|
||||
|
||||
- **[frontend/src/components/common/ContextIndicator.tsx](frontend/src/components/common/ContextIndicator.tsx)** - Context indicator component needs to be enhanced to show token/char counts with a more compact layout
|
||||
|
||||
- **[frontend/src/app/(dashboard)/notebooks/components/ChatColumn.tsx](frontend/src/app/(dashboard)/notebooks/components/ChatColumn.tsx)** - Needs to pass token/char counts from the hook to the ContextIndicator component
|
||||
|
||||
### Files for Reference (No Changes)
|
||||
|
||||
- **[pages/stream_app/chat.py:22-47](pages/stream_app/chat.py:22-47)** - Working Streamlit implementation showing correct approach
|
||||
- **[api/routers/chat.py:391-496](api/routers/chat.py:391-496)** - Backend `/chat/context` endpoint implementation
|
||||
- **[api/chat_service.py:150-168](api/chat_service.py:150-168)** - Streamlit's service layer showing correct API usage
|
||||
|
||||
## Step by Step Tasks
|
||||
|
||||
### Step 1: Update Type Definitions
|
||||
Verify and update the context-related type definitions to match the backend's expectations:
|
||||
|
||||
- Review [frontend/src/lib/types/api.ts:208-223](frontend/src/lib/types/api.ts:208-223)
|
||||
- Ensure `BuildContextRequest.context_config` structure matches what the backend expects:
|
||||
```typescript
|
||||
context_config: {
|
||||
sources: Record<string, string> // id -> mode ("insights" | "full content" | "not in")
|
||||
notes: Record<string, string> // id -> mode ("full content" | "not in")
|
||||
}
|
||||
```
|
||||
- Update `SendNotebookChatMessageRequest.context` to accept the full context response from `/chat/context`, not just the simple structure
|
||||
|
||||
### Step 2: Rewrite buildContext in useNotebookChat Hook
|
||||
Replace the client-side context building with API-based context building:
|
||||
|
||||
- Modify [frontend/src/lib/hooks/useNotebookChat.ts:123-147](frontend/src/lib/hooks/useNotebookChat.ts:123-147)
|
||||
- Create a new async `buildContext` function that:
|
||||
1. Constructs `context_config` from `contextSelections` state
|
||||
2. Calls `chatApi.buildContext()` with notebook_id and context_config
|
||||
3. Returns the full context response with actual content + token_count + char_count
|
||||
- Update the function signature from synchronous to async
|
||||
- Keep the filtering logic (mode !== 'off') but map to proper status strings
|
||||
- Store token_count and char_count in component state
|
||||
|
||||
### Step 3: Update sendMessage to Use Async Context Building
|
||||
Modify the sendMessage function to await context building:
|
||||
|
||||
- Update [frontend/src/lib/hooks/useNotebookChat.ts:150-214](frontend/src/lib/hooks/useNotebookChat.ts:150-214)
|
||||
- Change `const context = buildContext()` to `const contextResponse = await buildContext()`
|
||||
- Extract `context`, `token_count`, and `char_count` from the response
|
||||
- Handle any errors from context building
|
||||
- Ensure the context from the API is passed correctly to `chatApi.sendMessage()`
|
||||
|
||||
### Step 4: Update SendNotebookChatMessageRequest Type
|
||||
Update the message request type to accept full context:
|
||||
|
||||
- Modify [frontend/src/lib/types/api.ts:198-206](frontend/src/lib/types/api.ts:198-206)
|
||||
- Change the `context` field to match what `/chat/context` returns:
|
||||
```typescript
|
||||
context: {
|
||||
sources: Array<Record<string, unknown>>
|
||||
notes: Array<Record<string, unknown>>
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Update ContextIndicator to Show Token/Char Counts
|
||||
Enhance the context indicator UI to display token and character counts:
|
||||
|
||||
- Modify [frontend/src/components/common/ContextIndicator.tsx](frontend/src/components/common/ContextIndicator.tsx)
|
||||
- Update the component props to accept `tokenCount` and `charCount`
|
||||
- Redesign the layout to be more compact:
|
||||
- Show just numbers next to each icon (e.g., "📄 2" instead of "2 sources")
|
||||
- Move insights/full badges inline with numbers
|
||||
- Add token/char count display to the right side
|
||||
- Format as: "Context: 📄 2 (1 insights, 1 full) • 📝 1 • 1.2K tokens / 5K chars"
|
||||
- Create a helper function to format large numbers (1234 → "1.2K", 1234567 → "1.2M")
|
||||
- Ensure responsive layout that doesn't wrap awkwardly
|
||||
|
||||
### Step 6: Update useNotebookChat to Store and Return Token/Char Counts
|
||||
Store the context metadata from the API response:
|
||||
|
||||
- Modify [frontend/src/lib/hooks/useNotebookChat.ts](frontend/src/lib/hooks/useNotebookChat.ts)
|
||||
- Add state to store `tokenCount` and `charCount` from `/chat/context` response
|
||||
- Update `buildContext` function to store these values when called
|
||||
- Return them from the hook so `ChatColumn` can pass to `ContextIndicator`
|
||||
- Update every time context selections change (via useEffect watching contextSelections)
|
||||
|
||||
### Step 7: Update ChatColumn to Pass Counts to ContextIndicator
|
||||
Connect the token/char counts to the UI:
|
||||
|
||||
- Modify [frontend/src/app/(dashboard)/notebooks/components/ChatColumn.tsx](frontend/src/app/(dashboard)/notebooks/components/ChatColumn.tsx)
|
||||
- Get `tokenCount` and `charCount` from the `useNotebookChat` hook
|
||||
- Pass these values to `ChatPanel` via `notebookContextStats`
|
||||
- Update the `NotebookContextStats` interface in [ChatPanel.tsx](frontend/src/components/source/ChatPanel.tsx) to include these fields
|
||||
|
||||
### Step 8: Verify API Integration
|
||||
Ensure the frontend correctly communicates with both API endpoints:
|
||||
|
||||
- Verify [frontend/src/lib/api/chat.ts:62-68](frontend/src/lib/api/chat.ts:62-68) `buildContext` function
|
||||
- Verify [frontend/src/lib/api/chat.ts:51-60](frontend/src/lib/api/chat.ts:51-60) `sendMessage` function
|
||||
- Ensure both functions handle the updated types correctly
|
||||
|
||||
### Step 9: Test the Fix
|
||||
Manually test the complete flow:
|
||||
|
||||
- Start the backend API server
|
||||
- Start the frontend development server
|
||||
- Create/open a notebook with sources and notes
|
||||
- Toggle context selections (off/insights/full)
|
||||
- Verify context indicator shows:
|
||||
- Correct counts with compact format (numbers next to icons)
|
||||
- Token and character counts on the right side
|
||||
- Updates in real-time as selections change
|
||||
- Send chat messages and verify AI receives proper context
|
||||
- Verify different context modes (insights vs full) work correctly
|
||||
|
||||
### Step 10: Run Validation Commands
|
||||
Execute all validation commands to ensure no regressions:
|
||||
|
||||
- Run TypeScript type checking
|
||||
- Run the build process
|
||||
- Test the complete user flow
|
||||
|
||||
## Validation Commands
|
||||
Execute every command to validate the bug is fixed with zero regressions.
|
||||
|
||||
- `cd frontend && npx tsc --noEmit` - Run TypeScript type checking to catch any type errors
|
||||
- `cd frontend && npm run build` - Build the frontend to ensure no build errors
|
||||
- Manual testing steps:
|
||||
1. Start backend: `make api` (or `uv run run_api.py`)
|
||||
2. Start frontend: `cd frontend && npm run dev`
|
||||
3. Open browser to `http://localhost:3000/notebooks/[test-notebook-id]`
|
||||
4. Add a test source and note
|
||||
5. Toggle source to "full" mode (blue icon)
|
||||
6. Verify context indicator shows:
|
||||
- Compact format: "📄 1 (1 full)" with token/char counts on right
|
||||
- Token count (e.g., "1.2K tokens")
|
||||
- Character count (e.g., "5K chars")
|
||||
7. Send message: "What does this source say?"
|
||||
8. Verify AI responds with content-aware answer (not "I don't have context")
|
||||
9. Toggle source to "insights" mode
|
||||
10. Verify context indicator updates to show "📄 1 (1 insights)"
|
||||
11. Send another message and verify AI uses insights-only context
|
||||
12. Toggle to "off" mode and verify AI says no context is available
|
||||
|
||||
## Notes
|
||||
|
||||
**Key Implementation Details:**
|
||||
|
||||
1. **Context Config Format**: The backend expects strings like "insights", "full content", "not in" as values in the context_config map. These are used as filters/indicators by the backend, not as actual content.
|
||||
|
||||
2. **API Flow**: The correct flow is:
|
||||
- Frontend builds `context_config` from user selections
|
||||
- Frontend calls `/chat/context` with config
|
||||
- Backend returns actual content + token_count + char_count based on config
|
||||
- Frontend uses returned context in `/chat/execute`
|
||||
- Frontend displays token/char counts in context indicator
|
||||
|
||||
3. **Streamlit Reference**: The working implementation is in [pages/stream_app/chat.py:22-47](pages/stream_app/chat.py:22-47) - use this as the gold standard for behavior.
|
||||
|
||||
4. **No New Dependencies**: This fix requires no new libraries or dependencies.
|
||||
|
||||
5. **Backward Compatibility**: The API endpoints haven't changed, so this fix maintains compatibility with the Streamlit frontend.
|
||||
|
||||
6. **Context Modes**:
|
||||
- Sources: "off" | "insights" | "full"
|
||||
- Notes: "off" | "full"
|
||||
- Backend API uses these exact strings in conditionals
|
||||
|
||||
7. **Error Handling**: Add proper error handling for the async buildContext call - if context building fails, show a user-friendly error and don't send the message.
|
||||
|
||||
8. **UI Enhancement - Context Indicator**:
|
||||
- The context indicator should show a more compact format to save space
|
||||
- Current format: "1 source", "1 full", "1 note" takes up too much space
|
||||
- New format: Show just numbers next to icons (📄 2, 💡 1, 📝 1)
|
||||
- Add token/char counts on the right: "1.2K tokens / 5K chars"
|
||||
- This gives a cleaner, more informative display
|
||||
- The `/chat/context` endpoint already returns `token_count` and `char_count` - just need to display them
|
||||
- Format large numbers with K/M suffixes (1234 → "1.2K", 1234567 → "1.2M")
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
# Chore: Remove Insights Count from Details Tab
|
||||
|
||||
## Chore Description
|
||||
In the source detail page under the frontend app, there are 3 tabs for source information: Content, Insights, and Details. The Details tab currently displays an "Insights" count in its Statistics section, which is redundant since the Insights tab already shows the count in its tab trigger (e.g., "Insights (1)"). This chore removes the redundant insights count display from the Details tab to avoid duplication and improve UI clarity.
|
||||
|
||||
## Relevant Files
|
||||
Use these files to resolve the chore:
|
||||
|
||||
- **`frontend/src/components/source/SourceDetailContent.tsx`** (lines 710-716)
|
||||
- This is the main component that renders the source detail page with tabs
|
||||
- Contains the Details tab with the Statistics section showing the redundant insights count
|
||||
- Need to remove the insights count row from the Statistics section while keeping the "Embedded" status
|
||||
|
||||
## Step by Step Tasks
|
||||
IMPORTANT: Execute every step in order, top to bottom.
|
||||
|
||||
### Step 1: Remove Insights Count from Statistics Section
|
||||
- Open `frontend/src/components/source/SourceDetailContent.tsx`
|
||||
- Locate the Statistics section in the Details tab (lines 697-718)
|
||||
- Remove the insights count display (lines 710-716) which shows:
|
||||
```tsx
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<FileText className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-sm">Insights</span>
|
||||
</div>
|
||||
<span className="font-semibold">{source.insights_count || 0}</span>
|
||||
</div>
|
||||
```
|
||||
- Keep the "Embedded" status display (lines 700-709) intact
|
||||
- Ensure proper formatting and spacing after removal
|
||||
|
||||
### Step 2: Verify the Change
|
||||
- Run the development server with `cd frontend && npm run dev`
|
||||
- Navigate to a source detail page
|
||||
- Verify that:
|
||||
- The Details tab no longer shows the "Insights" count in the Statistics section
|
||||
- The "Embedded" status is still displayed correctly
|
||||
- The Insights tab still shows the count in its tab trigger (e.g., "Insights (1)")
|
||||
- All three tabs (Content, Insights, Details) render properly
|
||||
|
||||
## Validation Commands
|
||||
Execute every command to validate the chore is complete with zero regressions.
|
||||
|
||||
- `cd frontend && npm run build` - Ensure the frontend builds successfully without TypeScript or build errors
|
||||
|
||||
## Notes
|
||||
- The `FileText` icon import on line 34 can remain as it may be used elsewhere in the component
|
||||
- The `source.insights_count` property is still used in the Insights tab trigger (line 410), so we're only removing the duplicate display from the Details tab
|
||||
- This change improves UI consistency by having the insights count displayed only once (in the Insights tab trigger)
|
||||
Loading…
Reference in a new issue