bmalph 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +111 -30
  2. package/dist/cli.js +1 -0
  3. package/dist/commands/doctor.d.ts +14 -2
  4. package/dist/commands/doctor.js +83 -35
  5. package/dist/commands/init.d.ts +1 -0
  6. package/dist/commands/init.js +74 -7
  7. package/dist/commands/upgrade.js +8 -5
  8. package/dist/installer.d.ts +15 -4
  9. package/dist/installer.js +190 -101
  10. package/dist/platform/aider.d.ts +2 -0
  11. package/dist/platform/aider.js +71 -0
  12. package/dist/platform/claude-code.d.ts +2 -0
  13. package/dist/platform/claude-code.js +88 -0
  14. package/dist/platform/codex.d.ts +2 -0
  15. package/dist/platform/codex.js +67 -0
  16. package/dist/platform/copilot.d.ts +2 -0
  17. package/dist/platform/copilot.js +71 -0
  18. package/dist/platform/cursor.d.ts +2 -0
  19. package/dist/platform/cursor.js +71 -0
  20. package/dist/platform/detect.d.ts +7 -0
  21. package/dist/platform/detect.js +23 -0
  22. package/dist/platform/index.d.ts +4 -0
  23. package/dist/platform/index.js +3 -0
  24. package/dist/platform/registry.d.ts +4 -0
  25. package/dist/platform/registry.js +27 -0
  26. package/dist/platform/resolve.d.ts +8 -0
  27. package/dist/platform/resolve.js +24 -0
  28. package/dist/platform/types.d.ts +41 -0
  29. package/dist/platform/types.js +7 -0
  30. package/dist/platform/windsurf.d.ts +2 -0
  31. package/dist/platform/windsurf.js +71 -0
  32. package/dist/transition/artifacts.js +1 -1
  33. package/dist/transition/specs-changelog.js +4 -1
  34. package/dist/utils/config.d.ts +2 -0
  35. package/dist/utils/validate.js +16 -0
  36. package/package.json +1 -1
  37. package/ralph/drivers/claude-code.sh +118 -0
  38. package/ralph/drivers/codex.sh +81 -0
  39. package/ralph/ralph_import.sh +11 -0
  40. package/ralph/ralph_loop.sh +37 -64
  41. package/ralph/templates/ralphrc.template +7 -0
@@ -0,0 +1,81 @@
1
+ #!/bin/bash
2
+ # OpenAI Codex driver for Ralph
3
+ # Provides platform-specific CLI invocation logic for Codex
4
+
5
+ driver_name() {
6
+ echo "codex"
7
+ }
8
+
9
+ driver_display_name() {
10
+ echo "OpenAI Codex"
11
+ }
12
+
13
+ driver_cli_binary() {
14
+ echo "codex"
15
+ }
16
+
17
+ driver_min_version() {
18
+ echo "0.1.0"
19
+ }
20
+
21
+ driver_check_available() {
22
+ command -v "$(driver_cli_binary)" &>/dev/null
23
+ }
24
+
25
+ # Codex tool names differ from Claude Code
26
+ driver_valid_tools() {
27
+ VALID_TOOL_PATTERNS=(
28
+ "shell"
29
+ "read_file"
30
+ "write_file"
31
+ "edit_file"
32
+ "list_directory"
33
+ "search_files"
34
+ )
35
+ }
36
+
37
+ # Build Codex CLI command
38
+ # Codex uses: codex exec [--resume <id>] --json "prompt"
39
+ driver_build_command() {
40
+ local prompt_file=$1
41
+ local loop_context=$2
42
+ local session_id=$3
43
+
44
+ CLAUDE_CMD_ARGS=("$(driver_cli_binary)" "exec")
45
+
46
+ if [[ ! -f "$prompt_file" ]]; then
47
+ echo "ERROR: Prompt file not found: $prompt_file" >&2
48
+ return 1
49
+ fi
50
+
51
+ # JSON output
52
+ CLAUDE_CMD_ARGS+=("--json")
53
+
54
+ # Sandbox mode - workspace write access
55
+ CLAUDE_CMD_ARGS+=("--sandbox" "workspace-write")
56
+
57
+ # Session resume — gated on CLAUDE_USE_CONTINUE to respect --no-continue flag
58
+ if [[ "$CLAUDE_USE_CONTINUE" == "true" && -n "$session_id" ]]; then
59
+ CLAUDE_CMD_ARGS+=("--resume" "$session_id")
60
+ fi
61
+
62
+ # Build prompt with context
63
+ local prompt_content
64
+ prompt_content=$(cat "$prompt_file")
65
+ if [[ -n "$loop_context" ]]; then
66
+ prompt_content="$loop_context
67
+
68
+ $prompt_content"
69
+ fi
70
+
71
+ CLAUDE_CMD_ARGS+=("$prompt_content")
72
+ }
73
+
74
+ driver_supports_sessions() {
75
+ return 0 # true - Codex supports session resume
76
+ }
77
+
78
+ # Codex outputs JSONL events
79
+ driver_stream_filter() {
80
+ echo 'select(.type == "message") | .content // empty'
81
+ }
@@ -7,6 +7,17 @@ set -e
7
7
  # Configuration
8
8
  CLAUDE_CODE_CMD="claude"
9
9
 
10
+ # Platform driver support
11
+ SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
12
+ PLATFORM_DRIVER="${PLATFORM_DRIVER:-claude-code}"
13
+
14
+ # Source platform driver if available
15
+ if [[ -f "$SCRIPT_DIR/drivers/${PLATFORM_DRIVER}.sh" ]]; then
16
+ # shellcheck source=/dev/null
17
+ source "$SCRIPT_DIR/drivers/${PLATFORM_DRIVER}.sh"
18
+ CLAUDE_CODE_CMD="$(driver_cli_binary)"
19
+ fi
20
+
10
21
  # Modern CLI Configuration (Phase 1.1)
11
22
  # These flags enable structured JSON output and controlled file operations
12
23
  CLAUDE_OUTPUT_FORMAT="json"
@@ -66,7 +66,8 @@ RALPH_SESSION_HISTORY_FILE="$RALPH_DIR/.ralph_session_history" # Session transi
66
66
  CLAUDE_SESSION_EXPIRY_HOURS=${CLAUDE_SESSION_EXPIRY_HOURS:-24}
67
67
 
68
68
  # Valid tool patterns for --allowed-tools validation
69
- # Tools can be exact matches or pattern matches with wildcards in parentheses
69
+ # Default: Claude Code tools. Platform driver overwrites via driver_valid_tools() in main().
70
+ # Validation runs in main() after load_platform_driver so the correct patterns are in effect.
70
71
  VALID_TOOL_PATTERNS=(
71
72
  "Write"
72
73
  "Read"
@@ -98,6 +99,9 @@ TEST_PERCENTAGE_THRESHOLD=30 # If more than 30% of recent loops are test-only,
98
99
  RALPHRC_FILE=".ralphrc"
99
100
  RALPHRC_LOADED=false
100
101
 
102
+ # Platform driver (set from .ralphrc or environment)
103
+ PLATFORM_DRIVER="${PLATFORM_DRIVER:-claude-code}"
104
+
101
105
  # load_ralphrc - Load project-specific configuration from .ralphrc
102
106
  #
103
107
  # This function sources .ralphrc if it exists, applying project-specific
@@ -155,6 +159,26 @@ load_ralphrc() {
155
159
  return 0
156
160
  }
157
161
 
162
+ # Source platform driver
163
+ load_platform_driver() {
164
+ local driver_file="$SCRIPT_DIR/drivers/${PLATFORM_DRIVER}.sh"
165
+ if [[ ! -f "$driver_file" ]]; then
166
+ log_status "ERROR" "Platform driver not found: $driver_file"
167
+ log_status "ERROR" "Available drivers: $(ls "$SCRIPT_DIR/drivers/"*.sh 2>/dev/null | xargs -n1 basename | sed 's/.sh$//' | tr '\n' ' ')"
168
+ exit 1
169
+ fi
170
+ # shellcheck source=/dev/null
171
+ source "$driver_file"
172
+
173
+ # Initialize driver-specific tool patterns
174
+ driver_valid_tools
175
+
176
+ # Set CLI binary from driver
177
+ CLAUDE_CODE_CMD="$(driver_cli_binary)"
178
+
179
+ log_status "INFO" "Platform driver: $(driver_display_name) ($(driver_cli_binary))"
180
+ }
181
+
158
182
  # Colors for terminal output
159
183
  RED='\033[0;31m'
160
184
  GREEN='\033[0;32m'
@@ -949,68 +973,11 @@ update_session_last_used() {
949
973
  # Global array for Claude command arguments (avoids shell injection)
950
974
  declare -a CLAUDE_CMD_ARGS=()
951
975
 
952
- # Build Claude CLI command with modern flags using array (shell-injection safe)
976
+ # Build CLI command with platform driver (shell-injection safe)
977
+ # Delegates to the active platform driver's driver_build_command()
953
978
  # Populates global CLAUDE_CMD_ARGS array for direct execution
954
- # Uses -p flag with prompt content (Claude CLI does not have --prompt-file)
955
979
  build_claude_command() {
956
- local prompt_file=$1
957
- local loop_context=$2
958
- local session_id=$3
959
-
960
- # Reset global array
961
- # Note: We do NOT use --dangerously-skip-permissions here. Tool permissions
962
- # are controlled via --allowedTools from CLAUDE_ALLOWED_TOOLS in .ralphrc.
963
- # This preserves the permission denial circuit breaker (Issue #101).
964
- CLAUDE_CMD_ARGS=("$CLAUDE_CODE_CMD")
965
-
966
- # Check if prompt file exists
967
- if [[ ! -f "$prompt_file" ]]; then
968
- log_status "ERROR" "Prompt file not found: $prompt_file"
969
- return 1
970
- fi
971
-
972
- # Add output format flag
973
- if [[ "$CLAUDE_OUTPUT_FORMAT" == "json" ]]; then
974
- CLAUDE_CMD_ARGS+=("--output-format" "json")
975
- fi
976
-
977
- # Add allowed tools (each tool as separate array element)
978
- if [[ -n "$CLAUDE_ALLOWED_TOOLS" ]]; then
979
- CLAUDE_CMD_ARGS+=("--allowedTools")
980
- # Split by comma and add each tool
981
- local IFS=','
982
- read -ra tools_array <<< "$CLAUDE_ALLOWED_TOOLS"
983
- for tool in "${tools_array[@]}"; do
984
- # Trim whitespace
985
- tool=$(echo "$tool" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
986
- if [[ -n "$tool" ]]; then
987
- CLAUDE_CMD_ARGS+=("$tool")
988
- fi
989
- done
990
- fi
991
-
992
- # Add session continuity flag
993
- # IMPORTANT: Use --resume with explicit session ID instead of --continue
994
- # --continue resumes the "most recent session in current directory" which
995
- # can hijack active Claude Code sessions. --resume with a specific session ID
996
- # ensures we only resume Ralph's own sessions. (Issue #151)
997
- if [[ "$CLAUDE_USE_CONTINUE" == "true" && -n "$session_id" ]]; then
998
- CLAUDE_CMD_ARGS+=("--resume" "$session_id")
999
- fi
1000
- # If no session_id, start fresh - Claude will generate a new session ID
1001
- # which we'll capture via save_claude_session() for future loops
1002
-
1003
- # Add loop context as system prompt (no escaping needed - array handles it)
1004
- if [[ -n "$loop_context" ]]; then
1005
- CLAUDE_CMD_ARGS+=("--append-system-prompt" "$loop_context")
1006
- fi
1007
-
1008
- # Read prompt file content and use -p flag
1009
- # Note: Claude CLI uses -p for prompts, not --prompt-file (which doesn't exist)
1010
- # Array-based approach maintains shell injection safety
1011
- local prompt_content
1012
- prompt_content=$(cat "$prompt_file")
1013
- CLAUDE_CMD_ARGS+=("-p" "$prompt_content")
980
+ driver_build_command "$@"
1014
981
  }
1015
982
 
1016
983
  # Main execution function
@@ -1418,6 +1385,14 @@ main() {
1418
1385
  fi
1419
1386
  fi
1420
1387
 
1388
+ # Load platform driver (after .ralphrc so PLATFORM_DRIVER can be overridden)
1389
+ load_platform_driver
1390
+
1391
+ # Validate --allowed-tools now that platform-specific VALID_TOOL_PATTERNS are loaded
1392
+ if [[ "${_CLI_ALLOWED_TOOLS:-}" == "true" ]] && ! validate_allowed_tools "$CLAUDE_ALLOWED_TOOLS"; then
1393
+ exit 1
1394
+ fi
1395
+
1421
1396
  log_status "SUCCESS" "🚀 Ralph loop starting with Claude Code"
1422
1397
  log_status "INFO" "Max calls per hour: $MAX_CALLS_PER_HOUR"
1423
1398
  log_status "INFO" "Logs: $LOG_DIR/ | Docs: $DOCS_DIR/ | Status: $STATUS_FILE"
@@ -1750,10 +1725,8 @@ while [[ $# -gt 0 ]]; do
1750
1725
  shift 2
1751
1726
  ;;
1752
1727
  --allowed-tools)
1753
- if ! validate_allowed_tools "$2"; then
1754
- exit 1
1755
- fi
1756
1728
  CLAUDE_ALLOWED_TOOLS="$2"
1729
+ _CLI_ALLOWED_TOOLS=true
1757
1730
  shift 2
1758
1731
  ;;
1759
1732
  --no-continue)
@@ -6,6 +6,13 @@
6
6
  # Values here override global Ralph defaults.
7
7
  # Environment variables override values in this file.
8
8
 
9
+ # =============================================================================
10
+ # PLATFORM DRIVER
11
+ # =============================================================================
12
+
13
+ # Platform driver for Ralph loop (claude-code or codex)
14
+ PLATFORM_DRIVER="${PLATFORM_DRIVER:-claude-code}"
15
+
9
16
  # =============================================================================
10
17
  # PROJECT IDENTIFICATION
11
18
  # =============================================================================