Commit Graph

3073 Commits

Author SHA1 Message Date
spencrmartin 03d6256c19 Add user badge to Goose messages from collaborators
- Display Goose dot avatar as main avatar for all assistant messages
- Add small user badge in bottom-right corner for collaborator messages
- Badge shows user's avatar if available, or initial letter on colored background
- Header shows 'Goose (username)' for collaborator messages
- This clearly indicates the message is from another user's Goose instance
2025-11-21 15:18:01 -05:00
spencrmartin 8138bbeef4 Fix Matrix room context detection for message filtering
- Check targetRoomId (not sessionId) to determine if in Matrix room context
- sessionId can be a backend session ID even when in a Matrix room
- Use isInMatrixRoomContext based on targetRoomId starting with '!'
- This correctly allows messages from other users in the same Matrix room
2025-11-21 15:16:36 -05:00
spencrmartin 8b9d64e102 Fix Matrix room message filtering logic
- Changed condition from (isMatrixRoom ? true : isSessionMatch) to (isMatrixRoom || isSessionMatch)
- For Matrix rooms, only room IDs need to match (not session IDs)
- Each user has their own backend session ID, so checking session match was incorrectly blocking messages
- This allows messages from other users in the same Matrix room to display properly
2025-11-21 15:15:23 -05:00
spencrmartin 73647c9624 Add enhanced logging for Matrix message sender information
- Log full sender details (userId, displayName, avatarUrl) when processing messages
- Log complete message object being sent to onMessageSync
- This will help debug if sender info is properly flowing through to display
2025-11-21 15:07:58 -05:00
spencrmartin eaa39ca49e Fix Matrix message deduplication - only mark as processed after successful display
- Moved processedMessages.current.add() to AFTER onMessageSync call
- Prevents messages from being marked as processed when they fail to display
- Fixes issue where messages were skipped due to premature deduplication
2025-11-21 15:03:43 -05:00
spencrmartin a3d371b86c Fix Matrix message streaming - only send complete messages once
- Added sentToMatrixRef to track sent messages and prevent duplicates
- Only send messages when chatState is Idle (streaming complete)
- Format messages as goose-session-message: for proper parsing by receivers
- Prevents 429 Too Many Requests errors from sending during streaming
2025-11-21 14:42:28 -05:00
spencrmartin 904b43d4fc Show loading state only for existing chats with messages
Check message_count from backend session to determine if chat
has existing messages. Only show loading indicator if messages
need to be loaded. New chats (message_count = 0) show empty
state immediately with popular topics.

This prevents showing a loading spinner for brand new Matrix
chats that have no message history to load.
2025-11-21 14:22:16 -05:00
spencrmartin 05b936fb61 Fix existing Matrix tab loading state
When switching to an existing Matrix tab that's still loading,
ensure the backend session is created and loading state is cleared.

Previously, clicking 'Open Chat' would switch to an existing tab
but leave it in a loading/blank state if the async session creation
hadn't completed yet.
2025-11-21 14:20:43 -05:00
spencrmartin 8a81a9988b Fix Matrix notification system and add loading states
- Fix Goose assistant response spam: suppress role='assistant' notifications
- Fix stale tab state: use fresh shouldSuppressNotification calls
- Remove buggy legacy /pair suppression logic that checked sender ID
- Fix 'Open Chat' to check existing tabs before navigating
- Add Matrix room ID display in SessionListView
- Optimize MatrixSessionService to defer heavy loading until needed
- Add loading state for Matrix chat initialization
- Improve loading indicator visibility in BaseChat2

Fixes notification spam, incorrect suppression, and blank chat states.
2025-11-21 14:18:52 -05:00
spencrmartin b7db0dde93 Fix: Show pending Matrix invites in all tabs, fetch from server
- Updated TabbedChatContainer to show pending invites in all tabs (not just Matrix tabs)
- Added getPendingInvitedRooms() method to MatrixService to fetch invites directly from Matrix server
- Exposed getPendingInvitedRooms() in MatrixContext for easy component access
- Updated PendingInvitesInHistory to fetch from Matrix API and merge with local storage
- Matrix server data now takes precedence over local storage for accuracy

Fixes issue where pending collaboration invites weren't showing in regular chat tabs
2025-11-21 13:32:20 -05:00
spencrmartin 66634d7ec3 Fix Matrix message isolation and sending functionality
- Fix 'targetRoomId is not defined' error in useSessionSharing
- Implement comprehensive Matrix message isolation to prevent cross-tab contamination
- Add Matrix room ownership system to ensure only one tab handles each Matrix room
- Fix Matrix message sending in ChatInput with proper async/await support
- Prevent solo sessions from accidentally inheriting Matrix functionality
- Fix mention popover positioning and visibility issues
- Add session-specific Matrix message event filtering
- Ensure Matrix messages only appear in designated Matrix tabs
- Prevent non-Matrix tabs from receiving or sending Matrix messages
- Fix MatrixRealtimeSync to respect tab ownership system
- Add comprehensive debug logging for Matrix message flow

Key changes:
- useSessionSharing.ts: Add targetRoomId calculation and ownership registry
- ChatInput.tsx: Add Matrix message sending with sendMessage() and conditional onMessageSync
- useChatStream.ts: Add isMatrixTab prop to filter Matrix message listeners
- BaseChat2.tsx: Add targetSessionId to Matrix message events
- MatrixRealtimeSync.ts: Implement ownership-based message routing
- TabContext.tsx: Prevent solo sessions from being treated as Matrix sessions
- EnhancedMentionPopover.tsx: Fix positioning with fixed positioning and document.body rendering
2025-11-21 13:22:02 -05:00
spencrmartin 1a5530c4bd DEBUG: Add extensive logging to diagnose Matrix message leakage
- Added detailed logging to useSessionSharing Matrix listener setup check
- Added critical debug logging to ChatInput before calling useSessionSharing
- Enhanced Matrix room detection logging with timestamps
- This will help identify why regular chats are still receiving Matrix messages

The issue appears to be that regular chat sessions might be getting
initialRoomId values when they shouldn't, causing Matrix listeners
to be set up for non-Matrix chats.
2025-11-21 09:52:46 -05:00
spencrmartin 7dca0c2494 CRITICAL FIX: Prevent Matrix leakage into new chats (hybrid approach)
Key Changes:
- Fixed TabContext sanitization logic for hybrid approach
- Matrix tabs now only require matrixRoomId (not matrix_ sessionId format)
- Regular tabs are sanitized to remove Matrix properties (matrixRoomId, matrixRecipientId)
- Preserved actual backend session IDs during sanitization
- Applied fix to both initial load and restoreTabState functions

This prevents new chat tabs from inheriting Matrix properties after app reload,
which was causing Matrix messages to leak into regular chats. The hybrid approach
uses real backend session IDs while storing Matrix context in tab properties.
2025-11-21 09:49:27 -05:00
spencrmartin 8a91fb3dd7 HYBRID APPROACH: Matrix sessions use real backend session IDs
Key Changes:
- Matrix tabs now use actual backend session IDs, not matrix_ format
- Matrix context comes from tab properties (matrixRoomId, matrixRecipientId, type: 'matrix')
- SessionMappingService creates proper Matrix ↔ Backend session mappings
- ChatInput detects Matrix rooms via tab properties, not sessionId format
- useSessionSharing always gets real backend session ID for API calls
- Matrix room ID passed separately via initialRoomId parameter
- TabContext openMatrixChat creates backend sessions and proper mappings
- Matrix session restoration works via backend session metadata

This ensures Goose backend always gets proper session IDs while maintaining
Matrix functionality through the mapping service and tab properties.
2025-11-21 09:37:08 -05:00
spencrmartin 4a79e739c7 CRITICAL FIX: Matrix session persistence across app reloads
- Store Matrix metadata in backend session descriptions during creation
- Add Matrix metadata extraction and restoration functionality to SessionMappingService
- Update TabContext to restore Matrix properties from backend sessions on load
- Ensure Matrix tabs maintain correct sessionId format and properties after reload
- Add comprehensive Matrix session detection and restoration logic
- Pass matrixRecipientId when creating Matrix session mappings

This fixes the issue where Matrix sessions lose their Matrix context
and become regular chats after app reload. Now Matrix sessions are
properly restored with their room ID, recipient ID, and Matrix properties.
2025-11-21 09:34:00 -05:00
spencrmartin 1bbdb096d0 CRITICAL FIX: Prevent Matrix properties corruption in regular chats on reload
- Add tab state sanitization during localStorage restoration
- Validate Matrix tab properties (must have matrixRoomId and matrix_ sessionId)
- Strip Matrix properties from regular chat tabs during restore
- Apply sanitization to both initial load and manual restoreTabState
- Generate new session IDs for corrupted tabs to prevent conflicts

This fixes the bug where reloading the app would cause regular 'New Chat'
tabs to inherit Matrix properties, leading to Matrix messages appearing
in non-Matrix chats.
2025-11-21 09:24:11 -05:00
spencrmartin 190e5aa110 CRITICAL FIX: Prevent Matrix message leakage into regular chats
- Add strict session isolation in useSessionSharing
- Only set up Matrix listeners for sessions that have a Matrix room ID
- Prevent regular chats from receiving Matrix messages
- Fix message filtering logic that was too permissive

This resolves the critical bug where Matrix messages were appearing
in non-Matrix chat sessions due to inadequate session isolation.
2025-11-21 09:20:40 -05:00
spencrmartin e64db09e8e Fix Matrix tab persistence and real-time message handling
- Implement tab persistence to prevent component unmounting when switching tabs
- Remove key prop from BaseChat2 to maintain component state across tab switches
- Add conditional rendering for all tabs (visible/hidden instead of mount/unmount)
- Fix Matrix session ID consistency in TabContext.openMatrixChat
- Enhance ChatInput Matrix room detection with TabContext integration
- Add isTabActive prop to BaseChat2 for future optimizations
- Ensure Matrix connections persist when navigating between tabs
- Fix real-time message display in Matrix rooms when switching back to tabs
- Resolve notification suppression issues for multichat sessions
- Add extensive debugging logs for Matrix room detection and tab state

Key fixes:
* Matrix tabs no longer 'unmount' when switching away and back
* Real-time messages appear correctly in background Matrix tabs
* Notification suppression now works correctly with tab context
* Session ID format consistency (matrix_!roomId) maintained
* useSessionSharing connections persist across tab switches

This resolves the core issue where Matrix tabs would lose their state and
stop syncing messages after navigating to different tabs.
2025-11-21 09:18:27 -05:00
spencrmartin 1fe3edb328 Add error handling and diagnostics for document persistence dialog functions
- Add function existence checks for showSaveDialog and showOpenDialog
- Provide clear error messages when IPC handlers are not available
- Add console logging for debugging dialog calls
- Graceful fallback when Electron app needs restart for new IPC handlers
2025-11-20 18:18:08 -05:00
spencrmartin 38f43d1953 Fix document persistence by exposing save/open dialog functions in preload
- Add showSaveDialog and showOpenDialog to ElectronAPI interface
- Implement IPC calls for show-save-dialog and show-open-dialog handlers
- Fix TypeError: window.electron.showSaveDialog is not a function
- Enable Save As functionality in DocumentEditor persistence system
2025-11-20 18:11:06 -05:00
spencrmartin 9c6cd3f980 Enhance document persistence system with comprehensive auto-save and Save As functionality
- Create complete persistence system with DocumentPersistence utility class
- Add usePersistence React hook for state management
- Enhance DocumentEditor with auto-save (30s intervals), Save As dialogs
- Support multiple file formats (HTML, Markdown, Plain Text) with smart conversion
- Add visual indicators for saving states (saving, auto-saving, unsaved)
- Implement backup/recovery system with localStorage session persistence
- Add keyboard shortcuts (Ctrl+S save, Ctrl+Shift+S save as)
- Create comprehensive error handling and user feedback
- Add IPC handlers for save/open dialogs in main.ts

Features:
- Auto-save every 30 seconds with visual feedback
- Save As with file type detection and format conversion
- Session persistence - drafts survive tab switches/app restarts
- Backup creation and restoration capabilities
- Multi-format support with intelligent content conversion
- Type-safe implementation with full TypeScript interfaces
2025-11-20 18:10:06 -05:00
spencrmartin 6848420293 Fix comment persistence and finalize implementation
- Fixed sessionId passing from BaseChat2 to useComments hook
- Moved comment loading to useState initializer for immediate loading
- Resolved useEffect dependency issues that prevented comment loading
- Comments now persist correctly across tab switches and page refreshes
- Cleaned up all debugging logs for production readiness
- Verified full persistence functionality working

The Google Docs-style commenting system is now complete and production-ready!
2025-11-20 17:59:22 -05:00
spencrmartin d074fffdc9 Add persistent storage for comments
- Create CommentStorage utility class for localStorage management
- Comments now persist between app sessions with 90-day retention
- Automatic loading/saving tied to chat session IDs
- Updated useComments hook to integrate with storage system
- Session-scoped storage prevents comment cross-contamination
- Efficient JSON serialization with timestamp tracking
- Zero performance impact with background load/save operations

Comments now survive app restarts and session switching!
2025-11-20 16:49:10 -05:00
spencrmartin fc3575f1c1 Implement Google Docs-style commenting system
- Add text selection and commenting functionality to chat messages
- Comments appear in right margin with floating overlay design
- Support for threaded comment conversations with replies
- Visual text highlighting for commented sections
- Clickable highlights that focus corresponding comments
- Persistent comment storage with unique message identification
- Maintain tool call chaining functionality
- Components: CommentableMarkdown, MessageComments, CommentCard, CommentInput
- Custom useComments hook for state management
- TypeScript interfaces for comment data structures
2025-11-20 16:27:05 -05:00
spencrmartin 765b1c52b0 Implement multi-panel sidecar system with drag-and-drop
- Add MultiPanelTabSidecar component for tab-level multi-panel layouts
- Implement drag-and-drop panel reordering with visual drop zones
- Support multiple layout modes: single, columns, rows, grid, custom
- Add drag handles to panel headers for intuitive rearrangement
- Auto-detect layout based on drop position (left/right for columns, top/bottom for rows, center for grid)
- Fix WebBrowser screenshot interference by disabling backdrop functionality
- Remove border strokes from all sidecar components for clean appearance
- Fix drop shadow clipping issues in ResizableSplitter
- Ensure proper rounded edges on all sidecar panels
- Maintain backward compatibility with single-panel TabSidecar
- Add comprehensive documentation in MULTI_PANEL_DEMO.md

Features:
- Drag panels by grip icon in headers
- Visual drop zones with color-coded feedback
- Smooth animations with Framer Motion
- Individual sidecar styling (no wrapper containers)
- Support for web, file, diff, editor, and localhost content types
- Automatic layout switching based on panel count
- Clean, modern UI without borders or clipped shadows
2025-11-20 15:25:04 -05:00
spencrmartin 953acf73bd Improve WebBrowser compatibility - add standard user agent and enhanced web preferences 2025-11-20 14:44:02 -05:00
spencrmartin 618009e06a Fix BrowserView visibility issue - use proper hide/show instead of zero bounds 2025-11-20 14:33:22 -05:00
spencrmartin 5823f8f129 Implement WebBrowser state persistence across tab switches - preserve current webpage when navigating between tabs 2025-11-20 14:32:03 -05:00
spencrmartin fbb5d0766b Fix BrowserView persistence after sidecar close - add explicit cleanup event handling 2025-11-20 14:30:42 -05:00
spencrmartin acb8a539d4 Improve BrowserView web compatibility - allow mixed content and use separate session 2025-11-20 14:24:29 -05:00
spencrmartin 02e789a7a5 Improve WebBrowser compatibility - add standard user agent and enhanced web preferences 2025-11-20 14:24:08 -05:00
spencrmartin b1e502c773 Fix WebBrowser layout issues - remove white background and fix BrowserView positioning 2025-11-20 14:18:43 -05:00
spencrmartin 45ba098b44 Fix WebBrowser component recreation issue - prevent BrowserView destruction during navigation 2025-11-20 14:17:03 -05:00
spencrmartin 6d052edb4c Fix URL input being overwritten while typing - only update URL when not actively editing 2025-11-20 14:13:46 -05:00
spencrmartin c7c5f08a44 Fix BrowserView persistence across tabs - properly hide/show BrowserViews when switching tabs 2025-11-20 14:12:26 -05:00
spencrmartin b98daeb120 Fix WebBrowser navigation state function name mismatch 2025-11-20 14:11:16 -05:00
spencrmartin 5bae05d263 Fix per-tab sidecar isolation - WebBrowser instances now properly isolated between tabs 2025-11-20 14:09:55 -05:00
spencrmartin 57c8cb1dff Implement full-featured web browser using Electron BrowserView
- Created WebBrowser component with proper browser controls
- Added address bar with URL input and search functionality
- Implemented navigation buttons (back, forward, refresh, home)
- Added loading states and status bar
- Uses Electron's native BrowserView for real web browsing instead of iframe
- Includes proper URL validation and search query handling
- Integrated into TabSidecar for web content type
- Maintains TipTap document editor for rich text editing
- Full browser functionality with navigation state polling
2025-11-20 14:03:44 -05:00
spencrmartin 091bcdfdc8 Integrate TipTap rich document editor into per-tab sidecars
- Replaced simple textarea with full-featured DocumentEditor component
- Added RichDocumentEditor wrapper for sidecar integration
- Document editor now includes:
  - Rich text formatting (bold, italic, underline, strikethrough)
  - Headings (H1, H2, H3)
  - Lists (bullet, ordered)
  - Code blocks and blockquotes
  - Undo/redo functionality
  - Auto-save with Ctrl+S
  - File format support (HTML, Markdown, plain text)
  - Character and word count
  - Unsaved changes indicator
- Maintains all original styling and features from the global document editor
2025-11-20 14:01:22 -05:00
spencrmartin fe8bb17e3f Add web viewer support and fix sidecar content types
- Added showWebViewer function to TabContext for web browsing
- Extended TabSidecarView interface to support 'web' content type
- Updated TabSidecar component to render web content with Monitor icon
- Fixed TabSidecarInvoker to use showWebViewer instead of showLocalhostViewer for web browsing
- All sidecar types (diff, localhost, web, file, editor) now properly supported
- Resolves 'Unknown content type' error for document editor and web viewer
2025-11-20 13:59:53 -05:00
spencrmartin 2682ff135a Fix React child serialization error in per-tab sidecars
- Changed TabSidecarView interface to use contentType/iconType strings instead of JSX elements
- Updated TabSidecar component to render components based on type rather than storing JSX
- Added component renderers for diff, localhost, file, and editor views
- Removed JSX elements from TabContext state to fix localStorage serialization
- This resolves the 'Objects are not valid as a React child' error
2025-11-20 13:57:41 -05:00
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