Commit Graph

2465 Commits

Author SHA1 Message Date
Pedram Amini
6f472a4de1 MAESTRO: Add unifiedTabs useMemo for unified tab system
Creates a memoized unifiedTabs array that combines aiTabs and
filePreviewTabs according to the session's unifiedTabOrder. Uses
a discriminated union type to allow components to render the
appropriate content for each tab type (AI or file preview).
2026-02-02 16:18:37 -06:00
Pedram Amini
942a9c0568 MAESTRO: Add FilePreviewTab type and unified tab system foundation
Phase 1 of file preview tabs feature:
- Add FilePreviewTab interface with id, path, name, extension, scrollTop,
  searchQuery, editMode, editContent, and createdAt fields
- Add UnifiedTabRef type for tab ordering across types
- Add filePreviewTabs, activeFileTabId, and unifiedTabOrder to Session
- Update all 13 session creation locations with new fields
- Update session restoration to hydrate new fields from persistence

This establishes the data model for coexisting AI tabs, file preview tabs,
and future terminal tabs in a unified tab bar.
2026-02-02 16:18:37 -06:00
Pedram Amini
04843b89f6 fix(symphony): make PR link clickable in claimed issue cards
Changed IssueCard from <button disabled> to <div role="button"> to allow
nested PR link button to receive click events. Disabled buttons block all
pointer events on children, even with pointerEvents: 'auto' style.

- Outer container is now a div with role="button" and manual keyboard handling
- PR link is now a proper <button> that can receive clicks independently
- Maintains same visual styling (opacity-60 for unavailable issues)
- Keyboard navigation preserved via tabIndex and onKeyDown
2026-02-02 08:18:50 -06:00
Pedram Amini
56ab021b33 ## CHANGES
- Moderator @mentions now normalize names (spaces→hyphens) for reliability 🧭
- Participant and available-session lists now show mention-ready normalized handles 👥
- Header responsiveness tuned for AUTO mode’s extra button width 📐
- Session name now hides on ultra-narrow panels to save space 🪟
- Git branch icon won’t shrink; branch text truncates cleanly ✂️
- Symphony issue PR link upgraded from span to proper button 🧷
- PR link click handling simplified; keyboard hacks removed for cleaner UX ⌨️
- Batch TTS settings now use refs to avoid stale closures mid-run 🎙️
- Audio feedback toggles take effect immediately during batch processing 
- Batch processor deps slimmed since audio settings are ref-driven 🧼
2026-02-02 08:03:39 -06:00
Pedram Amini
a7ca32f8c7 feat(tabNaming): add spinning indicator while generating tab name
- Add isGeneratingName property to AITab interface
- Show Loader2 spinner in tab while name generation is in progress
- Set isGeneratingName true before API call, false on completion/error
- Spinner only shows when automatic tab naming is enabled
2026-02-02 03:11:19 -06:00
Pedram Amini
38925cc627 feat(settings): move font/terminal/log settings to Display panel
Moved additional visual/output settings from General to Display:
- Interface font family and size
- Terminal width (columns)
- System log level and max buffer

Updated tests and docs to reflect new Display tab location.
2026-02-02 03:04:59 -06:00
Pedram Amini
dbf87ca760 feat(batchRunner): add unsaved changes confirmation on close
When closing the Auto Run Configuration modal, show a confirmation
dialog if there are unsaved changes to:
- Document list (documents added or removed)
- Loop settings (enabled/disabled, max loops)
- Agent prompt (edited from initial value)

If no changes were made, the modal closes immediately without
confirmation.

This prevents accidental loss of configuration when users press
Escape, click Cancel, or click the X button.
2026-02-02 02:55:55 -06:00
Pedram Amini
341fe0fdd6 test(modalPriorities): add tests for modal priority hierarchy
Add comprehensive test suite to verify modal priority ordering:
- Child modals must have higher priority than parents (30 test cases)
- Ensures DocumentSelectorModal closes before BatchRunner
- Ensures MarketplaceModal closes before BatchRunner/AutoRunExpanded
- Verifies confirmation dialogs are 1000+, overlays are lower priority
- Tests priority ranges match documented conventions

These tests will catch future regressions where child modals have
incorrect priorities, causing Escape to close parent modals first.
2026-02-02 02:52:07 -06:00
Pedram Amini
6a913b9b04 feat(settings): add Display panel for output/visual settings
Split General settings panel by creating new Display tab containing:
- Max output lines per response
- Document graph settings (external links, max nodes)
- Context window warnings (thresholds)

Updated docs to reflect new panel location.
2026-02-02 02:49:15 -06:00
Pedram Amini
dd340da30f feat(tabs): add automatic tab naming based on first message
When a new session starts and the first message is sent, Maestro now
automatically generates a descriptive tab name based on the user's
request. This runs in parallel with the main prompt processing and
uses the same AI agent (honoring SSH remote configurations).

Implementation:
- Add tab naming prompt at src/prompts/tab-naming.md
- Add IPC handler (tabNaming:generateTabName) that spawns ephemeral
  session to generate names with 30s timeout
- Integrate with onSessionId callback to trigger naming for new tabs
- Only update name if tab is still in UUID format (user hasn't renamed)
- Add automaticTabNamingEnabled setting (default: true)
- Add Settings UI checkbox under General section

Tab names are 2-5 words, Title Case, and capture the specific intent
rather than generic descriptions. Examples:
- "Help me implement JWT auth" → "JWT Auth Implementation"
- "Fix the checkout bug" → "Checkout Bug Fix"

Tests: 22 new tests covering IPC handler, settings, and edge cases
Docs: Updated general-usage.md, features.md, and configuration.md
2026-02-02 02:40:13 -06:00
Pedram Amini
2f945ec032 fix(ui): truncate document paths from left to show filename
Apply RTL text direction with LTR text isolation to show the rightmost
(filename) portion of document paths when truncated, while maintaining
full path on hover via title attribute.

Updated components:
- DocumentsPanel: Auto Run document list entries
- RightPanel: Auto Run progress indicator (single and multi-doc views)
2026-02-02 02:34:10 -06:00
Pedram Amini
a23cb425c3 fix(lightbox): sync lightboxImages state when deleting staged images
When opening the lightbox from staged images, a snapshot of stagedImages
was saved to lightboxImages. The LightboxModal used this snapshot for
navigation. When deleting an image, only stagedImages was updated but
lightboxImages remained stale, causing the deleted image to still appear.

Fix: Update both stagedImages AND lightboxImages in handleDeleteLightboxImage.

Added regression tests that simulate the parent state synchronization
pattern and verify both states are updated on deletion.
2026-02-02 02:29:18 -06:00
Pedram Amini
9c30233549 fix(ui): hamburger menu scrolls when insufficient vertical height
Add overflow-y-auto and max-h-[calc(100vh-120px)] to hamburger menu
dropdown containers so content can scroll when the viewport doesn't
have enough vertical space to display all menu items.

Applied to both expanded and collapsed sidebar menu overlays.
2026-02-02 01:59:21 -06:00
Pedram Amini
44c31627a4 ## CHANGES
- Stabilized group-chat integration tests by mocking Electron `app.getPath()` 🧪
- Added preload filesystem support to write files on SSH remotes 🚀
- Expanded `fs:writeFile` IPC signature to include optional remote identifier 🔌
2026-02-02 01:07:26 -06:00
Pedram Amini
51ab205d9b fix(tests): clear mock between tests in slash commands suite
The useInputProcessing test for "preserves multi-word arguments with
spaces" was failing because mockProcessQueuedItemRef.current accumulated
calls across tests in the nested describe block. Added a beforeEach to
explicitly clear the mock, ensuring mock.calls[0] always references the
current test's call.
2026-02-02 01:02:00 -06:00
Pedram Amini
8f6dd60386 feat(prompts): add response completeness guidance to system prompt
Adds a "Response Completeness" section to the Maestro system prompt
instructing agents to make each response self-contained with clear
summaries, relevant context, and key details. This ensures users can
understand responses even when only seeing the most recent message.
2026-02-02 00:32:42 -06:00
Pedram Amini
11a35c60cf Revert "feat(prompts): emphasize last message completeness in all agent prompts"
This reverts commit ba5641c19e.
2026-02-02 00:31:36 -06:00
Pedram Amini
ba5641c19e feat(prompts): emphasize last message completeness in all agent prompts
Updated all agent prompts to explicitly state that only the LAST
message is captured by the system. This ensures agents produce
complete, self-contained responses with all relevant information.

Prompts updated:
- context-grooming.md, context-summarize.md, context-transfer.md
- autorun-default.md, autorun-synopsis.md
- group-chat-participant.md, group-chat-participant-request.md
- group-chat-moderator-system.md, group-chat-moderator-synthesis.md
- maestro-system-prompt.md (new "Response Completeness" section)
2026-02-02 00:29:54 -06:00
Pedram Amini
bf86974290 feat(save-markdown): add SSH remote filesystem support
Enable saving markdown content directly to remote filesystems
when connected via SSH. The fs:writeFile IPC handler now accepts
an optional sshRemoteId parameter and uses writeFileRemote for
SSH transport.
2026-02-01 23:48:10 -06:00
Pedram Amini
7c19aec1ce test(save-markdown-modal): add comprehensive test suite
34 test cases covering:
- Basic rendering and form elements
- SSH remote session behavior (folder browse button visibility)
- Folder browser dialog interactions
- Form validation (disabled state, required fields)
- Save functionality (path construction, .md extension handling)
- Keyboard interaction (Enter to save)
- Error handling and error clearing
- Focus behavior on mount
2026-02-01 23:39:23 -06:00
Pedram Amini
988db778a7 fix(save-markdown-modal): hide folder browse button for SSH sessions
The native folder dialog can only browse local filesystems, so hide the
browse button when the session is running over SSH (where the default
path would be a remote path). Users can still manually type a path.
2026-02-01 23:37:19 -06:00
Pedram Amini
2c2fa91d1f fix(main-panel): open ORIGIN link in system browser
Changed the git info popup's remote URL link to use
window.maestro.shell.openExternal() instead of window.open()
so it opens in the user's default system browser.
2026-02-01 23:21:53 -06:00
Pedram Amini
25b6545ab8 fix(quick-actions): improve Open Repository in Browser error handling
- Add await to shell.openExternal call to ensure proper async handling
- Show toast notification when no remote URL is found for the repository
- Add error handling with toast feedback for any failures
- Update tests to verify toast notifications are shown on error

Fixes issue where the command didn't provide feedback when failing.
2026-02-01 23:19:04 -06:00
Pedram Amini
65af8a23c7 fix(notifications): skip custom notification for synopsis messages
Custom notification commands (e.g., TTS, fabric pipelines) should only
run for regular AI conversation flow toasts, not for synopsis messages.

Added skipCustomNotification flag to Toast interface and set it to true
for synopsis toasts. This prevents the notification command from being
executed when a synopsis completes, while still showing OS notifications
and toast UI.
2026-02-01 23:09:04 -06:00
Pedram Amini
13f68c15a7 fix(document-graph): truncate long text lines in document nodes
Document nodes with long unbroken text (like separator lines with ====)
were bleeding outside their boundaries. Fixed by:
- Setting fixed width (280px) on container instead of just maxWidth
- Using break-all word breaking for description text
- Adding webkit line clamping to limit description to 3 lines
- Using text-overflow: ellipsis with overflow: hidden
2026-02-01 22:59:23 -06:00
Pedram Amini
9dbb2419b6 feat(left-bar): add drop zone for ungrouping when all sessions are in groups
- Shows "Drop here to ungroup" zone when dragging a session and no ungrouped sessions exist
- Allows users to drag sessions out of groups even when Ungrouped Agents folder is hidden
- Added tests for drop zone visibility and drop handler
2026-02-01 22:46:01 -06:00
Pedram Amini
434f89268e fix(notifications): show Stop button only while command is running
Previously, the Test button would show "Stop" after the notification
command started and remain visible even after the process exited,
requiring an 8-second timeout fallback to reset.

Now the component listens for the onCommandCompleted event and
immediately resets to "Test" (via Success state) when the process
exits naturally. The Stop button is only shown while the process
is actively running.
2026-02-01 22:44:15 -06:00
Pedram Amini
ed14745e63 test updates 2026-02-01 22:36:35 -06:00
Pedram Amini
c769668b6c refactor(notifications): complete ttsId to notificationId migration
Remove backward compatibility shim and fully migrate from legacy ttsId
property to notificationId across all notification-related code:

- Update NotificationsPanel.tsx to use result.notificationId
- Remove deprecated ttsId from NotificationCommandResponse interface
- Remove legacy TTS alias exports from handler
- Update all test files and mocks to use notificationId
2026-02-01 22:30:29 -06:00
Pedram Amini
141d0e015e fix(history): use actual task duration for USER entry elapsed time
Changed elapsed time calculation for USER history entries to use the
actual task duration (from thinkingStartTime to completion) instead of
time since the last synopsis. This accurately reflects how long the
agent was actively working on the task being synopsized.
2026-02-01 22:25:47 -06:00
Pedram Amini
d9d4a44894 feat(history): add elapsed time tracking for USER history entries
Add elapsed time calculation when creating USER history entries via
the saveToHistory/synopsis feature. Time is calculated from lastSynopsisTime
(if a previous synopsis exists) or tabCreatedAt (for first synopsis).
This complements the existing elapsed time tracking for AUTO entries.
2026-02-01 22:24:04 -06:00
Pedram Amini
2968a36e11 docs: update notification docs for Custom Notifications rename (#168)
- Rename "Speakable Notifications" to "Custom Notifications" in features
- Update Notifications tab description to remove TTS-specific language
- Revise Custom Notification section with broader command examples
- Remove default TTS bias from configuration guidance
2026-02-01 22:21:13 -06:00
Pedram Amini
9605e44366 docs(skills): add documentation for /skills command with screenshot
Documents the /skills slash command in the slash commands guide,
including the screenshot and explanation that it's Claude Code only.
2026-02-01 22:18:10 -06:00
Pedram Amini
e306be17ac chore: fix 39 ESLint unused variable warnings
- Remove unused FocusArea import from App.tsx
- Prefix unused destructured variables with _ (inline wizard state, refs)
- Remove unused imports (useCallback, MainPanelHandle, hasExistingAutoRunDocs, etc.)
- Remove unused SymphonyCategory type import
- Fix prefer-const warning in fileExplorer.ts (regexStr)
2026-02-01 22:13:46 -06:00
Pedram Amini
1c75629805 fix(drag-drop): use capture phase for document-level listeners to enable repeated drops
The previous fix added document-level dragover/drop handlers to call
preventDefault(), but handleImageDragOver was calling stopPropagation()
which prevented the document-level handlers from firing during the bubble
phase. Switching to capture phase ensures preventDefault() is called at
the document level before element handlers can stop propagation.
2026-02-01 21:58:50 -06:00
Pedram Amini
33de2c15ab test(notifications): explicitly verify NO whitelist for custom commands
Update notification tests to clearly document and verify that:
- Custom notification commands have NO whitelist and NO validation
- ANY executable path, binary name, or arguments are allowed
- Shell pipelines with redirects and pipes are fully supported

Also rename TTS terminology to generic notification terminology:
- resetTtsState → resetNotificationState
- getTtsQueueLength → getNotificationQueueLength
- getActiveTtsCount → getActiveNotificationCount
- clearTtsQueue → clearNotificationQueue
- getTtsMaxQueueSize → getNotificationMaxQueueSize
- Add onCommandCompleted alongside deprecated onTtsCompleted

This ensures the feature remains open-ended for user flexibility.
2026-02-01 21:52:31 -06:00
Pedram Amini
6b33e72a21 perf: lazy-load heavy modals and consolidate session ID parsing
- Add sessionIdParser utility with pre-compiled regex patterns for parsing
  session IDs (AI tab, synopsis, batch, group chat formats). Replaces 20+
  inline regex compilations with shared module-level constants.

- Lazy-load rarely-used heavy components to reduce initial bundle:
  - SymphonyModal (2,193 lines)
  - MarketplaceModal (playbook exchange)
  - UsageDashboardModal (8 chart components)
  - ProcessMonitor
  - LogViewer (system logs)
  - GitLogViewer
  - GitDiffViewer
  - DocumentGraphView (mind map visualization)

- Add comprehensive test coverage for sessionIdParser utility

These changes reduce initial JavaScript execution time by deferring
loading of ~10k+ lines of rarely-accessed modal code until first use.
2026-02-01 21:48:12 -06:00
Pedram Amini
90bb955df5 fix(drag-drop): add document-level preventDefault to enable repeated image drops
Without preventing default on both dragover and drop at the document level,
Electron/Chromium can reject subsequent drag-and-drop operations after the
first drop. This adds document-level handlers that call preventDefault() on
both events, ensuring the drop zone remains valid across multiple operations.
2026-02-01 20:10:34 -06:00
Pedram Amini
2dc99e646a feat(notifications): allow any custom notification command
- Remove TTS command whitelist validation - users can now configure any
  command for custom notifications (e.g., fabric piped to 11s)
- Enable shell mode for spawn to support pipes and command chains
- Add visual feedback to Test button (running/success/error states)
- Remove speech bubble from AI response messages in TerminalOutput
- Rename internal TTS terminology to more generic "notification command"
- Update tests to reflect new behavior
2026-02-01 20:06:34 -06:00
Pedram Amini
9e83588ffd fix(save-markdown-modal): use createPortal to render at document body
Fixes overlay not covering sidebar and file panel by rendering the
modal via React portal to document.body, ensuring proper z-index
stacking across all UI layers.
2026-02-01 19:49:27 -06:00
Pedram Amini
f9db845712 fix(tests): add missing webContents.on mock for render-process-gone handler
The window-manager tests were failing because the mock webContents
object was missing the 'on' method needed by the crash detection handler.
2026-02-01 18:16:47 -06:00
Pedram Amini
c2239fee70 feat(stats-db): add Sentry error reporting for database failures
Stats DB initialization failures were only logged locally, providing no
visibility into production issues. This change adds Sentry reporting for:

- Database corruption detection (integrity check failures)
- Native module loading failures (architecture mismatches)
- Database creation failures
- General initialization failures

Created reusable Sentry utilities in src/main/utils/sentry.ts that
lazily load @sentry/electron to avoid module initialization issues.
2026-02-01 18:13:24 -06:00
Pedram Amini
5ccebfd73e feat(crash-detection): add renderer crash handlers and Sentry reporting
Add comprehensive crash detection for renderer process failures that
Sentry in the renderer cannot capture (because the process is dead,
broken, or failed before Sentry initialized):

- render-process-gone: captures crash, kill, OOM, launch-failed
- unresponsive/responsive: tracks frozen window states
- crashed: handles page-level crashes
- did-fail-load: captures page load failures (network, invalid URLs)
- preload-error: captures preload script failures before app loads
- console-message: forwards critical renderer errors (TypeError, etc.)

Reports to Sentry from main process with detailed context.
Auto-reloads renderer after non-intentional crashes.
2026-02-01 18:07:19 -06:00
Pedram Amini
4405540003 fix(settings): restore maxOutputLines correctly when set to Infinity
When users select "All" for Max Output Lines, Infinity is stored but
JSON.stringify(Infinity) produces null. On app restart, this null value
was being loaded directly, causing:
- null * 1.5 = 0 for maxHeight calculation
- All AI responses appearing fully collapsed (only "Show all X lines")

Now we detect null values for maxOutputLines and restore them as
Infinity, matching the user's original "All" selection.

Root cause: JSON cannot represent Infinity, so it becomes null during
serialization to electron-store.

Fixes the regression where maxOutputLines setting was lost on restart.
2026-02-01 17:46:33 -06:00
Pedram Amini
93faa712b0 feat(terminal-output): add save button to AI response tool panel
Add a save icon to the action buttons at the bottom of AI responses
that opens a modal allowing users to save the markdown content to a
file. The modal includes:
- Folder path input with a browse button for filesystem navigation
- Filename input with automatic .md extension handling
- Error handling and validation
2026-02-01 16:23:43 -05:00
Pedram Amini
528dbf27a6 fix(tour): remove labels from pencil/image icons, fix thinking description
- Remove "Pencil" and "Image" labels to show icon-only for those controls
- Update Thinking description to "toggles display of agent thinking"
- Make label prop optional in TourIcon component
2026-02-01 16:08:21 -05:00
Pedram Amini
274698efea feat(file-preview): dismiss TOC overlay on click outside
Add an invisible fixed backdrop behind the TOC overlay that captures
clicks outside the menu, providing standard dismiss-on-click-outside
behavior.
2026-02-01 15:57:47 -05:00
Pedram Amini
db5ae7cac1 feat(tour): render actual Lucide icons inline in input area step
- Convert tourSteps.ts to tourSteps.tsx to support JSX content
- Add descriptionContent/descriptionContentGeneric fields to TourStepConfig
  for rendering JSX after the text description
- Create TourIcon component that renders actual Lucide icons inline
- Update input area step to show PenLine, ImageIcon, History, Eye, Brain,
  and Keyboard icons matching the actual UI controls
- Widen tooltip to 480px when step has extra JSX content
- Restore original description text, move icon explanations to JSX content
2026-02-01 15:56:09 -05:00
Pedram Amini
88d960e73b fix(main-panel): remote file loading state now fills entire main panel
When loading remote content (e.g., README.md from SSH), the loading
indicator now takes over the entire main panel instead of showing
alongside the terminal output. This prevents the awkward half-filled
appearance.
2026-02-01 15:47:15 -05:00
Pedram Amini
8f63b6d87d fix(symphony): fallback to expired cache when GitHub fetch fails
Apply the same fix from the marketplace handlers to Symphony:
- getRegistry: Falls back to expired cache when GitHub fetch fails
- getIssues: Falls back to expired cache when GitHub fetch fails

This prevents showing empty data when the network is unavailable
but valid (though expired) cache data exists.
2026-02-01 15:22:16 -05:00