-
Notifications
You must be signed in to change notification settings - Fork 294
🏎️ Rrrralphy: Multi-Engine Support for Maximum Speed #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
🏎️ Rrrralphy: Multi-Engine Support for Maximum Speed #38
Conversation
Added comprehensive multi-engine support configuration after line 85: - ENGINES array: stores engines for rotation - ENGINE_DISTRIBUTION: pattern string (e.g., "claude:2,opencode:1") - ENGINE_WEIGHTS: associative array for engine priority - ENGINE_AGENT_COUNT: tracks agents assigned per engine - ENGINE_COSTS: tracks total cost per engine - ENGINE_SUCCESS: tracks success count per engine - ENGINE_FAILURES: tracks failure count per engine - VALID_ENGINES: array with claude, opencode, cursor, codex, qwen, droid These variables enable multi-engine distribution and performance tracking in parallel execution mode, supporting the upcoming sprint work for multi-engine task distribution and analytics. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Added ENGINES array and ENGINE_WEIGHTS associative array declarations - Implemented --engines argument in parse_args() around line 712 - Parses comma-separated list of engines into ENGINES array - Supports weight syntax: engine:weight (e.g., claude:5, opencode:10) - Validates that weights are positive integers (> 0) - Defaults to weight of 1 for engines without explicit weight - Supports alphanumeric engine names with hyphens and underscores - Provides clear error messages for invalid specifications Test coverage: - Created test_engines_parsing.sh with 12 comprehensive test cases - All tests validate regex patterns, parsing logic, and error handling - Tests passed successfully Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit implements the --engine-distribution CLI argument in parse_args() that accepts four distribution strategies: round-robin, weighted, random, or fill-first. The argument sets the ENGINE_DISTRIBUTION variable which defaults to "round-robin". Changes: - Added ENGINE_DISTRIBUTION variable to configuration defaults (ralphy.sh:47) - Implemented --engine-distribution argument parsing with validation (ralphy.sh:738-753) - Validates that the value is one of the four accepted strategies - Provides clear error messages for invalid or missing values - Added test script to verify functionality (test_engine_distribution.sh) - Updated .ralphy/progress.txt with implementation details Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add multi-engine configuration variables (ENGINES array, ENGINE_DISTRIBUTION, ENGINE_WEIGHTS, ENGINE_AGENT_COUNT, ENGINE_COSTS, ENGINE_SUCCESS, ENGINE_FAILURES, and VALID_ENGINES array) - Implement append_engine() helper function with deduplication logic - Modify all engine flags (--claude, --cursor, --opencode, --codex, --qwen, --droid) to call append_engine() instead of setting AI_ENGINE directly - Handle --cursor/--agent alias properly: both append "cursor" to avoid duplicates - Add comprehensive test suite with 8 tests covering: - Single engine flag - Multiple different engines - Duplicate engine flags - --cursor/--agent alias deduplication - Mixed scenarios with cursor aliases - All engines together - All tests passing This prepares ralphy for multi-engine parallel execution while maintaining backward compatibility with AI_ENGINE variable. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit implements the validate_engines() function that: - Checks engines are in VALID_ENGINES list - Verifies CLI commands exist (claude, opencode, agent, codex, qwen, droid) - Maps cursor engine to 'agent' CLI command - Warns about missing CLI commands - Filters ENGINES array to only available engines - Returns errors for invalid engines or when no engines are available Also added: - Multi-engine configuration variables (ENGINES, ENGINE_WEIGHTS, etc.) - VALID_ENGINES array with supported engines - Comprehensive test suite (test_validate_engines.sh) - Progress documentation in .ralphy/progress.txt Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented backward compatibility logic at the end of parse_args() to ensure seamless transition between single-engine and multi-engine usage: - If exactly one engine is specified: set AI_ENGINE to that engine - If no engines are specified: populate ENGINES with default AI_ENGINE - If multiple engines: no modification (multi-engine mode) This maintains compatibility with existing workflows that use single engine flags (--claude, --opencode, etc.) while enabling new multi-engine functionality. Changes: - ralphy.sh: Added backward compatibility logic after parse_args() - ralphy.sh: Set ENGINE_DISTRIBUTION default to "round-robin" - ralphy.sh: Removed duplicate ENGINES/ENGINE_WEIGHTS declarations - test_backward_compatibility.sh: Comprehensive test suite with 9 tests All tests pass successfully. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add multi-engine configuration variables and implement the get_engine_for_agent() function that distributes agents across engines using round-robin strategy (agent_num % engine_count). Changes: - Added ENGINES array and related tracking variables (ENGINE_WEIGHTS, ENGINE_AGENT_COUNT, ENGINE_COSTS, ENGINE_SUCCESS, ENGINE_FAILURES) - Added VALID_ENGINES array with supported engine names - Implemented get_engine_for_agent() function with round-robin logic - Created comprehensive test suite with 6 test cases (all passing) - Updated .ralphy/progress.txt with implementation details The function takes a 0-based agent number and returns the appropriate engine name using modulo operation for even distribution. Falls back to AI_ENGINE default when ENGINES array is empty. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement display of parsed engines in dry-run output showing distribution strategy and engine list with weights (Task 7 of multi-engine implementation). Changes: - Created display_engines_config() function to show engine configuration with weights and distribution strategy explanation - Updated main banner to use display_engines_config() for consistent formatting - Added dry-run handling in run_parallel_tasks() that displays: * Engine distribution configuration * Task assignment preview (first 10 tasks) with simulated engine assignments * Complete list of tasks to be executed - Maintains backward compatibility with single-engine mode - Created test_dry_run_display.sh for manual verification The implementation assumes ENGINES array, ENGINE_DISTRIBUTION, and ENGINE_WEIGHTS variables exist (from tasks 1-6), and gracefully degrades when they are not set. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented serialization and deserialization functions to pass ENGINE_WEIGHTS and multi-engine configuration through environment variables to subshells, addressing the limitation that Bash associative arrays cannot be exported to subshells. Changes: - Added multi-engine configuration variables (ENGINES, ENGINE_WEIGHTS, ENGINE_AGENT_COUNT, ENGINE_SUCCESS, ENGINE_FAILURES, ENGINE_COSTS) - Implemented serialize_engine_config() to convert arrays to environment variables using comma-separated and pipe-delimited formats - Implemented deserialize_engine_config() to reconstruct arrays in subshells from serialized environment variables - Created comprehensive test documentation in test_engine_serialization.md - Updated .ralphy/progress.txt with implementation details Serialization format: - Indexed arrays: comma-separated (e.g., "claude,cursor,opencode") - Associative arrays: pipe-delimited key:value pairs (e.g., "claude:2|cursor:3|opencode:1") Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…parse-args' into ralphy/agent-11-add-random-distribution-strategy-to-get-engine-for # Conflicts: # .ralphy/progress.txt
Add multi-engine configuration variables and implement the get_engine_for_agent() function that distributes agents across engines using round-robin strategy (agent_num % engine_count). Changes: - Added ENGINES array and related tracking variables (ENGINE_WEIGHTS, ENGINE_AGENT_COUNT, ENGINE_COSTS, ENGINE_SUCCESS, ENGINE_FAILURES) - Added VALID_ENGINES array with supported engine names - Implemented get_engine_for_agent() function with round-robin logic - Created comprehensive test suite with 6 test cases (all passing) - Updated .ralphy/progress.txt with implementation details The function takes a 0-based agent number and returns the appropriate engine name using modulo operation for even distribution. Falls back to AI_ENGINE default when ENGINES array is empty. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…n-parse-ar' into ralphy/agent-11-add-random-distribution-strategy-to-get-engine-for # Conflicts: # .ralphy/progress.txt
…de-codex-q' into ralphy/agent-11-add-random-distribution-strategy-to-get-engine-for # Conflicts: # .ralphy/progress.txt # ralphy.sh
…t-parsing-' into ralphy/agent-11-add-random-distribution-strategy-to-get-engine-for # Conflicts: # .ralphy/progress.txt # ralphy.sh
…-checks-en' into ralphy/agent-11-add-random-distribution-strategy-to-get-engine-for # Conflicts: # .ralphy/progress.txt # ralphy.sh
…-showing-d' into ralphy/agent-11-add-random-distribution-strategy-to-get-engine-for # Conflicts: # .ralphy/progress.txt # ralphy.sh
…ialize-eng' into ralphy/agent-11-add-random-distribution-strategy-to-get-engine-for # Conflicts: # .ralphy/progress.txt
…with-round' into ralphy/agent-11-add-random-distribution-strategy-to-get-engine-for # Conflicts: # .ralphy/progress.txt # ralphy.sh
Implement fill-first distribution strategy that fills engines sequentially before moving to the next engine. Changes: - Modified get_engine_for_agent() to accept optional total_agents parameter - Added case statement to support multiple distribution strategies - Implemented fill-first strategy with agents_per_engine calculation - Formula: agents_per_engine = ceil(total_agents / engine_count) - Engine assignment: engine_index = agent_num / agents_per_engine - Falls back to round-robin when total_agents not provided - Handles edge cases (more engines than agents, out of bounds) Test Coverage: - Added 8 comprehensive test cases for fill-first distribution - Tests cover even/uneven distributions, edge cases, and fallback behavior - All 14 test cases pass successfully (6 round-robin + 8 fill-first) Example with 3 engines and 10 agents: - agents_per_engine = 4 - Agents 0-3 → engine 0 - Agents 4-7 → engine 1 - Agents 8-9 → engine 2 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented random distribution strategy for multi-engine support: - Modified get_engine_for_agent() to use case statement for distribution strategies - When ENGINE_DISTRIBUTION="random", uses RANDOM % engine_count for selection - Maintains backward compatibility with round-robin as default strategy - Each agent receives a randomly selected engine from the ENGINES array Created comprehensive test suite (test_random_distribution.sh): - Validates random distribution returns only valid engines - Tests single engine configuration with random distribution - Verifies all engines are eventually selected over 100 samples - Tests switching between round-robin and random strategies - Confirms empty ENGINES array fallback to default AI_ENGINE - All tests pass successfully Updated .ralphy/progress.txt with implementation details and merged work. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements the weighted distribution strategy for get_engine_for_agent() that expands engines by weight and cycles through the expanded array. Changes: - Added multi-engine configuration variables (ENGINES, ENGINE_WEIGHTS, etc.) - Implemented expand_engines_by_weight() to create weighted engine array - Implemented get_engine_for_agent() with support for multiple strategies: * round-robin: cycles through engines evenly * weighted: expands engines by weight and cycles through expanded array * random: random selection from engines * fill-first: placeholder for future implementation Weighted distribution algorithm: - Each engine is added to EXPANDED_ENGINES array N times (N = weight) - Agents cycle through EXPANDED_ENGINES using modulo arithmetic - Example: engines=[claude:2, opencode:1] creates [claude, claude, opencode] - Ensures proportional distribution matching specified weights Testing: - Added test_weighted_distribution.sh with comprehensive test cases - Added verify_weighted_distribution.sh for structure verification - All verifications pass successfully Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add engine as third parameter to run_parallel_agent() function - Create get_engine_for_agent() function that returns engine for agent number - Implements round-robin distribution across ENGINES array - Falls back to AI_ENGINE when ENGINES not set - Create deserialize_engine_config() stub for future engine config passing - Update call site to pass get_engine_for_agent() result - Set AI_ENGINE in subshell to ensure correct engine per agent - Write engine to status file for monitoring - Log engine in agent header for debugging This enables multi-engine support in parallel execution while maintaining backward compatibility with single-engine setups. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit implements engine tracking infrastructure for multi-engine
parallel execution support:
1. Added multi-engine configuration variables (lines 88-96):
- ENGINES array for enabled engines
- ENGINE_DISTRIBUTION for strategy selection
- ENGINE_WEIGHTS associative array for weighted distribution
- ENGINE_AGENT_COUNT, ENGINE_SUCCESS, ENGINE_FAILURES, ENGINE_COSTS
for per-engine metrics tracking
- VALID_ENGINES array defining supported engines
2. Implemented serialize_engine_config() function (lines 129-143):
- Converts ENGINE_WEIGHTS associative array to serialized string
- Exports as environment variables for subshell propagation
- Format: "engine1:weight1,engine2:weight2,..."
3. Implemented deserialize_engine_config() function (lines 145-156):
- Restores ENGINE_WEIGHTS from serialized environment variable
- Enables engine configuration access in subshells
4. Initialize tracking arrays in run_parallel_tasks() (lines 2194-2211):
- Declares global tracking associative arrays
- Initializes counters to 0 for all engines
- Calls serialize_engine_config() to prepare for subshells
Technical notes:
- Uses declare -gA for global associative array declarations
- Handles empty ENGINES array gracefully
- Ready for integration with get_engine_for_agent() and
run_parallel_agent()
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented engine assignment preview table showing agent number, task name, and assigned engine for the first 10 tasks. This feature helps visualize how tasks will be distributed across multiple engines in parallel execution. Changes: - Added multi-engine infrastructure (ENGINES array, ENGINE_DISTRIBUTION) - Implemented get_engine_for_agent() with round-robin distribution - Created print_engine_assignment_preview() to display assignment table - Integrated preview into run_parallel_tasks() function - Added backward compatibility to populate ENGINES with default AI_ENGINE - Table shows color-coded engine names and truncates long task names - Only displays when multiple engines are configured or in dry-run mode Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Modified status file format to include engine information and updated monitoring loop to parse it using grep. This enables engine tracking for each agent during parallel execution. Changes: - Extended status file format with engine= line - Updated all status writes to include engine info - Modified monitoring loop to parse engine with grep - Status read changed from cat to head -n 1 for first line only - Added grep to extract engine from status file The engine variable is now available in the monitoring loop for future features like engine-specific status display and per-engine metrics. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Updated the status display format for parallel agents to show the engine name alongside the agent number: "Agent N (engine): status" Changes: - Added get_engine_short_name() helper function to get engine display name - Updated initial agent status display to include engine name - Updated final agent status display to include engine name - Updated failed agent log header to include engine name - Created test suite with 7 passing tests for all supported engines This provides better visibility when running parallel agents with different AI engines, making it clear which engine is handling each task. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Created reusable display_agent_status() function (ralphy.sh:2152-2214) that accepts arrays of PIDs, status file paths, batch size, and start time - Replaced 57 lines of inline monitoring code with clean 2-line function call - Added comprehensive test suite (test_display_agent_status.sh) with 6 tests - Updated .ralphy/progress.txt with implementation details Benefits: - Eliminates code duplication - Improves maintainability - Provides reusable monitoring for future parallel execution needs - All tests pass successfully Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ne merge - Remove duplicate validate_engines(), get_engine_for_agent(), print_engine_summary(), deserialize_engine_config() - Consolidate multiple multi-engine configuration blocks into single block - Keep most complete implementation of each function - Script now has 73 unique functions and passes bash syntax check Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Implement worker pool for parallel execution: tasks are now dynamically claimed from a queue, so no engine sits idle while work remains - Add --multi-engine flag to auto-detect and use all available AI engines - Add --detect-engines flag to show available engines on the system - Replace flock with portable mkdir-based locking for macOS compatibility - Update banner to show multi-engine configuration when active - Fix backward compatibility to not interfere with multi-engine detection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
@zkwentz is attempting to deploy a commit to the Goshen Labs Team on Vercel. A member of the Team first needs to authorize it. |
Greptile OverviewGreptile SummaryThis PR adds comprehensive multi-engine support to Ralphy, enabling parallel task execution across multiple AI engines (Claude, OpenCode, Cursor, Codex, Qwen, Droid) using a worker pool pattern. Key Changes:
Issues Found:
Resolved from Previous Reviews:
The implementation is well-structured with excellent documentation and test coverage. The worker pool pattern is a solid design choice for dynamic task distribution. The main blocker is the distribution strategy bug in the worker pool. Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant Main as ralphy.sh (main)
participant Queue as Task Queue
participant W1 as Worker 1
participant W2 as Worker 2
participant W3 as Worker 3
participant Engine1 as Claude
participant Engine2 as OpenCode
participant Engine3 as Cursor
User->>Main: ./ralphy.sh --multi-engine --parallel
Main->>Main: detect_available_engines()
Main->>Main: serialize_engine_config()
Main->>Queue: task_queue_init(tasks)
Main->>Queue: Write all tasks to queue file
par Spawn Workers
Main->>W1: run_worker(1) &
Main->>W2: run_worker(2) &
Main->>W3: run_worker(3) &
end
W1->>W1: deserialize_engine_config()
W2->>W2: deserialize_engine_config()
W3->>W3: deserialize_engine_config()
loop Worker Pool Pattern
W1->>Queue: task_queue_claim() [atomic lock]
Queue-->>W1: Task A
W1->>W1: get_next_engine_atomic()
W1->>Engine1: run_parallel_agent(Task A, claude)
W2->>Queue: task_queue_claim() [atomic lock]
Queue-->>W2: Task B
W2->>W2: get_next_engine_atomic()
W2->>Engine2: run_parallel_agent(Task B, opencode)
W3->>Queue: task_queue_claim() [atomic lock]
Queue-->>W3: Task C
W3->>W3: get_next_engine_atomic()
W3->>Engine3: run_parallel_agent(Task C, cursor)
Engine1-->>W1: Result (success/failure)
W1->>Queue: Store result file
W1->>Queue: task_queue_claim() [next task]
Queue-->>W1: Task D
W1->>Engine1: run_parallel_agent(Task D, claude)
Engine2-->>W2: Result
W2->>Queue: Store result file
W2->>Queue: task_queue_claim()
Queue-->>W2: (empty - exit)
Engine3-->>W3: Result
W3->>Queue: Store result file
W3->>Queue: task_queue_claim()
Queue-->>W3: Task E
end
Main->>Main: Monitor worker_pids (wait)
Main->>Queue: Collect all result files
Main->>Main: print_engine_summary()
Main-->>User: Multi-engine execution complete
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
31 files reviewed, 14 comments
| test_error "Invalid weight (non-numeric)" --engines claude:abc --dry-run | ||
|
|
||
| # Test 4: Invalid weight format (negative) | ||
| echo "=== Test 4: Invalid weight format (zero) ===" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
syntax: Comment mentions 'negative' but test description says 'zero' - should clarify which invalid weight case this tests
Prompt To Fix With AI
This is a comment left during a code review.
Path: test_error_messages.sh
Line: 44:44
Comment:
**syntax:** Comment mentions 'negative' but test description says 'zero' - should clarify which invalid weight case this tests
How can I resolve this? If you propose a fix, please make it concise.| ENGINE_AGENT_COUNT["claude"]=50 | ||
| ENGINE_SUCCESS["claude"]=45 | ||
| ENGINE_FAILURES["claude"]=5 | ||
| ENGINE_COSTS["claude"]=2.5678 | ||
|
|
||
| ENGINE_AGENT_COUNT["opencode"]=30 | ||
| ENGINE_SUCCESS["opencode"]=28 | ||
| ENGINE_FAILURES["opencode"]=2 | ||
| ENGINE_COSTS["opencode"]=1.2345 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Test 5 overwrites the claude and opencode data from previous tests, which could mask issues if the function doesn't handle data updates correctly.
Prompt To Fix With AI
This is a comment left during a code review.
Path: test_print_engine_summary.sh
Line: 86:94
Comment:
**logic:** Test 5 overwrites the claude and opencode data from previous tests, which could mask issues if the function doesn't handle data updates correctly.
How can I resolve this? If you propose a fix, please make it concise.| if [[ ${#ENGINES[@]} -eq 0 ]] && [[ "$MULTI_ENGINE" != true ]]; then | ||
| ENGINES=("$AI_ENGINE") | ||
|
|
||
| # Load browser setting from config (if not overridden by CLI flag) | ||
| if [[ "$BROWSER_ENABLED" == "auto" ]] && [[ -f "$CONFIG_FILE" ]]; then | ||
| BROWSER_ENABLED=$(load_browser_setting) | ||
|
|
||
| fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
syntax: syntax error in conditional structure - missing 'fi' to close the if statement started on line 4154
| if [[ ${#ENGINES[@]} -eq 0 ]] && [[ "$MULTI_ENGINE" != true ]]; then | |
| ENGINES=("$AI_ENGINE") | |
| # Load browser setting from config (if not overridden by CLI flag) | |
| if [[ "$BROWSER_ENABLED" == "auto" ]] && [[ -f "$CONFIG_FILE" ]]; then | |
| BROWSER_ENABLED=$(load_browser_setting) | |
| fi | |
| # Backward compatibility: populate ENGINES if not set | |
| # Skip if using --multi-engine (it will auto-detect) | |
| if [[ ${#ENGINES[@]} -eq 0 ]] && [[ "$MULTI_ENGINE" != true ]]; then | |
| ENGINES=("$AI_ENGINE") | |
| fi | |
| # Load browser setting from config (if not overridden by CLI flag) | |
| if [[ "$BROWSER_ENABLED" == "auto" ]] && [[ -f "$CONFIG_FILE" ]]; then | |
| BROWSER_ENABLED=$(load_browser_setting) | |
| fi |
Prompt To Fix With AI
This is a comment left during a code review.
Path: ralphy.sh
Line: 4154:4161
Comment:
**syntax:** syntax error in conditional structure - missing 'fi' to close the if statement started on line 4154
```suggestion
# Backward compatibility: populate ENGINES if not set
# Skip if using --multi-engine (it will auto-detect)
if [[ ${#ENGINES[@]} -eq 0 ]] && [[ "$MULTI_ENGINE" != true ]]; then
ENGINES=("$AI_ENGINE")
fi
# Load browser setting from config (if not overridden by CLI flag)
if [[ "$BROWSER_ENABLED" == "auto" ]] && [[ -f "$CONFIG_FILE" ]]; then
BROWSER_ENABLED=$(load_browser_setting)
fi
```
How can I resolve this? If you propose a fix, please make it concise.Resolve git merge conflicts in three test files that were preventing execution: - test_backward_compatibility.sh: Keep comprehensive 14-test suite - test_get_engine_for_agent.sh: Merge round-robin and fill-first tests - test_load_parallel_config.sh: Keep integration test with proper setup/teardown All tests now pass. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix missing `fi` in ralphy.sh main() causing syntax error - Fix comment/test name mismatch in test_error_messages.sh - Add safe default for unset associative array key check in test_record_agent_result.sh - Properly reset associative arrays between tests in test_weighted_distribution.sh Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The check now verifies expand_engines_by_weight is called within the weighted distribution case block, not just that it exists somewhere in the file. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Immediately restore IFS to default after the comma-separated read to avoid affecting global state. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
test_print_engine_summary.sh: - Inline function definition instead of fragile grep-based sourcing - Add reset_engine_data() helper to clear arrays between tests - Each test now starts with clean state test_get_engine_color.sh: - Add comments explaining intentional inline definitions for test isolation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
@greptile give it another look please |
Greptile's behavior is changing!From now on, if a review finishes with no comments, we will not post an additional "statistics" comment to confirm that our review found nothing to comment on. However, you can confirm that we reviewed your changes in the status check section. This feature can be toggled off in your Code Review Settings by deselecting "Create a status check for each PR". |
|
Going to review this in the AM. Good stuff @zkwentz |
|
I'd love a variation on this where I can use an engine like Claude Code and then once I hit my daily usage limit I can specify a failover engine to switch to GLM in OpenCode, for example |
|
That was sort of the spirit behind this. In practice this pool approach isn't working all that well due to merge conflicts and need for isolated tasks. I'd be fine to rework this in the spirit of quota conservation which was original goal anyway. The only thing I can see being practical here is a sort of cheap multi engine approach with expensive overseer taking best implementation from the group (i.e. GRPO applied to test time). Probably worth landing the conservation first, and consensus second using this as starting point but ultimately abandoning this one but for key functionality. |
|
Makes sense. I was definitely thinking of simple failover more than pooling. Quota conservation to avoid hitting the limit is also interesting but may also be more complicated than necessary, |
|
@greptile review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 file reviewed, 1 comment
| get_next_engine_atomic() { | ||
| local engine_count=${#ENGINES[@]} | ||
|
|
||
| # If no engines configured or only one, return default/single | ||
| if [[ $engine_count -eq 0 ]]; then | ||
| echo "$AI_ENGINE" | ||
| return | ||
| fi | ||
|
|
||
| if [[ $engine_count -eq 1 ]]; then | ||
| echo "${ENGINES[0]}" | ||
| return | ||
| fi | ||
|
|
||
| local lock_dir="${ENGINE_COUNTER_FILE}.lock.dir" | ||
|
|
||
| # Acquire lock | ||
| if ! acquire_lock "$lock_dir"; then | ||
| # Fallback to first engine if lock fails | ||
| echo "${ENGINES[0]}" | ||
| return | ||
| fi | ||
|
|
||
| local counter | ||
| counter=$(cat "$ENGINE_COUNTER_FILE" 2>/dev/null || echo "0") | ||
| local index=$((counter % engine_count)) | ||
|
|
||
| # Increment counter for next call | ||
| echo $((counter + 1)) > "$ENGINE_COUNTER_FILE" | ||
|
|
||
| # Release lock | ||
| release_lock "$lock_dir" | ||
|
|
||
| echo "${ENGINES[$index]}" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get_next_engine_atomic() only implements round-robin distribution and ignores the ENGINE_DISTRIBUTION setting. When users specify --engine-distribution weighted, random, or fill-first, the worker pool will still use round-robin.
The function should check ENGINE_DISTRIBUTION and implement the selected strategy atomically, similar to how get_engine_for_agent() does it.
Prompt To Fix With AI
This is a comment left during a code review.
Path: ralphy.sh
Line: 2884:2918
Comment:
`get_next_engine_atomic()` only implements round-robin distribution and ignores the `ENGINE_DISTRIBUTION` setting. When users specify `--engine-distribution weighted`, `random`, or `fill-first`, the worker pool will still use round-robin.
The function should check `ENGINE_DISTRIBUTION` and implement the selected strategy atomically, similar to how `get_engine_for_agent()` does it.
How can I resolve this? If you propose a fix, please make it concise.
Preamble
Rrrralphy goes FAST - this PR adds multi-engine support so you can run parallel agents across Claude, Cursor, OpenCode, Codex, and Q simultaneously.
--multi-engineflag auto-detects and uses all available AI engines on your systemNote: Requires bash v4 (mac:
brew install bash).This is experimental but has been working locally on my fork. Ready to make ralphy go rrrreally fast! 🚀
Summary
Adds comprehensive multi-engine support for parallel task execution, allowing Ralphy to distribute work across multiple AI engines (Claude, Codex, OpenCode, Cursor, Qwen, Droid) simultaneously.
Key Features
--multi-engineflag automatically detects and uses all available AI engines on the system--detect-enginesflag shows which engines are installed--enginesflag for explicit engine selection with optional weights (e.g.,--engines claude:3,codex:1)New CLI Options
Example Usage
Technical Details
mkdir-based locking (works on macOS and Linux)Test plan
--detect-enginesshows available engines--multi-engineauto-detects and configures engines🤖 Generated with Claude Code