claude-evolve 1.5.28 → 1.5.30
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.
- package/bin/claude-evolve-worker +99 -59
- package/lib/ai-cli.sh +8 -3
- package/lib/config.sh +8 -7
- package/package.json +1 -1
package/bin/claude-evolve-worker
CHANGED
|
@@ -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
|
-
#
|
|
80
|
-
local
|
|
81
|
-
local
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if [[
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
|
@@ -222,11 +260,13 @@ with EvolutionCSV('$FULL_CSV_PATH') as csv:
|
|
|
222
260
|
# Use relative path for AI prompt
|
|
223
261
|
local target_basename=$(basename "$target_file")
|
|
224
262
|
local evolution_prompt="Modify the algorithm in $target_basename based on this description: $description
|
|
225
|
-
|
|
263
|
+
|
|
226
264
|
The modification should be substantial and follow the description exactly. Make sure the algorithm still follows all interface requirements and can run properly.
|
|
227
265
|
|
|
228
266
|
Important: Make meaningful changes that match the description. Don't just add comments or make trivial adjustments.
|
|
229
267
|
|
|
268
|
+
CRITICAL: If you do not know how to implement what was asked for, or if the requested change is unclear or not feasible, you MUST refuse to make any changes. DO NOT modify the code if you are uncertain about the implementation. Simply respond that you cannot implement the requested change and explain why. It is better to refuse than to make incorrect or random changes.
|
|
269
|
+
|
|
230
270
|
CRITICAL: Do NOT use any git commands (git add, git commit, git reset, etc.). Only modify the file directly."
|
|
231
271
|
|
|
232
272
|
if [[ "$is_baseline" != "true" ]]; then
|
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)
|
|
@@ -81,6 +81,11 @@ $prompt"
|
|
|
81
81
|
ai_output=$(timeout 300 opencode -m openrouter/z-ai/glm-4.6 run "$prompt" 2>&1)
|
|
82
82
|
local ai_exit_code=$?
|
|
83
83
|
;;
|
|
84
|
+
deepseek)
|
|
85
|
+
local ai_output
|
|
86
|
+
ai_output=$(timeout 300 opencode -m openrouter/deepseek/deepseek-v3.1-terminus run "$prompt" 2>&1)
|
|
87
|
+
local ai_exit_code=$?
|
|
88
|
+
;;
|
|
84
89
|
*)
|
|
85
90
|
echo "[ERROR] Unknown model: $model_name" >&2
|
|
86
91
|
return 1
|
package/lib/config.sh
CHANGED
|
@@ -54,8 +54,8 @@ DEFAULT_MAX_RETRIES=3
|
|
|
54
54
|
DEFAULT_MEMORY_LIMIT_MB=12288
|
|
55
55
|
|
|
56
56
|
# Default LLM CLI configuration - use simple variables instead of arrays
|
|
57
|
-
DEFAULT_LLM_RUN="sonnet gpt5 cursor-sonnet glm"
|
|
58
|
-
DEFAULT_LLM_IDEATE="gemini sonnet-think sonnet-think gpt5high sonnet-think o3high"
|
|
57
|
+
DEFAULT_LLM_RUN="sonnet gpt5 cursor-sonnet glm deepseek"
|
|
58
|
+
DEFAULT_LLM_IDEATE="gemini sonnet-think sonnet-think gpt5high sonnet-think o3high glm"
|
|
59
59
|
|
|
60
60
|
# Load configuration from config file
|
|
61
61
|
load_config() {
|
|
@@ -102,13 +102,14 @@ 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}}"'
|
|
112
|
+
LLM_CLI_deepseek='opencode -m openrouter/deepseek/deepseek-v3.1-terminus run "{{PROMPT}}"'
|
|
112
113
|
LLM_RUN="$DEFAULT_LLM_RUN"
|
|
113
114
|
LLM_IDEATE="$DEFAULT_LLM_IDEATE"
|
|
114
115
|
|
|
@@ -328,7 +329,7 @@ show_config() {
|
|
|
328
329
|
echo " Memory limit: ${MEMORY_LIMIT_MB}MB"
|
|
329
330
|
echo " LLM configuration:"
|
|
330
331
|
# Show LLM configurations using dynamic variable names
|
|
331
|
-
for model in gpt5high o3high codex gemini opus opus_think sonnet sonnet_think cursor_sonnet cursor_opus glm; do
|
|
332
|
+
for model in gpt5high o3high codex gemini opus opus_think sonnet sonnet_think cursor_sonnet cursor_opus glm deepseek; do
|
|
332
333
|
var_name="LLM_CLI_${model}"
|
|
333
334
|
var_value=$(eval echo "\$$var_name")
|
|
334
335
|
if [[ -n "$var_value" ]]; then
|