claude-evolve 1.5.28 → 1.5.29

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.
@@ -72,68 +72,106 @@ fi
72
72
  call_ai_for_evolution() {
73
73
  local prompt="$1"
74
74
  local candidate_id="$2"
75
-
75
+
76
76
  # Get target file path from worker context
77
77
  local target_file="$FULL_OUTPUT_DIR/evolution_${candidate_id}.py"
78
-
79
- # Capture file state before AI call
80
- local file_hash_before=""
81
- local file_mtime_before=""
82
- if [[ -f "$target_file" ]]; then
83
- file_hash_before=$(shasum -a 256 "$target_file" 2>/dev/null | cut -d' ' -f1)
84
- file_mtime_before=$(stat -f %m "$target_file" 2>/dev/null || stat -c %Y "$target_file" 2>/dev/null)
85
- fi
86
-
87
- # Extract generation and ID numbers for round-robin calculation
88
- local gen_num=0
89
- local id_num=0
90
- if [[ $candidate_id =~ ^gen([0-9]+)-([0-9]+)$ ]]; then
91
- gen_num=$((10#${BASH_REMATCH[1]}))
92
- id_num=$((10#${BASH_REMATCH[2]}))
93
- fi
94
-
95
- # Calculate hash for round-robin (combine generation and ID)
96
- local hash_value=$((gen_num * 1000 + id_num))
97
-
98
- # Use the centralized AI library for evolution (run command)
99
- local ai_output
100
- ai_output=$(call_ai_with_round_robin "$prompt" "run" "$hash_value")
101
- local ai_exit_code=$?
102
-
103
- # Handle special exit codes
104
- if [[ $ai_exit_code -eq 3 ]]; then
105
- echo "[WORKER-$$] All models hit usage limits" >&2
106
- echo "[WORKER-$$] Unable to complete evolution due to API limits" >&2
107
- exit 3
108
- fi
109
-
110
- # Check if the target file was actually modified
111
- local file_was_modified=false
112
- if [[ -f "$target_file" ]]; then
113
- local file_hash_after
114
- local file_mtime_after
115
- file_hash_after=$(shasum -a 256 "$target_file" 2>/dev/null | cut -d' ' -f1)
116
- file_mtime_after=$(stat -f %m "$target_file" 2>/dev/null || stat -c %Y "$target_file" 2>/dev/null)
117
-
118
- if [[ "$file_hash_before" != "$file_hash_after" ]] || [[ "$file_mtime_before" != "$file_mtime_after" ]]; then
119
- file_was_modified=true
78
+
79
+ # Retry configuration for API limits
80
+ local retry_count=0
81
+ local max_retries=3
82
+ local wait_seconds=300 # Start with 5 minutes
83
+ local max_wait_seconds=1800 # Cap at 30 minutes
84
+
85
+ while true; do
86
+ # Capture file state before AI call
87
+ local file_hash_before=""
88
+ local file_mtime_before=""
89
+ if [[ -f "$target_file" ]]; then
90
+ file_hash_before=$(shasum -a 256 "$target_file" 2>/dev/null | cut -d' ' -f1)
91
+ file_mtime_before=$(stat -f %m "$target_file" 2>/dev/null || stat -c %Y "$target_file" 2>/dev/null)
120
92
  fi
121
- fi
122
-
123
- # Success if file was modified OR exit code is 0 (for cases where file validation isn't applicable)
124
- if [[ "$file_was_modified" == "true" ]] || [[ $ai_exit_code -eq 0 ]]; then
125
- if [[ "$file_was_modified" == "true" ]]; then
126
- echo "[WORKER-$$] AI successfully modified $target_file (exit code: $ai_exit_code)" >&2
127
- else
128
- echo "[WORKER-$$] AI succeeded with exit code 0" >&2
93
+
94
+ # Extract generation and ID numbers for round-robin calculation
95
+ local gen_num=0
96
+ local id_num=0
97
+ if [[ $candidate_id =~ ^gen([0-9]+)-([0-9]+)$ ]]; then
98
+ gen_num=$((10#${BASH_REMATCH[1]}))
99
+ id_num=$((10#${BASH_REMATCH[2]}))
129
100
  fi
130
- # Output the result for the worker to use
131
- echo "$ai_output"
132
- return 0
133
- fi
134
-
135
- echo "[WORKER-$$] AI failed: exit code $ai_exit_code, no file changes detected" >&2
136
- return 1
101
+
102
+ # Calculate hash for round-robin (combine generation and ID)
103
+ local hash_value=$((gen_num * 1000 + id_num))
104
+
105
+ # Use the centralized AI library for evolution (run command)
106
+ local ai_output
107
+ ai_output=$(call_ai_with_round_robin "$prompt" "run" "$hash_value")
108
+ local ai_exit_code=$?
109
+
110
+ # Handle special exit codes
111
+ if [[ $ai_exit_code -eq 3 ]]; then
112
+ # All models hit usage limits
113
+ if [[ $retry_count -lt $max_retries ]]; then
114
+ ((retry_count++))
115
+ echo "[WORKER-$$] All models hit usage limits (retry $retry_count/$max_retries)" >&2
116
+ echo "[WORKER-$$] Waiting $wait_seconds seconds ($(($wait_seconds / 60)) minutes) before retrying..." >&2
117
+
118
+ # Sleep with countdown
119
+ local remaining=$wait_seconds
120
+ while [[ $remaining -gt 0 ]]; do
121
+ if [[ $((remaining % 60)) -eq 0 ]]; then
122
+ echo "[WORKER-$$] Retrying in $((remaining / 60)) minutes..." >&2
123
+ fi
124
+ sleep 60
125
+ remaining=$((remaining - 60))
126
+ done
127
+
128
+ echo "[WORKER-$$] Retrying AI call (attempt #$((retry_count + 1)))..." >&2
129
+
130
+ # Exponential backoff: double the wait time, up to max
131
+ wait_seconds=$((wait_seconds * 2))
132
+ if [[ $wait_seconds -gt $max_wait_seconds ]]; then
133
+ wait_seconds=$max_wait_seconds
134
+ fi
135
+
136
+ # Continue to retry
137
+ continue
138
+ else
139
+ # Exhausted retries
140
+ echo "[WORKER-$$] All models hit usage limits after $max_retries retries" >&2
141
+ echo "[WORKER-$$] Unable to complete evolution due to API limits" >&2
142
+ exit 3
143
+ fi
144
+ fi
145
+
146
+ # Check if the target file was actually modified
147
+ local file_was_modified=false
148
+ if [[ -f "$target_file" ]]; then
149
+ local file_hash_after
150
+ local file_mtime_after
151
+ file_hash_after=$(shasum -a 256 "$target_file" 2>/dev/null | cut -d' ' -f1)
152
+ file_mtime_after=$(stat -f %m "$target_file" 2>/dev/null || stat -c %Y "$target_file" 2>/dev/null)
153
+
154
+ if [[ "$file_hash_before" != "$file_hash_after" ]] || [[ "$file_mtime_before" != "$file_mtime_after" ]]; then
155
+ file_was_modified=true
156
+ fi
157
+ fi
158
+
159
+ # Success if file was modified OR exit code is 0 (for cases where file validation isn't applicable)
160
+ if [[ "$file_was_modified" == "true" ]] || [[ $ai_exit_code -eq 0 ]]; then
161
+ if [[ "$file_was_modified" == "true" ]]; then
162
+ echo "[WORKER-$$] AI successfully modified $target_file (exit code: $ai_exit_code)" >&2
163
+ else
164
+ echo "[WORKER-$$] AI succeeded with exit code 0" >&2
165
+ fi
166
+ # Output the result for the worker to use
167
+ echo "$ai_output"
168
+ return 0
169
+ fi
170
+
171
+ # Non-limit failure - don't retry
172
+ echo "[WORKER-$$] AI failed: exit code $ai_exit_code, no file changes detected" >&2
173
+ return 1
174
+ done
137
175
  }
138
176
 
139
177
  # Validate paths
package/lib/ai-cli.sh CHANGED
@@ -19,7 +19,7 @@ call_ai_model_configured() {
19
19
  case "$model_name" in
20
20
  opus|sonnet)
21
21
  local ai_output
22
- ai_output=$(timeout 300 claude --dangerously-skip-permissions --model "$model_name" -p "$prompt" 2>&1)
22
+ ai_output=$(timeout 300 claude --dangerously-skip-permissions --mcp-config '' --model "$model_name" -p "$prompt" 2>&1)
23
23
  local ai_exit_code=$?
24
24
  ;;
25
25
  sonnet-think)
@@ -28,7 +28,7 @@ call_ai_model_configured() {
28
28
  local think_prompt="ultrathink
29
29
 
30
30
  $prompt"
31
- ai_output=$(timeout 600 claude --dangerously-skip-permissions --model sonnet -p "$think_prompt" 2>&1)
31
+ ai_output=$(timeout 600 claude --dangerously-skip-permissions --mcp-config '' --model sonnet -p "$think_prompt" 2>&1)
32
32
  local ai_exit_code=$?
33
33
  ;;
34
34
  opus-think)
@@ -37,7 +37,7 @@ $prompt"
37
37
  local think_prompt="ultrathink
38
38
 
39
39
  $prompt"
40
- ai_output=$(timeout 600 claude --dangerously-skip-permissions --model opus -p "$think_prompt" 2>&1)
40
+ ai_output=$(timeout 600 claude --dangerously-skip-permissions --mcp-config '' --model opus -p "$think_prompt" 2>&1)
41
41
  local ai_exit_code=$?
42
42
  ;;
43
43
  gpt5high)
package/lib/config.sh CHANGED
@@ -102,10 +102,10 @@ load_config() {
102
102
  LLM_CLI_o3high='codex exec --profile o3high --dangerously-bypass-approvals-and-sandbox "{{PROMPT}}"'
103
103
  LLM_CLI_codex='codex exec --dangerously-bypass-approvals-and-sandbox "{{PROMPT}}"'
104
104
  LLM_CLI_gemini='gemini -y -p "{{PROMPT}}"'
105
- LLM_CLI_opus='claude --dangerously-skip-permissions --model opus -p "{{PROMPT}}"'
106
- LLM_CLI_opus_think='claude --dangerously-skip-permissions --model opus -p "ultrathink\n\n{{PROMPT}}"'
107
- LLM_CLI_sonnet='claude --dangerously-skip-permissions --model sonnet -p "{{PROMPT}}"'
108
- LLM_CLI_sonnet_think='claude --dangerously-skip-permissions --model sonnet -p "ultrathink\n\n{{PROMPT}}"'
105
+ LLM_CLI_opus='claude --dangerously-skip-permissions --mcp-config "" --model opus -p "{{PROMPT}}"'
106
+ LLM_CLI_opus_think='claude --dangerously-skip-permissions --mcp-config "" --model opus -p "ultrathink\n\n{{PROMPT}}"'
107
+ LLM_CLI_sonnet='claude --dangerously-skip-permissions --mcp-config "" --model sonnet -p "{{PROMPT}}"'
108
+ LLM_CLI_sonnet_think='claude --dangerously-skip-permissions --mcp-config "" --model sonnet -p "ultrathink\n\n{{PROMPT}}"'
109
109
  LLM_CLI_cursor_sonnet='cursor-agent sonnet -p "{{PROMPT}}"'
110
110
  LLM_CLI_cursor_opus='cursor-agent opus -p "{{PROMPT}}"'
111
111
  LLM_CLI_glm='opencode -m openrouter/z-ai/glm-4.6 run "{{PROMPT}}"'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-evolve",
3
- "version": "1.5.28",
3
+ "version": "1.5.29",
4
4
  "bin": {
5
5
  "claude-evolve": "./bin/claude-evolve",
6
6
  "claude-evolve-main": "./bin/claude-evolve-main",