Commit Graph

3032 Commits

Author SHA1 Message Date
spencrmartin acea40314d Implement per-tab sidecars with resizing and original styling
- Added TabSidecar component with proper drop shadow, rounded corners, and border styling
- Implemented ResizableSplitter for sidecar resizing functionality (30-80% width range)
- Added view mode toggle for diff viewers (split/unified)
- Extended TabContext with sidecar management functions (showDiffViewer, showLocalhostViewer, etc.)
- Created TabSidecarInvoker to replace global SidecarInvoker
- Updated TabbedChatContainer to use ResizableSplitter with floatingRight styling
- Removed global sidecar dependencies from BaseChat2
- Each tab now maintains independent sidecar state and content
2025-11-20 13:55:31 -05:00
spencrmartin e55cd174e0 Fix popover zone to not push app icons up
- Changed popover zone from flex layout to absolute positioning
- Zone now positioned at -top-24 (96px above chat input)
- No longer affects the layout flow or pushes bottom controls up
- Popover still renders in dedicated space above chat input
2025-11-20 13:37:22 -05:00
spencrmartin b806d52278 Move mention popover zone to be directly above chat input
- Removed popover zone from TabbedChatContainer (was too high up)
- Added popover zone directly above chat input in ChatInput component
- Zone positioned right before the chat input container for proper placement
- Height set to h-24 (96px) with same styling and portal target
- Popover should now appear directly above the input area where user is typing
2025-11-20 13:33:03 -05:00
spencrmartin 450ed5317e Improve mention popover positioning within dedicated zone
- Changed popover zone height from h-16 to h-32 for more space
- Position popover at bottom of zone (bottom: 8px) instead of center
- Popover now appears closer to chat input while still being above it
- Only center horizontally, not vertically, for better UX
2025-11-20 13:31:35 -05:00
spencrmartin 0a8e81a683 Create dedicated popover zone above chat for mention popover
- Added mention-popover-zone div in TabbedChatContainer above the chat area
- Zone has fixed height (h-16) and high z-index (z-50) for proper layering
- Updated EnhancedMentionPopover to use React portal to render in this zone
- Popover now renders absolutely positioned within the dedicated zone
- Should appear above chat content in the reserved space
2025-11-20 13:30:32 -05:00
spencrmartin df513dfd98 Move mention popover to very top of screen for maximum visibility
- Changed from percentage-based to fixed pixel positioning
- Popover now appears at top: 50px from the very top of screen
- Should be clearly visible at the top of the window
- Horizontally centered for easy access
2025-11-20 13:28:58 -05:00
spencrmartin 3915c76a5f Position mention popover in upper center of screen for better visibility
- Changed from relative positioning to fixed center positioning
- Popover now appears at 50% left, 20% top with horizontal centering
- Should be clearly visible in upper portion of screen
- No longer dependent on chat input position calculations
2025-11-20 13:28:04 -05:00
spencrmartin 20493d5faa Fix mention popover positioning to appear above chat input
- Changed positioning logic to use chatInputRef instead of bottomControlsRef
- Popover now positioned relative to the chat input container
- Should appear above the input area instead of at bottom of screen
- Updated position calculations to use chatInputRect.left and chatInputRect.top
2025-11-20 13:27:14 -05:00
spencrmartin f0c4dc6140 Set mention popover transform to translate(0) for explicit positioning 2025-11-20 13:25:37 -05:00
spencrmartin 3f5276e2e0 Fix mention popover positioning to be absolutely visible
- Remove transform translateY(-100%) for more predictable positioning
- Position popover at fixed coordinates well above input area
- Add Math.max() to prevent off-screen positioning
- Add debug logging to trace popover render state
- Should now be visible when typing @ in chat input
2025-11-20 13:24:59 -05:00
spencrmartin 187d54e93e Implement proper goose on/off state management
- Add gooseEnabled state that persists until explicitly changed
- @goose off now disables all AI responses until @goose is typed
- @goose or @goose on re-enables the AI
- When goose is off, all messages are recorded but no AI responses generated
- Improved command detection with exact matching
- Added detailed logging for goose state changes
2025-11-20 13:24:06 -05:00
spencrmartin 7214fbefef Add debugging for ChatInput onChange to trace mention popover issue
- Added console logs to track when ChatInput onChange is called
- Added logs to show cursorPos value and whether checkForMention is called
- Should help identify why mention popover isn't appearing when typing @
2025-11-20 13:19:59 -05:00
spencrmartin 4455895fb3 Add goose command and mention filtering to prevent AI responses
- Added checkForGooseCommands function to detect @goose commands and user mentions
- Prevents AI from responding to @goose off, @goose stop, @goose quiet, etc.
- Prevents AI from responding to Matrix user mentions (@user:domain.com)
- Prevents AI from responding to simple @username mentions
- Messages are still added to chat history but don't trigger AI response
- Maintains chat continuity while respecting mention/command semantics
2025-11-20 13:18:46 -05:00
spencrmartin 23a716ad9a Add debugging for mention popover positioning and state
- Added detailed console logging for checkForMention function
- Log bottomControlsRect dimensions and positioning
- Log mention popover state changes
- Should help identify why @ functionality isn't showing popovers
2025-11-20 13:17:44 -05:00
spencrmartin ab04620983 Position mention popover above bottom controls area (app icons)
- Added bottomControlsRef to reference the secondary actions row
- Updated checkForMention to use bottomControlsRect instead of textAreaRect
- Popover now appears above the app icons area (Actions, Attach, etc.)
- Uses transform: translateY(-100%) to position above the controls
- Maintains existing functionality while improving visual positioning
2025-11-20 13:11:39 -05:00
spencrmartin bd94846362 Fix mention popover positioning by using RichChatInput's getBoundingClientRect method
- Updated checkForMention to use textAreaRef.current?.getBoundingClientRect()
- This uses the RichChatInput component's exposed getBoundingClientRect method
- Should properly position the popover above the input field
- Removed fallback to contentRef which was causing positioning issues
2025-11-20 13:09:53 -05:00
spencrmartin 043ed29ff2 Add debugging for @ mention functionality
- Added detailed console logging to checkForMention function
- Improved error handling for getBoundingClientRect calls
- Added fallback for textArea positioning
- This will help identify if @ functionality is working properly
2025-11-20 13:07:55 -05:00
spencrmartin f749c35624 Fix Matrix integration in tabbed chat
- Modified BaseChat2 append function to dispatch matrix-message-received events
- Added event listener in useChatStream to handle Matrix messages
- Matrix messages now properly integrate into the chat message stream
- Fixed 'text.trim is not a function' error handling in TabContext
- Improved Matrix message processing and display in tabbed interface
2025-11-20 13:06:04 -05:00
spencrmartin bd975f691d Fix 'text.trim is not a function' error for Matrix messages
- Add type checking in updateTabTitleFromMessage function
- Handle Matrix message objects that may not be strings
- Extract text from message.text, message.content, or message.body
- Fallback to String() conversion for any other message types
- Prevents crash when Matrix users send non-string message objects
2025-11-20 12:51:36 -05:00
spencrmartin 30dc47595d Show close button only on active tab
- Remove close button from inactive tabs to save space
- Only active tab shows the X close button
- Inactive tabs no longer reserve space for close button
- Cleaner, more focused tab bar design
2025-11-20 12:37:06 -05:00
spencrmartin b6522aeee7 Change goose avatar from line to dot in BaseChat2
- Update GooseMessage component avatar from horizontal line to circular dot
- Changed from w-4 h-0.5 (line) to w-2 h-2 (dot) with rounded-full
- Provides a more subtle and clean avatar appearance
2025-11-20 12:34:12 -05:00
spencrmartin acd3473909 Fix React component remounting issue in tabbed chat
- Change BaseChat2 key from sessionId to stable tab.id
- Prevents component remounting when session ID changes from temporary to real
- Maintains chat state and messages when new sessions are created
- Messages now persist correctly when sending first message in new tab

The issue was that using sessionId as the React key caused the component
to unmount and remount when the backend assigned a real session ID,
clearing all state. Using the stable tab ID prevents this.
2025-11-20 12:32:35 -05:00
spencrmartin fb0b1ca13a Fix session ID mismatch issue in tabbed chat
- Add onSessionIdChange callback to useChatStream hook
- Notify tab context when new session gets real backend ID
- Update tab's session ID when backend creates new session
- Prevents message clearing when sending first message in new tab

This fixes the issue where new tabs would show messages briefly
then clear them because the temporary session ID didn't match
the real session ID created by the backend.
2025-11-20 12:28:40 -05:00
spencrmartin 567060e56e Fix resumeAgent API usage - correct data structure
- Fix destructuring of resumeAgent response (returns Session directly, not {session, conversation})
- Extract conversation from session.conversation property
- Add proper error handling for missing session data
- This should fix the 'Cannot read properties of undefined' error
2025-11-20 12:22:48 -05:00
spencrmartin ef6dc8f30c Fix critical message display logic in useChatStream
- Fix logic that was preventing messages from being returned properly
- Always prefer current messages over cached when available
- Add better logging for return values
- This should fix the blank chat issue
2025-11-20 12:20:00 -05:00
spencrmartin b418dfe05d Add comprehensive debugging for session resume process
- Add detailed console logs for resumeAgent calls and responses
- Log conversation data and message details
- This will help identify exactly where conversation loading fails
2025-11-20 12:18:16 -05:00
spencrmartin 9f8f5a931c Add debugging for BaseChat2 render state
- Add console logging to see messages length, chat state, and session info
- This will help identify why conversations show empty state instead of loading
2025-11-20 12:16:58 -05:00
spencrmartin 4a3754fa05 Add better debugging and caching for session loading
- Add detailed logging for resumeAgent responses
- Immediately cache loaded sessions and messages
- Add conversation preview in debug logs
- This should help identify why conversations aren't loading
2025-11-20 12:15:45 -05:00
spencrmartin 846c86854e Implement proper session tracking for tabs
- Re-enable setChat with selective updates (only sessionId and title changes)
- Add change detection in TabbedChatContainer to prevent infinite loops
- Track when new sessions get real backend IDs and update tabs accordingly
- This should enable proper session persistence and conversation loading
2025-11-20 12:14:45 -05:00
spencrmartin e486cfe486 Emergency fix: Disable setChat calls to stop infinite loops
- Temporarily disable setChat useEffect in BaseChat2
- Simplify handleSetChat in TabbedChatContainer
- This should restore basic chat functionality while we fix tab persistence properly
2025-11-20 12:12:56 -05:00
spencrmartin 1dc8bdfc34 Fix infinite loop by memoizing setChat callback and adding change detection
- Memoize handleSetChat callback to prevent recreation on every render
- Add change detection to only update when chat data actually changes
- This should fix the remaining infinite re-render issues
2025-11-20 12:10:58 -05:00
spencrmartin e27b9a3bd0 Fix infinite re-render loop in BaseChat2
- Use useMemo to memoize chat object and prevent recreation on every render
- Simplify useEffect dependencies to avoid infinite loops
- This fixes the 'Maximum update depth exceeded' error
2025-11-20 12:10:03 -05:00
spencrmartin 156db4e310 Fix setChat parameter destructuring in BaseChat2
- Add missing setChat parameter to function destructuring
- This fixes the 'setChat is not defined' error
2025-11-20 12:09:26 -05:00
spencrmartin d22bb01a2f Implement proper tab persistence across app reloads
- Add updateSessionId method to TabContext for tracking session ID changes
- Update BaseChat2 to properly call setChat with current session data
- Handle session ID updates when new sessions get real backend IDs
- Ensure tabs restore with proper session data and load conversation history
- Fix chat object to include actual session ID and title from backend
2025-11-20 12:08:39 -05:00
spencrmartin 7030ff6077 Fix 404 errors for new sessions
- Add guard in syncTabTitleWithBackend to skip new sessions (starting with 'new_')
- Update TabbedChatContainer to only sync existing sessions
- Prevent openExistingSession from trying to sync new session titles
- This eliminates 404 errors when creating new chat tabs
2025-11-20 12:06:28 -05:00
spencrmartin ac826cc851 fix: restore session loading and conversation history in tabbed interface
🐛 Problem Fixed:
- Tabbed interface always created new sessions instead of loading existing ones
- 'Resume from history' opened blank chats instead of loading conversation history
- useChatStream hook only supported new session creation, not existing session loading
- No integration with existing session management and resumeAgent API

✨ Solution Implemented:
- Enhanced useChatStream to attempt loading existing sessions via resumeAgent API
- Added smart session detection - only creates new for IDs starting with 'new_'
- Implemented openExistingSession method in TabContext for existing session support
- Added URL parameter handling for resumeSessionId in TabbedPairRoute
- Session deduplication prevents opening same session in multiple tabs

🔧 Technical Implementation:
- Modified useChatStream session loading logic to try resumeAgent first
- Added fallback to new session creation if resume fails
- Integrated with existing backend session management APIs
- Added automatic title synchronization for opened existing sessions
- URL parameter cleanup to prevent re-opening on refresh

🎯 User Experience:
- Resume from history now properly loads conversation history
- Existing sessions open with full message history and proper titles
- Clicking same session switches to existing tab instead of creating duplicate
- Seamless integration with existing session management workflow

📋 Features Added:
- Smart session detection (new_ prefix vs existing session IDs)
- Existing session loading with conversation history
- URL parameter support for session resumption (resumeSessionId)
- Tab deduplication for same session IDs
- Automatic title loading from backend for existing sessions
- Error resilience with fallback to new session creation

Files modified:
- ui/desktop/src/hooks/useChatStream.ts (added session loading with resumeAgent)
- ui/desktop/src/contexts/TabContext.tsx (added openExistingSession method)
- ui/desktop/src/components/TabbedPairRoute.tsx (added URL parameter handling)

Testing: ✅ Existing sessions now load with full conversation history
Testing: ✅ Resume from history works properly in tabbed interface
Testing: ✅ Session deduplication prevents duplicate tabs
Testing: ✅ Titles load automatically for existing sessions
2025-11-20 12:02:19 -05:00
spencrmartin 7be17f3d4a fix: improve tab title synchronization with existing sessions
🐛 Problem Fixed:
- Tab titles not loading from existing sessions with descriptions
- Only syncing titles for sessions that don't start with 'new_'
- Missing title updates when chat data is loaded

✨ Improvements:
- Removed restrictive session ID filtering - now syncs all sessions
- Enhanced backend sync with better logging and error handling
- Added title updates from chat.title when available
- Improved condition checking for meaningful backend titles

🔧 Technical Changes:
- Sync titles for ANY session showing 'New Chat' regardless of ID format
- Better logging to debug session title sync process
- Handle empty/null descriptions from backend gracefully
- Update tab titles when chat data contains title information

🎯 Expected Behavior:
- Existing sessions with descriptions should now show proper titles
- Better debugging output to identify sync issues
- More robust handling of different session ID formats
- Fallback to chat.title when available

Files modified:
- ui/desktop/src/contexts/TabContext.tsx (improved sync logic)
- ui/desktop/src/components/TabbedChatContainer.tsx (removed restrictive filtering)
2025-11-20 11:57:21 -05:00
spencrmartin 26ea7017b4 feat: implement smart tab titles with backend synchronization
✨ New Features:
- Smart tab title generation from first user message
- Backend synchronization with session descriptions
- Automatic title restoration from existing sessions
- Real-time title updates with immediate UI feedback

🔧 Technical Implementation:
- Added syncTabTitleWithBackend() method to TabContext
- Added updateTabTitleFromMessage() method for first message detection
- Integrated with existing getSession and updateSessionDescription APIs
- Graceful error handling - continues working if backend sync fails

🎯 User Experience:
- Tabs now show meaningful conversation titles instead of 'New Chat'
- First message (up to 47 chars) becomes the tab title automatically
- Existing session titles are loaded when tabs are restored
- Titles persist across app restarts via backend storage

📋 Smart Title Logic:
- Detects first user message and generates title
- Truncates long messages with ellipsis (47 chars + '...')
- Fallback to timestamp-based titles for empty messages
- Immediate local updates + async backend persistence

🔄 Backend Integration:
- Uses existing Session.description field for persistence
- Leverages getSession API for title restoration
- Uses updateSessionDescription API for title updates
- No breaking changes to existing session management

Files modified:
- ui/desktop/src/contexts/TabContext.tsx (added title sync methods)
- ui/desktop/src/components/TabbedChatContainer.tsx (added first message detection)

Testing: ✅ Tab titles update automatically on first message
Testing: ✅ Titles persist across navigation and app restart
Testing: ✅ Backend sync works with existing session APIs
Testing: ✅ Graceful fallback when backend calls fail
2025-11-20 11:55:44 -05:00
spencrmartin 15ca67afb1 fix: implement persistent tab state to survive navigation
🐛 Problem Fixed:
- Tab state was lost when navigating from tabbed chat to home and back
- Users would lose all their chat tabs when switching between routes
- Tab state was stored in local component state, lost on component unmount

✨ Solution Implemented:
- Created TabContext for global tab state management
- Integrated localStorage for automatic tab state persistence
- Refactored TabbedChatContainer to use context instead of local state
- Added TabProvider wrapper to App.tsx for global state access

🚀 Benefits:
- Tab state now persists across route navigation
- Tabs survive app restarts via localStorage
- Maintains all existing functionality (keyboard shortcuts, etc.)
- No breaking changes to existing tab behavior
- Better user experience with persistent workspace

Files modified:
- ui/desktop/src/contexts/TabContext.tsx (new)
- ui/desktop/src/components/TabbedChatContainer.tsx (refactored)
- ui/desktop/src/App.tsx (added TabProvider)

Testing: ✅ Tabs persist when navigating to home and back
Testing: ✅ Tab state survives app restart
Testing: ✅ All tab functionality still works (create, close, switch)
Testing: ✅ Concurrent sessions still work independently
2025-11-20 11:51:16 -05:00
spencrmartin 0ab1d3364b feat: implement tabbed chat interface with enhanced styling and session management
✨ New Features:
- Add tabbed chat interface with TabBar, TabbedChatContainer, and TabbedPairRoute components
- Support for multiple concurrent chat sessions with independent state
- Custom tab styling with animations, hover effects, and accessibility features
- Session isolation to prevent content bleeding between tabs

🎨 UI/UX Improvements:
- Enhanced tab bar with proper macOS stoplight button spacing
- Custom scrollbar styling aligned with design system
- Smooth transitions and animations for tab interactions
- Active tab indicators positioned at bottom of tabs
- Rounded top corners for chat container
- Responsive design with mobile optimization
- Dark mode support with proper color theming

🔧 Technical Enhancements:
- Implement sessionCreationInProgress tracking to prevent race conditions
- Add randomized delays to reduce concurrent session creation conflicts
- Force React component remounting with key prop for fresh session state
- Unique session ID generation with timestamp and entropy
- Enhanced error handling for 'Address already in use' conflicts
- Proper cleanup in async operations with finally blocks

🚀 Performance & Accessibility:
- CSS containment and hardware acceleration for smooth animations
- Focus management for keyboard navigation
- Reduced motion support for accessibility
- Touch target optimization for mobile devices
- Efficient session management with shared scheduler architecture

Files added:
- ui/desktop/src/components/TabBar.tsx
- ui/desktop/src/components/TabbedChatContainer.tsx
- ui/desktop/src/components/TabbedPairRoute.tsx
- ui/desktop/src/styles/tabs.css
- ui/desktop/src/utils/sessionUtils.ts

Files modified:
- ui/desktop/src/hooks/useChatStream.ts (session creation race condition fixes)
2025-11-20 11:46:45 -05:00
spencrmartin 5dac5a4603 Update home page chat input styling: remove background, center shadow, and add dark mode support 2025-11-19 13:17:11 -05:00
spencrmartin 8ec5609ac9 Remove background from chat input container for full transparency 2025-11-19 12:58:29 -05:00
spencrmartin 98c93157d1 Remove overflow clipping from chat container to allow sidecar shadows
- Remove overflow-hidden from BaseChat main container (bg-background-muted)
- This was the container clipping the sidecar drop shadows
- Allows sidecar shadows to spill properly over the chat area
- Fixes the grey appearance caused by shadow clipping against bg-background-muted
2025-11-19 12:54:15 -05:00
spencrmartin a539c1ff9f Update resizable splitter to use background-default when not hovered
- Change splitter default background from bg-border-subtle to bg-background-default
- Maintains hover state with bg-border-default for visual feedback
- Grip indicator remains hidden until hover for cleaner appearance
- Creates more subtle splitter that blends with app background when idle
2025-11-19 12:53:13 -05:00
spencrmartin 51a45631c0 Ensure chat area maintains clipped appearance while allowing sidecar shadows
- Add overflow-hidden to BaseChat main container
- Chat input area maintains its clipped, contained appearance
- Sidecar shadows can still spill properly due to ResizableSplitter changes
- Creates proper visual separation between chat and sidecar areas
2025-11-19 12:52:10 -05:00
spencrmartin 23cdfddea0 Remove overflow clipping to allow sidecar drop shadow to spill properly
- Remove overflow-hidden from ResizableSplitter right panel when floating
- Remove overflow-hidden from EnhancedBentoBox main container
- Allows drop shadow to render properly without being clipped
- Shadow can now spill into other sections of the app as intended
- Fixes grey appearance caused by clipped shadows
2025-11-19 12:51:05 -05:00
spencrmartin 8ac9b309f0 Revert sidecar container to use app background color
- Change EnhancedBentoBox main container back to bg-background-default
- Change individual DraggableContainer back to bg-background-default
- Uses consistent app background color throughout sidecar area
- Maintains design system consistency with app theme colors
2025-11-19 12:49:57 -05:00
spencrmartin 3baae43dd0 Ensure sidecar container uses white background
- Change EnhancedBentoBox main container from bg-background-default to bg-white
- Change individual DraggableContainer from bg-background-default to bg-white
- Ensures consistent white background throughout the sidecar area
- Matches the white background used in chat input area
2025-11-19 12:48:57 -05:00
spencrmartin 7224bb04ec Match sidecar background with chat input background
- Add bg-background-default to floating right panel area
- Ensures consistent background color between chat and sidecar areas
- Removes greyish app background behind floating sidecar
- Creates seamless visual integration with chat interface
2025-11-19 12:44:58 -05:00
spencrmartin 4648e8989a Increase border radius on floating sidecar container
- Change from rounded-lg to rounded-2xl for more rounded corners
- Matches the styling of the floating chat input container
- Creates a softer, more modern appearance for the floating sidecar
2025-11-19 12:44:12 -05:00