Commit Graph

2638 Commits

Author SHA1 Message Date
chr1syy
3a0affb149 feat: prefer PowerShell and auto-detect shell scripts on Windows
Improvements to Windows shell execution for OpenCode and other shell-based tools:

1. **Binary detection priority**: Changed Windows detection to prefer extensionless
   shell scripts (like opencode) over .cmd wrappers. The .cmd files execute through
   cmd.exe which has command line length limits and less robust script handling.

2. **Auto-detect shell scripts**: Added shebang detection in ChildProcessSpawner to
   automatically enable shell execution for POSIX scripts, preventing ENOENT errors
   when trying to execute shell scripts without explicit shell.

3. **Use PowerShell by default**: Changed Windows agent execution to prefer PowerShell
   over cmd.exe when available via PSHOME environment variable. PowerShell provides:
   - Better handling of POSIX shell scripts (with shebangs)
   - Avoids cmd.exe command line length limitations
   - Better compatibility with modern tooling

   Falls back to cmd.exe if PowerShell unavailable, respects user customizations.

4. **Improved path detection**: Updated Windows path probing to correctly prefer
   .exe > extensionless scripts > .cmd in the selection order.
2026-02-05 19:49:34 +01:00
chr1syy
e65266f8d9 test: add Windows nvm4w path detection test
Verifies that nvm4w Node.js installation paths are properly included in
the expanded PATH environment on Windows, ensuring OpenCode and other
npm-installed tools are detected correctly.
2026-02-05 19:49:24 +01:00
chr1syy
32e4fc33a6 fix: add nvm4w node path detection for Windows
OpenCode installed via npm in nvm4w Node installations was not being
detected because C:\nvm4w\nodejs\ path was not included in the expanded
PATH environment. This fix adds support for nvm4w and fallback paths so
OpenCode can be properly discovered and selected as a group chat moderator.
2026-02-05 19:49:10 +01:00
chr1syy
5616e6107b fix: resolve select dropdown z-index issue in group chat modals
The native HTML select element's dropdown menu was being rendered behind
the modal overlay, making it impossible to interact with the options. This
was caused by a z-index stacking context issue where the modal's overlay
had a higher z-index than the select element.

Fixed by explicitly setting zIndex: 10000 on the select container and
select element, and zIndex: 10001 on the icon, ensuring the dropdown
renders above the modal overlay (z-index: 9999).

Fixes the issue in both NewGroupChatModal and EditGroupChatModal.
2026-02-05 19:48:25 +01:00
chr1syy
c260cc824e MAESTRO: Implement model selection for OpenCode moderator - Task 3.1
- Add customModel field to ModeratorConfig type for storing selected model
- Update NewGroupChatModal to pass agentConfig.model through moderatorConfig
- Update App.tsx handleCreateGroupChat to accept customModel parameter
- Update spawnModeratorSynthesis to pass sessionCustomModel from moderatorConfig
- Update initial moderator spawn to pass sessionCustomModel for both spawns
- Verify modelArgs config produces correct --model flag in arguments

This enables users to select a custom model when creating a group chat,
and ensures the selected model is applied when spawning the OpenCode moderator.
2026-02-05 19:47:09 +01:00
Raza Rauf
811e592076 Merge pull request #297 from pedramamini/0.15.0-polish
Round of Polishing
2026-02-04 10:06:22 -06:00
Pedram Amini
af4a6c4c93 ## CHANGES
- Symphony modal now receives sessions list for richer contribution context 🧩
- Active contributions show clickable session name with new Terminal icon 🖥️
- Added “navigate to session” flow directly from contribution cards 🧭
- Selecting a session updates active session and auto-closes modal 
- Session lookup wires contributions to matching session IDs seamlessly 🔗
2026-02-04 07:51:29 -06:00
Pedram Amini
16cf35390c let users know about how maestro works 2026-02-04 00:59:45 -06:00
Pedram Amini
f38f6b66e6 ## CHANGES
- Renamed empty-state action from “Select Folder” to “Change Folder” for clarity 🧭
- Refreshed empty-state helper text to match the new folder-change flow 📝
- Cleaned up `EditGroupChatModal` icon imports by dropping the unused `X` 🎛️
2026-02-04 00:15:13 -06:00
Pedram Amini
17fed4f232 ## CHANGES
- Added Code Style section to CLAUDE.md specifying tabs-for-indentation requirement 📏
- Added Root Cause Verification section under Debugging with historical bug patterns 🔍
- Added UI Bug Debugging Checklist to CLAUDE-PATTERNS.md (section 11) 🎨
- Documents CSS-first debugging, portal escapes, and fixed positioning pitfalls 🐛
2026-02-03 23:29:48 -06:00
Pedram Amini
a7e504e205 ## CHANGES
- Symphony IPC now validates active contributions against stored sessions 🧩
- Orphaned contributions auto-filtered when sessions disappear, keeping UI clean 🧹
- `symphony:getState` returns only session-backed active items for accuracy 🎯
- `symphony:getActive` now excludes contributions tied to missing sessions 🚫
- Added reusable `filterOrphanedContributions` helper with detailed logging 🪵
- Wired `sessionsStore` dependency through main + handler registration flow 🔌
- Integration tests now mock sessions store for realistic state scenarios 🧪
- Expanded handler tests to cover missing-session filtering behavior 🛡️
2026-02-03 23:21:06 -06:00
Pedram Amini
bcf6c4e60d ## CHANGES
- Added brand-new cross-platform guide covering Windows, Linux, macOS, SSH gotchas 🌍
- Documented SSH remote constraints: no chokidar watch, stdin prompts, path norms 🛰️
- Standardized path best-practices: `path.join`, `path.posix`, delimiters, tilde expansion 🧭
- Clarified shell execution differences: default shells, which/where lookup, permissions 🐚
- Codified agent portability quirks: session IDs, storage locations, resume flags 📦
- Introduced keyboard/input pitfalls: macOS Alt keycodes, Windows command-length limits ⌨️
- Added Git cross-platform warnings: stat differences and case-sensitivity traps 🧩
- Upgraded collaboration rules: assumptions, confusion stops, pushback, scope discipline 🤝
- Added Sentry/error-handling guidance: bubble unexpected errors, report with context 🔎
- Refreshed docs structure references to match current `src/` layout and modules 🗺️
2026-02-03 19:31:52 -06:00
Pedram Amini
d5ad08ec9f ## CHANGES
- Default OpenCode vision model now uses `ollama/qwen3-vl:latest` tagging 🏷️
- SSH integration detects remote auth failures across Claude, Codex, OpenCode 🔐
- Added remote config-error detection for missing models/providers in output 🧩
- Added remote path/environment error detection to avoid false SSH failures 🗺️
- SSH tests now skip assertions when remote paths don’t exist (expected) ⏭️
- New SSH integration test validates end-to-end image OCR via agents 🖼️
- Image SSH test auto-copies fixture to remote `/tmp` for file-based agents 📤
- IPC SSH execution switched to stdin-fed `/bin/bash` for cleaner runs 🐚
- SSH command builder now exports env + cwd via stdin script reliably 📜
- AutoRun shows Save/Revert whenever dirty (even in preview mode) 💾
- Context consumption warnings now default to disabled in settings ⚙️
2026-02-03 16:43:13 -06:00
Raza Rauf
e6ced8a77b Merge pull request #289 from pedramamini/code-refactor
feat: add conservative context growth estimation during multi-tool turns
2026-02-03 16:40:56 -06:00
Raza Rauf
4fe009e30f Merge branch 'main' into code-refactor 2026-02-04 03:35:43 +05:00
Raza Rauf
d4d94471f0 resolved merge conflicts 2026-02-04 03:27:32 +05:00
Raza Rauf
234d13ac08 Merge branch 'code-refactor' of https://github.com/pedramamini/Maestro into code-refactor 2026-02-04 03:24:31 +05:00
Pedram Amini
44e11ecf16 Merge branch 'fix-opencode'
Merges OpenCode fixes and SSH stdin improvements:
- Use stdin passthrough for all SSH prompts (simplifies escaping)
- Add question:deny to OpenCode permission block for robust tool disabling
- Simplify stdin prompt delivery by appending after exec (no heredoc needed)
2026-02-03 15:21:21 -06:00
Pedram Amini
963531e4ff ## CHANGES
- Swapped moderator selection tiles for a clean agent dropdown picker 🔽
- Added expandable “Customize” panel directly inside both group chat modals ⚙️
- Lazily loads agent config/models only when customization panel expands 🚀
- Resets custom path/args/env overrides automatically when changing agents 🧹
- Displays clear “Detecting agents…” inline spinner during agent discovery 
- Labels Codex, OpenCode, and Factory Droid options as “(Beta)” 🧪
- Expands empty-state messaging to recommend installing Factory Droid too 🧩
- Simplified modal flow by removing separate config-view navigation entirely 🧭
- Improved accessibility with proper combobox/button roles in modal controls 
- Strengthened test coverage for dropdown options and moderator-change warning 🧯
2026-02-03 15:17:25 -06:00
Pedram Amini
63d15d1a16 fix(opencode): add question:deny to permission block for robust tool disabling
Per OpenCode GitHub issue workaround, add "question": "deny" to the
permission block in addition to the existing "tools":{"question":false}.

This ensures the question tool is disabled via both configuration methods,
preventing stdin hangs in batch mode.

Config now: {"permission":{"*":"allow","external_directory":"allow","question":"deny"},"tools":{"question":false}}
2026-02-03 15:17:01 -06:00
Pedram Amini
ccabe75248 refactor(ssh): simplify stdin prompt delivery with passthrough approach
Replace heredoc-based prompt delivery with simpler stdin passthrough.

How it works:
1. Bash script is sent via stdin to /bin/bash on the remote
2. Script sets up PATH, cd, env vars, then calls `exec <agent>`
3. The `exec` replaces bash with the agent process
4. The agent inherits stdin and reads the remaining content (the prompt)

Benefits:
- No heredoc syntax needed
- No delimiter collision detection
- No prompt escaping required - prompt is never parsed by any shell
- Works with any prompt content (quotes, newlines, $, backticks, etc.)
- Simpler, more maintainable code

Changes:
- Remove heredoc logic from buildSshCommandWithStdin()
- Update process.ts to use stdin passthrough for ALL agents over SSH
  (not just OpenCode - all agents benefit from this approach)
- Update tests to verify stdin passthrough behavior

Verified locally that both OpenCode and Claude Code read prompts from stdin.
2026-02-03 15:13:55 -06:00
Raza Rauf
e409123d9e feat: add conservative context growth estimation during multi-tool turns
When Claude Code performs multi-tool turns (many internal API calls),
accumulated token values cause estimateContextUsage to return null,
freezing the context gauge. This adds estimateAccumulatedGrowth which
provides conservative 1-3% per-turn growth estimates so the gauge
keeps moving during tool-heavy sessions.

Safety: App.tsx caps all estimates at yellowThreshold - 5, guaranteeing
that estimates can never trigger compact warnings — only real
measurements from non-accumulated turns can.
2026-02-04 01:43:00 +05:00
Pedram Amini
ed374bc69d fix(dashboard): use accurate agent count excluding terminal sessions
Update SummaryCards to accept sessions prop and filter out terminal-only
sessions when calculating agent count for consistent metrics display.
This ensures queries-per-session and total sessions accurately reflect
AI agent sessions rather than including terminal sessions.
2026-02-03 14:27:30 -06:00
Pedram Amini
4bdfa86b83 fix(wizard): use navigator.platform for Windows detection in renderer
Replace process.platform with navigator.platform for Windows detection
in the inline wizard conversation service, as process.platform is not
available in the browser/renderer context.
2026-02-03 14:27:24 -06:00
Pedram Amini
078a837ef4 feat(agents): add Factory Droid to Beta badge list
Adds 'factory-droid' agent to the Beta badge display in:
- NewInstanceModal agent selection
- AgentSelectionScreen wizard tiles
2026-02-03 14:27:19 -06:00
Pedram Amini
69b6299677 fix(windows): handle full paths in known exe command detection
Fixes an issue in PR #288's Windows shell fix where full paths like
'C:\Program Files\Git\bin\git' weren't recognized as known commands.

Changes:
- Extract command basename using regex for both Unix and Windows separators
- Change from array to Set for O(1) lookup performance
- Add additional common commands: npx, pnpm, pip, pip3
- Export needsWindowsShell for testability
- Add comprehensive test suite for needsWindowsShell function
2026-02-03 14:27:03 -06:00
Pedram Amini
fb64d4a769 feat(ssh): use heredoc for stdin prompts to avoid CLI length limits
IMPORTANT: Prompts must be passed via stdin to avoid CLI argument length
limits. Prompts can be huge and contain arbitrary characters that would
break if passed as command-line arguments.

Changes:
- Add stdinInput parameter to buildSshCommandWithStdin for heredoc-based
  prompt delivery
- Use MAESTRO_PROMPT_EOF delimiter with collision detection (appends _N
  suffix if prompt contains the delimiter)
- OpenCode prompts now always sent via stdin heredoc, not CLI args
- Add comprehensive tests for heredoc behavior and delimiter collision
- Add comment in process.ts documenting this requirement to prevent
  regressions

The heredoc approach: exec opencode 'run' <<'MAESTRO_PROMPT_EOF'
ensures prompts of any size with any characters work correctly.
2026-02-03 14:26:25 -06:00
Pedram Amini
3d593719fb fix(ssh): use stdin-based execution to bypass shell escaping issues
This is a complete rewrite of SSH remote command execution that eliminates
all shell escaping issues by sending the entire script via stdin.

Previously, the SSH command was built as:
  ssh host '/bin/bash -c '\''cd /path && VAR='\''value'\'' cmd arg'\'''

This required complex nested escaping that broke with:
- Heredocs (cat << 'EOF')
- Long prompts (command line length limits)
- Special characters in prompts

Now the SSH command is simply:
  ssh host /bin/bash

And the entire script is piped via stdin:
  export PATH="$HOME/.local/bin:..."
  cd '/project/path'
  export OPENCODE_CONFIG_CONTENT='{"permission":...}'
  exec opencode run --format json 'prompt here'

Benefits:
- No shell escaping layers (stdin is binary-safe)
- No command line length limits
- Works with any remote shell (bash, zsh, fish)
- Handles any prompt content (quotes, newlines, $, etc.)
- Much simpler to debug and maintain

Changes:
- Add buildSshCommandWithStdin() in ssh-command-builder.ts
- Update process.ts to use stdin-based SSH for all agents
- Add sshStdinScript to ProcessConfig type
- Update ChildProcessSpawner to send stdin script
- Add comprehensive tests for new function
2026-02-03 14:26:25 -06:00
Pedram Amini
09aa978932 fix(ssh): remove heredoc approach for OpenCode prompts
The heredoc syntax (cat << 'EOF' ... EOF) was breaking when passed
through buildSshCommand's single-quote escaping. The '\'' escape
pattern was being applied to the heredoc delimiters, producing
invalid shell syntax like cat << '\''EOF'\''.

Solution: Embed OpenCode prompts directly as positional arguments.
The prompt will be properly escaped by buildRemoteCommand using
shellEscape(), which handles the single-quote escaping correctly
for bash -c command execution.

This was the root cause of SSH remote execution failures with
OpenCode - the OPENCODE_CONFIG_CONTENT env var escaping was
correct, but the heredoc escaping was not.
2026-02-03 14:26:24 -06:00
Pedram Amini
7be82ce338 fix(tab-bar): ensure full tab visibility when scrolling into view
Changed from centering the tab to using scrollIntoView with 'nearest' option.
This ensures the entire tab including the close button is visible, rather than
potentially cutting off the right edge when near container boundaries.
2026-02-03 14:26:24 -06:00
Pedram Amini
99f4257c17 feat(symphony): add manual contribution credit handler
Add symphony:manualCredit IPC handler to allow crediting contributions
made outside the Symphony workflow (e.g., manual PRs, external
contributors). This enables proper tracking of all contributions
regardless of how they were created.

- Add symphony:manualCredit handler with full validation
- Add preload API for manual credit
- Support all contribution fields (tokens, time, merged status, etc.)
- Prevent duplicate PR credits
- Update contributor stats (streak, repos, totals)
- Add comprehensive tests for validation and success cases
2026-02-03 14:26:24 -06:00
Pedram Amini
81c64d9858 Merge pull request #288 from chr1syy/main
fix(windows): Shell interpration of % in git log format string
2026-02-03 14:25:35 -06:00
Raza Rauf
7d76a5a06d feat: add conservative context growth estimation during multi-tool turns
When Claude Code performs multi-tool turns (many internal API calls),
accumulated token values cause estimateContextUsage to return null,
freezing the context gauge. This adds estimateAccumulatedGrowth which
provides conservative 1-3% per-turn growth estimates so the gauge
keeps moving during tool-heavy sessions.

Safety: App.tsx caps all estimates at yellowThreshold - 5, guaranteeing
that estimates can never trigger compact warnings — only real
measurements from non-accumulated turns can.
2026-02-04 01:20:51 +05:00
Chris
a9e725b9e7 Merge branch 'pedramamini:main' into main 2026-02-03 19:41:00 +01:00
chr1syy
2f5c74480f fix: Windows shell interpretation of % in git log format string
On Windows, when execFile detects 'git' without extension, it enables shell
mode for PATHEXT resolution. However, shell mode interprets '%' characters in
arguments as environment variable expansions, causing 'git log --pretty=format:%an'
to fail with 'Der Befehl "%an" ist entweder falsch geschrieben...'

The fix adds 'git' (and other known .exe commands) to a list of exceptions
that don't require shell mode, allowing the format string to pass through
to git unchanged. This works because these commands have .exe variants on
Windows and don't need PATHEXT resolution.
2026-02-03 19:37:07 +01:00
Pedram Amini
fc7880cc32 feat(ssh): use heredoc for stdin prompts to avoid CLI length limits
IMPORTANT: Prompts must be passed via stdin to avoid CLI argument length
limits. Prompts can be huge and contain arbitrary characters that would
break if passed as command-line arguments.

Changes:
- Add stdinInput parameter to buildSshCommandWithStdin for heredoc-based
  prompt delivery
- Use MAESTRO_PROMPT_EOF delimiter with collision detection (appends _N
  suffix if prompt contains the delimiter)
- OpenCode prompts now always sent via stdin heredoc, not CLI args
- Add comprehensive tests for heredoc behavior and delimiter collision
- Add comment in process.ts documenting this requirement to prevent
  regressions

The heredoc approach: exec opencode 'run' <<'MAESTRO_PROMPT_EOF'
ensures prompts of any size with any characters work correctly.
2026-02-03 12:15:49 -06:00
Pedram Amini
07df61fbcf fix(ssh): use stdin-based execution to bypass shell escaping issues
This is a complete rewrite of SSH remote command execution that eliminates
all shell escaping issues by sending the entire script via stdin.

Previously, the SSH command was built as:
  ssh host '/bin/bash -c '\''cd /path && VAR='\''value'\'' cmd arg'\'''

This required complex nested escaping that broke with:
- Heredocs (cat << 'EOF')
- Long prompts (command line length limits)
- Special characters in prompts

Now the SSH command is simply:
  ssh host /bin/bash

And the entire script is piped via stdin:
  export PATH="$HOME/.local/bin:..."
  cd '/project/path'
  export OPENCODE_CONFIG_CONTENT='{"permission":...}'
  exec opencode run --format json 'prompt here'

Benefits:
- No shell escaping layers (stdin is binary-safe)
- No command line length limits
- Works with any remote shell (bash, zsh, fish)
- Handles any prompt content (quotes, newlines, $, etc.)
- Much simpler to debug and maintain

Changes:
- Add buildSshCommandWithStdin() in ssh-command-builder.ts
- Update process.ts to use stdin-based SSH for all agents
- Add sshStdinScript to ProcessConfig type
- Update ChildProcessSpawner to send stdin script
- Add comprehensive tests for new function
2026-02-03 12:15:49 -06:00
Pedram Amini
3a8dd62a13 fix(ssh): remove heredoc approach for OpenCode prompts
The heredoc syntax (cat << 'EOF' ... EOF) was breaking when passed
through buildSshCommand's single-quote escaping. The '\'' escape
pattern was being applied to the heredoc delimiters, producing
invalid shell syntax like cat << '\''EOF'\''.

Solution: Embed OpenCode prompts directly as positional arguments.
The prompt will be properly escaped by buildRemoteCommand using
shellEscape(), which handles the single-quote escaping correctly
for bash -c command execution.

This was the root cause of SSH remote execution failures with
OpenCode - the OPENCODE_CONFIG_CONTENT env var escaping was
correct, but the heredoc escaping was not.
2026-02-03 12:15:49 -06:00
Pedram Amini
4ae5d86a05 fix(tab-bar): ensure full tab visibility when scrolling into view
Changed from centering the tab to using scrollIntoView with 'nearest' option.
This ensures the entire tab including the close button is visible, rather than
potentially cutting off the right edge when near container boundaries.
2026-02-03 12:15:49 -06:00
Pedram Amini
b4c5f155ed feat(symphony): add manual contribution credit handler
Add symphony:manualCredit IPC handler to allow crediting contributions
made outside the Symphony workflow (e.g., manual PRs, external
contributors). This enables proper tracking of all contributions
regardless of how they were created.

- Add symphony:manualCredit handler with full validation
- Add preload API for manual credit
- Support all contribution fields (tokens, time, merged status, etc.)
- Prevent duplicate PR credits
- Update contributor stats (streak, repos, totals)
- Add comprehensive tests for validation and success cases
2026-02-03 12:15:49 -06:00
Raza Rauf
802ecd52a1 Merge pull request #287 from pedramamini/code-refactor
fix(file-preview): resolve image flickering under heavy parallel agen…
2026-02-03 10:58:43 -06:00
Raza Rauf
6e36f6b63f fix(file-preview): stabilize fileTree prop to complete memoization chain
The fileTree prop was passed as `activeSession?.fileTree || []` which
creates a new array reference on every render, defeating React.memo()
on FilePreview during agent activity. Memoize it with useMemo so the
reference only changes when the actual fileTree changes.
2026-02-03 21:46:07 +05:00
Raza Rauf
2f8a77a65d fix(file-preview): resolve image flickering under heavy parallel agent load
Wrap FilePreview and MarkdownImage with React.memo to prevent unnecessary
re-renders caused by upstream state updates from running agents.
2026-02-03 21:31:34 +05:00
Pedram Amini
2cd882ed7b Merge pull request #286 from chr1syy/main
Add @chr1syy as Windows Contributor and tester
2026-02-03 09:24:34 -06:00
Chris
00016e2342 Add @chr1syy as Windows Contributor and tester 2026-02-03 15:34:37 +01:00
Pedram Amini
2fcd03eb44 Remove duplicate Contributors section
Removed redundant 'Contributors' header from README.
2026-02-03 06:52:54 -06:00
Pedram Amini
afaead2220 Add contributors section to README 2026-02-03 06:52:40 -06:00
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