Commit Graph

2591 Commits

Author SHA1 Message Date
Pedram Amini
c1e434e3fe test(tab-naming): fix tests to match extractTabName behavior
Update test expectations to match the actual extractTabName logic:
- Lines > 40 chars are filtered out (not truncated), returning null
- Lines starting with quotes are filtered as example inputs
- Use period separator to test multi-line filtering correctly
- Preamble test uses exact pattern that regex matches
2026-02-03 01:04:05 -06:00
Pedram Amini
92f49af12d fix(header): restore git badge and changes hover overlays
Remove overflow-hidden from parent containers that was clipping the
absolutely positioned tooltip overlays. The responsive text truncation
is now handled by individual element classes (truncate, max-w-[120px])
rather than container-level overflow clipping.

Changes:
- MainPanel.tsx: Remove overflow-hidden from flex containers, add truncate
  to session name, use shrink-0 on git badge container
- GitStatusWidget.tsx: Use shrink-0 instead of overflow-visible
2026-02-03 00:50:43 -06:00
Pedram Amini
9c654819ce fix(header): restore git badge and changes hover overlays
The git branch badge and GitStatusWidget hover overlays were being clipped
by overflow-hidden on their parent containers. Added overflow-visible to
the tooltip container divs while keeping overflow-hidden on the outer
parent containers to preserve responsive truncation behavior.

Changes:
- MainPanel.tsx: Added overflow-visible to git badge's relative container
- GitStatusWidget.tsx: Added overflow-visible to widget's relative container
2026-02-03 00:47:47 -06:00
Pedram Amini
464ccdb83d feat(file-explorer): add Open in Default App context menu option
Add a new context menu option for files that opens them in the system's
default application. The option appears in the top section of the menu,
after Preview and Document Graph, as the third item.
2026-02-03 00:30:28 -06:00
Pedram Amini
42dd005ca1 fix(tab-naming): use stdin for prompt in SSH remote execution
Tab naming was failing with 'zsh:23: unmatched' errors when running
via SSH because the prompt was being passed through multiple layers
of shell escaping (local spawn -> SSH -> remote zsh -> bash -c).

Fix by detecting SSH remote execution and sending the prompt via stdin
with --input-format stream-json instead of embedding it in the command
line. This completely bypasses shell escaping issues.

Changes:
- Add shouldSendPromptViaStdin flag when SSH remote is configured
- Pass useStdin option to buildSshCommand for proper SSH configuration
- Add sendPromptViaStdin to ProcessManager spawn call
- Add test case for SSH remote tab naming
2026-02-03 00:09:48 -06:00
Pedram Amini
f29e767b79 fix(tab-naming): replace unicode arrows with ASCII to prevent shell escaping issues 2026-02-03 00:03:53 -06:00
Pedram Amini
7088a33b1f fix(tab-naming): simplify prompt and improve output extraction
The tab naming prompt was too verbose, causing agents to output full
sentences instead of short 2-4 word names.

Changes:
- Simplified tab-naming.md prompt to be more concise and direct
- Improved extractTabName() to filter out bad output:
  - Removes markdown headers (##, ###)
  - Removes common preamble phrases ("Here's", "Tab name:")
  - Filters lines containing "example", "message:", "rules:"
  - Removes trailing punctuation (periods, colons)
  - Reduced max length from 50 to 40 characters
- Added tests for new extraction behaviors
2026-02-02 23:58:46 -06:00
Pedram Amini
89445f1a55 Remove excessive SSH debug logging in remote-fs
The execRemoteCommand() function was logging every SSH command at
DEBUG level, which created continuous log spam when operating over
SSH connections. This log fired for every remote filesystem operation
(directory listings, file stats, reads, etc.).

The transient error retry logging is preserved so SSH connection
issues are still visible in debug output.
2026-02-02 23:55:52 -06:00
Pedram Amini
9bdbac3818 test(tab-naming): add tests for automatic tab naming in useInputProcessing
Added test suite covering:
- Triggers tab naming for new AI sessions with text messages
- Respects automaticTabNamingEnabled setting
- Skips existing sessions (with agentSessionId)
- Skips tabs with custom names
- Skips terminal mode
- Skips empty/image-only messages
- Sets isGeneratingName flag during naming
- Handles naming failures gracefully
2026-02-02 23:49:06 -06:00
Pedram Amini
0f701e4ebd refactor(tab-naming): trigger immediately on first message send
Moved tab naming logic from onSessionId callback to useInputProcessing
hook. Tab naming now starts immediately when the user sends their first
message, running in parallel with the actual agent request instead of
waiting for the agent to respond with a session ID.

Changes:
- Added automaticTabNamingEnabled prop to UseInputProcessingDeps
- Tab naming triggered in processInput for new AI sessions with text
- Removed ~140 lines of tab naming code from onSessionId handler
- Removed unused automaticTabNamingEnabledRef
2026-02-02 23:47:44 -06:00
Pedram Amini
d15e023ea9 fix(tab-naming): show spinner regardless of tab busy state
The spinner was hidden when tab.state === 'busy', but when a user sends
a message the tab immediately enters busy state. Since tab naming runs
in parallel with the main request, the spinner should show regardless
of the busy state to indicate the naming process is working.
2026-02-02 23:37:58 -06:00
Pedram Amini
3761e0cf14 fix(tab-naming): register IPC handlers for automatic tab naming
The tabNaming:generateTabName IPC handler was defined in registerAllHandlers()
but that function was never called. Instead, handlers are registered individually
in main/index.ts. Added registerTabNamingHandlers import and call with required
dependencies (processManager, agentDetector, agentConfigsStore, settingsStore).

Also removed debug console.log statements that were added during investigation.
2026-02-02 23:32:51 -06:00
Pedram Amini
3e00e81b7a ## CHANGES
- Added detailed console logs to debug automatic tab naming conditions 🧭
- Logged user message discovery and first message preview for naming 📝
- Emitted telemetry for prepared tab-naming payload before AI processing 🔍
- Logged tab-naming trigger state, including feature-flag enablement 🚦
2026-02-02 23:28:23 -06:00
Pedram Amini
c2f4afe2cd fix(tab-naming): cancel automatic naming when manual rename is triggered
When user opens the rename modal, clear isGeneratingName flag to stop
showing the spinner. Also clear the flag when the rename is confirmed
to prevent any race conditions with the automatic naming completing.
2026-02-02 23:23:05 -06:00
Pedram Amini
3a56648fc1 fix(save-markdown): refresh file list after saving chat response to disk
When users save AI chat response content to a markdown file, the file
list in the right panel was not updating to show the new file. This
made it difficult to reference or open the saved file immediately.

Added onFileSaved callback prop to SaveMarkdownModal that triggers the
file tree refresh after a successful save. The callback is passed
through TerminalOutput from MainPanel, which calls refreshFileTree
with the active session ID.
2026-02-02 23:09:56 -06:00
Pedram Amini
64e0a886b9 ## CHANGES
- Toast clicks now always reveal the AI terminal, not file previews 🧠
- Session switching clears active file preview to prevent confusing UI state 🧹
- Toast-driven navigation can target a specific AI tab when available 🎯
- Missing tab IDs fall back gracefully while still entering AI input mode 🛟
- Context usage warnings are less noisy with higher yellow threshold (75%) 🟡
- Red context warnings now trigger later at 90% for calmer workflows 🔴
2026-02-02 22:54:16 -06:00
Pedram Amini
0b97505265 fix(tabs): use performTabClose for unified close history
When closing an AI tab via Cmd+W, the keyboard handler was calling
closeTab() directly which only adds to the legacy closedTabHistory.
This meant AI tabs were not being added to unifiedClosedTabHistory,
so Cmd+Shift+T could not restore them in the correct order with
file preview tabs.

Now uses performTabClose() which properly calls addAiTabToUnifiedHistory()
to ensure both AI tabs and file tabs appear in the unified closed tab
history in the order they were closed.

Fixes tab restore order: closing AI-tab-1, file-preview-A, AI-tab-2
then pressing Cmd+Shift+T three times now correctly restores:
AI-tab-2, file-preview-A, AI-tab-1.
2026-02-02 22:51:17 -06:00
Pedram Amini
e69beb2578 fix(hamburger-menu): improve scroll behavior for limited viewport height
- Move max-height from Tailwind class to inline style for better control
- Change max-height from calc(100vh-120px) to calc(100vh-90px) to allow
  more content to be visible when screen height is limited
- Update test to check inline style instead of class pattern
2026-02-02 22:46:35 -06:00
Pedram Amini
5275933c2e fix(tabs): select tab to the left when closing a tab
When closing a tab, now selects the previous (left) tab instead of
staying at the same index position. This provides more intuitive
behavior matching browser tab behavior.

- closeTab: select tab to the left, or new first tab if closing first
- closeFileTab: same behavior for unified tab order
- Updated tests to reflect new selection behavior
2026-02-02 22:44:02 -06:00
Pedram Amini
978e3b5381 fix(notifications): skip custom notification when content is empty
Add guards in both frontend (ToastContext) and backend (notifications
handler) to prevent sending empty content to custom notification
commands. This prevents unnecessary command executions when there's
no message to send.

- ToastContext: Check if toast.message has content before calling speak
- notifications.ts: Early return if text is empty/whitespace
- Add tests for empty and whitespace-only content handling
2026-02-02 22:36:43 -06:00
Pedram Amini
e6a0faed9a fix(opencode): disable question tool to prevent batch mode hangs
The OpenCode question tool waits for stdin input when invoked, which
causes Maestro to hang indefinitely in batch mode (Auto Run) since
stdin is closed immediately after the prompt is sent.

Added `"tools":{"question":false}` to the OPENCODE_CONFIG_CONTENT
environment variable to disable the question tool. This forces the
agent to communicate questions via normal text output instead.

Root cause analysis from user debug logs:
- Auto Run batch session ran for ~10 minutes without any output
- Process had to be killed manually (0/20 tasks completed)
- OpenCode's permission config (`"*":"allow"`) doesn't prevent the
  question tool from waiting for stdin input

Testing confirmed that disabling the question tool via tools config
prevents the hang while still allowing all other permissions.
2026-02-02 22:33:24 -06:00
Pedram Amini
f5334493d0 feat(menu): add Command Palette item to hamburger menu
Add "Command Palette" menu item with CMD+K shortcut below "Introductory Tour"
in the main hamburger menu. This provides quick access to the quick actions
modal from the menu for discoverability.

- Add Command icon import from lucide-react
- Add setQuickActionOpen prop through the component chain
- Display keyboard shortcut (Cmd+K) with proper formatting
- Update tests with Command icon mock
2026-02-02 22:24:29 -06:00
Pedram Amini
8feb138f30 fix(test): update FilePreview test to use correct search placeholder
The test was looking for 'Search...' but the actual placeholder is
'Search in file... (Enter: next, Shift+Enter: prev)'. Updated to use
regex /Search in file/ pattern consistent with other tests in the file.
2026-02-02 22:02:36 -06:00
Pedram Amini
d41a7035d1 feat(filePreview): dismiss ToC overlay on Escape key press
In tab mode, the layer system isn't registered so Escape wasn't being
handled. Added explicit Escape key handling in handleKeyDown to dismiss
the ToC overlay (and search) when open. ToC is dismissed first if both
are open, matching the expected priority order.
2026-02-02 21:44:55 -06:00
Pedram Amini
8b78f2988d fix(filePreview): reset breadcrumb history when restoring closed tab
When a file preview tab is closed and later restored via Cmd+Shift+T,
the navigation history could become corrupted or stale, causing
confusing breadcrumb behavior (e.g., pressing forward navigates to
an unexpected file).

Fix by resetting the navigation history to just the current file
when restoring a tab. The restored tab will show the last viewed
file with a fresh, empty breadcrumb history.

Changes:
- Modified reopenUnifiedClosedTab() to reset navigationHistory and
  navigationIndex when restoring file tabs
- Added test case to verify navigation history is reset on restore
2026-02-02 21:13:07 -06:00
Pedram Amini
48a2741208 ## CHANGES
- File preview tab scroll now syncs into navigation history for restores 🧭
- Breadcrumb close/restore keeps the exact scroll position per history entry 📌
- Session UUID pill hides when a file preview tab is focused 🪪
- Cost tracking pill hides during file preview to reduce UI noise 💸
- Context window usage widget hides in file preview for cleaner focus 🧹
2026-02-02 21:09:02 -06:00
Pedram Amini
03d157ee54 perf: improve startup and runtime performance
Tier 1 performance optimizations for snappier app experience:

1. Lazy-load SettingsModal in App.tsx
   - SettingsModal is ~2.6K lines, now only loaded when settings opened
   - Wrapped in Suspense with conditional rendering

2. Add manual chunk splitting to vite.config.mts
   - Split vendor chunks: react, xterm, markdown, syntax, mermaid, charts, flow, diff
   - Enables better browser caching and smaller initial bundle
   - Heavy visualization libs (mermaid ~500KB, recharts ~400KB, etc.) now in separate chunks

3. Cache static files in web server (staticRoutes.ts)
   - index.html, manifest.json, sw.js now read once and cached
   - Eliminates blocking sync file reads on every web request
   - Improves web/mobile interface responsiveness
2026-02-02 20:46:25 -06:00
Pedram Amini
2fd83bdc4a feat(toggleMode): restore file preview tab when returning from terminal
When pressing cmd+j to switch between AI/terminal mode, the previously
active file preview tab is now saved and restored. This allows users
to view a file, switch to terminal, run commands, then switch back and
have the same file preview re-opened automatically.

Added preTerminalFileTabIdRef to UILayoutContext to track the active
file tab before switching to terminal mode. Updated toggleInputMode
to save/restore this state.
2026-02-02 20:46:25 -06:00
github-actions[bot]
4b2f7e046d docs: sync release notes for v0.15.0-RC 2026-02-03 02:06:32 +00:00
Pedram Amini
7c7f3be9fb ## CHANGES
- Switching to Terminal now clears file preview, avoiding confusing leftovers 🧹
- Cmd+J toggle works from file preview straight into Terminal view ⌨️
- Keyboard handler now whitelists toggleMode even with modals open, improving flow 🔓
2026-02-02 19:53:10 -06:00
Pedram Amini
d9a27c9a3f fix(FilePreview): memoize props to prevent image flickering
The FilePreview component was receiving new object/function references on
every render of MainPanel, causing unnecessary re-renders that made images
flicker. This happened because:

1. The `file` prop was an inline object literal created each render
2. All callback props (onClose, onSave, etc.) were inline arrow functions
3. The `cwd` prop used an IIFE that recalculated each render
4. The `sshRemoteId` prop used inline ternary logic

Fixed by:
- Memoizing the file object with useMemo (keyed on actual values)
- Memoizing all callbacks with useCallback
- Memoizing cwd and sshRemoteId with useMemo
- Using stable references for all FilePreview props

This ensures FilePreview only re-renders when actual data changes, not on
every parent render cycle.
2026-02-02 19:49:26 -06:00
Pedram Amini
78a93cdf24 fix(tests): ensure SaveMarkdownModal tests wait for async state updates
The tests were causing unhandled rejection errors because they weren't
waiting for the `finally` block's `setSaving(false)` to complete after
error handling. Updated waitFor assertions to also check that the save
button text returns to "Save" (from "Saving..."), ensuring all async
state updates are complete before the test ends and the component unmounts.
2026-02-02 19:44:38 -06:00
Pedram Amini
02eed05dae added AGENTS.md symlink to CLAUDE.md 2026-02-02 19:43:41 -06:00
Pedram Amini
2e114451fd Merge pull request #282 from pedramamini/0.15.0-rc
0.15.0 rc
2026-02-02 19:41:34 -06:00
Pedram Amini
616c041626 fix(tabs): scroll file preview tabs into view when selected
The TabBar scroll-into-view effect only triggered for AI tabs. Added
activeFileTabId to the useEffect dependencies so file preview tabs
are also scrolled into view when opened.
2026-02-02 19:21:47 -06:00
Pedram Amini
fc3872ea73 fix(tabs): restore file preview tabs with Cmd+Shift+T
handleCloseCurrentTab was duplicating file tab close logic inline
but not adding closed tabs to unifiedClosedTabHistory, causing
Cmd+Shift+T to restore a different tab instead of the most recently
closed one. Now uses closeFileTabHelper which properly tracks history.
2026-02-02 19:19:21 -06:00
Pedram Amini
72debe1049 refactor: remove unused legacy file preview navigation code
- App.tsx: Remove unused import (reopenClosedTab), legacy navigation
  variables (backHistory, forwardHistory, filePreviewHistory,
  filePreviewHistoryIndex), legacy callbacks (setFilePreviewHistory,
  setFilePreviewHistoryIndex), unused async handler (handleOpenFileTabAsync),
  and legacy navigation handlers (handleNavigateBack, handleNavigateForward,
  handleNavigateToIndex) - all superseded by per-tab navigation system
- MainPanel.tsx: Prefix unused destructured props with underscore
- contextUsage.ts: Remove unused UsageStats import

This removes ~250 lines of dead code from the legacy session-level
file preview navigation system, which has been replaced by the per-tab
breadcrumb navigation in the unified tab system.
2026-02-02 18:34:38 -06:00
Pedram Amini
27cb4fbb86 fix(tests): update tests for agent count, ToolType changes, and file tab system
- detector.test.ts: Update agent count from 7 to 8 (aider was added)
- session-storage.test.ts: Fix import paths for factory-droid storage
- agents.test.ts: Add AGENT_DEFINITIONS to mock for handler tests
- stats.test.ts: Remove tests for non-existent initialization handlers
- usage-aggregator.test.ts: Update DEFAULT_CONTEXT_WINDOWS test for actual ToolType values
- MainPanel.test.tsx: Migrate from previewFile prop to activeFileTabId/activeFileTab system
- contextUsage.test.ts: Update tests for current ToolType values (removed 'claude', 'aider')
- SessionStatusBanner.test.tsx: Update test for null return when tokens exceed context
- usage-listener.test.ts: Fix expected contextUsage (falls back to 200k default)
2026-02-02 18:28:38 -06:00
Pedram Amini
88e04d2f8e Merge main into 0.15.0-rc: fix context window calculation
Key changes:
- Accept main's fix for context usage calculation (returns null for
  accumulated multi-tool turn values instead of capping at 100%)
- Adopt main's refactored structure:
  - agent-detector.ts → agents/detector.ts + definitions.ts + capabilities.ts
  - stats-db.ts → stats/*.ts modules
  - agent-session-storage types → agents/index.ts
- Port factory-droid agent to new agents/definitions.ts structure
- Remove obsolete shared/contextUsage.ts (logic now in renderer/utils)
- Update all import paths to reference new module locations
- Preserve all RC features: Symphony, File Preview Tabs, TabNaming, etc.

The context window fix is critical: main's approach correctly handles
when Claude Code reports accumulated token values from multi-tool turns
by returning null, causing the UI to preserve the last valid percentage.
RC's approach masked this by capping at 100%, hiding the issue.
2026-02-02 18:03:05 -06:00
Pedram Amini
898262af4a fix(tests): fix FilePreview click-outside tests by tracking dual useClickOutside hooks
The tests were failing because FilePreview uses useClickOutside twice (once for
container dismiss, once for TOC dismiss) and the mock was only capturing the
last call. Updated the mock to track both calls separately and added proper
act() wrapping for React state updates.
2026-02-02 17:37:25 -06:00
Pedram Amini
ace8e2beaa fix(docs): standardize image paths to use ./screenshots/ format
All image references now consistently use relative ./screenshots/ paths
instead of mixed formats (some were /screenshots/ or screenshots/).
2026-02-02 17:32:12 -06:00
Pedram Amini
11721c4b95 Merge pull request #281 from pedramamini/in-tab-file-preview
In-Tab File Preview
2026-02-02 17:31:31 -06:00
Pedram Amini
d5b75092d4 MAESTRO: Fix file preview save not persisting content
After saving a file in the file preview tab, the UI was reverting to the
original content despite showing "Saved". This occurred because:
- editContent was cleared to undefined after save
- The base content field was never updated to the saved value
- UI fell back to stale original content

Added savedContent parameter to handleFileTabEditContentChange to update
the tab's base content alongside clearing editContent after save.
2026-02-02 17:30:05 -06:00
Pedram Amini
bf528bc629 fixed image path 2026-02-02 17:29:18 -06:00
Pedram Amini
d1e499e9f5 MAESTRO: Add per-tab breadcrumb navigation for file preview
- Added FilePreviewHistoryEntry type to track navigation history per tab
- Extended FilePreviewTab with navigationHistory and navigationIndex fields
- Updated handleOpenFileTab to build navigation history when replacing content
- Added handleFileTabNavigateBack/Forward/ToIndex handlers for per-tab nav
- Wired navigation props through MainPanel to FilePreview component
- Each file tab maintains its own independent navigation history
2026-02-02 17:25:10 -06:00
Raza Rauf
5373a5faa4 Merge pull request #280 from pedramamini/code-refactor
fix: correct context usage calculation to include cacheRead tokens an…
2026-02-02 17:20:27 -06:00
Pedram Amini
a7117f3d41 MAESTRO: Fix ToC blocking file content scroll
Replace backdrop-based click-outside detection with useClickOutside hook.
The previous fixed backdrop div intercepted all pointer events including
wheel events, preventing file content from scrolling while ToC was open.
Now wheel events over file content scroll the content, while wheel events
over the ToC scroll the ToC list.
2026-02-02 17:17:41 -06:00
Pedram Amini
2aa3cc701e MAESTRO: Implement file link navigation behavior
Regular click on file links replaces current tab content, while
Cmd/Ctrl+Click opens a new tab adjacent to the current tab.
2026-02-02 17:13:37 -06:00
Raza Rauf
fa4eb745ab fix: correct context usage calculation to include cacheRead tokens and handle accumulated values
The context formula was excluding cacheReadInputTokens, causing the gauge to
drastically underestimate usage (e.g., 3% when reality was 23%). During
multi-tool turns, accumulated token totals could exceed the context window,
producing false 100% readings and premature compact warnings.

- Include cacheReadInputTokens in the formula (input + cacheRead + cacheCreation)
- Detect accumulated values (total > window) and return null to preserve last valid %
- Skip context updates during accumulated turns instead of displaying inflated values
- Fix MainPanel tooltip deriving from raw tab stats instead of preserved session percentage
- Handle group chat participant/moderator accumulated values with -1 sentinel
2026-02-03 04:12:19 +05:00
Pedram Amini
cca63c3741 MAESTRO: Isolate ToC scroll from file preview content scroll
Added overscrollBehavior: 'contain' to both the main content
container and the TOC overlay's scrollable entries section. Also
added onWheel stopPropagation to the TOC entries div to fully
prevent scroll events from leaking between the ToC overlay and
the main file preview content. This prevents scroll chaining that
could cause scrollbar flickering.
2026-02-02 17:05:33 -06:00