claude-evolve 1.8.32 → 1.8.34
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-ideate +69 -136
- package/bin/claude-evolve-worker +37 -97
- package/lib/ai-cli.sh +36 -63
- package/lib/config.sh +1 -1
- package/package.json +1 -1
package/bin/claude-evolve-ideate
CHANGED
|
@@ -54,36 +54,16 @@ safe_popd() {
|
|
|
54
54
|
fi
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
# Helper function to call AI
|
|
57
|
+
# Helper function to call AI (legacy wrapper)
|
|
58
58
|
call_ai_with_limit_check() {
|
|
59
59
|
local prompt="$1"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
# Calculate hash value for round-robin based on generation
|
|
63
|
-
local gen_num
|
|
64
|
-
if [[ $generation =~ ^0*([0-9]+)$ ]]; then
|
|
65
|
-
gen_num=$((10#${BASH_REMATCH[1]}))
|
|
66
|
-
else
|
|
67
|
-
gen_num=1
|
|
68
|
-
fi
|
|
69
|
-
|
|
70
|
-
# Use centralized AI library for ideation
|
|
60
|
+
|
|
61
|
+
# Use centralized AI library for ideation (random model selection)
|
|
71
62
|
local ai_output
|
|
72
|
-
ai_output=$(
|
|
63
|
+
ai_output=$(call_ai_random "$prompt" "ideate")
|
|
73
64
|
local ai_exit_code=$?
|
|
74
|
-
|
|
75
|
-
# Handle special exit codes
|
|
76
|
-
if [[ $ai_exit_code -eq 3 ]]; then
|
|
77
|
-
# All models hit usage limits
|
|
78
|
-
echo -e "\033[31m[ERROR] ALL AI MODELS HIT USAGE LIMITS!\033[0m" >&2
|
|
79
|
-
echo -e "\033[31m[ERROR] Ideation halted due to API rate limits.\033[0m" >&2
|
|
80
|
-
echo -e "\033[33m[INFO] Please wait for the rate limits to reset before continuing.\033[0m" >&2
|
|
81
|
-
echo -e "\033[33m[INFO] No ideas were generated. Run ideate again when the limits reset.\033[0m" >&2
|
|
82
|
-
exit 1
|
|
83
|
-
fi
|
|
84
|
-
|
|
65
|
+
|
|
85
66
|
if [[ $ai_exit_code -eq 0 ]]; then
|
|
86
|
-
# For ideation, AI modifies files directly - just return success
|
|
87
67
|
echo "[INFO] AI succeeded" >&2
|
|
88
68
|
return 0
|
|
89
69
|
else
|
|
@@ -97,28 +77,16 @@ call_claude_with_limit_check() {
|
|
|
97
77
|
call_ai_with_limit_check "$@"
|
|
98
78
|
}
|
|
99
79
|
|
|
100
|
-
# Robust AI calling with
|
|
80
|
+
# Robust AI calling with random model selection (no fallback)
|
|
101
81
|
# Returns 0 on success and echoes the successful model name to stdout
|
|
102
82
|
call_ai_for_ideation() {
|
|
103
83
|
local prompt="$1"
|
|
104
84
|
local generation="${2:-01}"
|
|
105
85
|
local expected_count="${3:-1}" # Number of ideas expected to be added
|
|
106
86
|
local temp_csv_file="${4:-temp-csv-$$.csv}" # Optional temp CSV filename
|
|
107
|
-
|
|
108
|
-
#
|
|
109
|
-
|
|
110
|
-
if [[ $generation =~ ^0*([0-9]+)$ ]]; then
|
|
111
|
-
gen_num=$((10#${BASH_REMATCH[1]}))
|
|
112
|
-
else
|
|
113
|
-
gen_num=1
|
|
114
|
-
fi
|
|
115
|
-
|
|
116
|
-
# Make a backup of the pre-populated temp CSV (which includes stub rows from caller)
|
|
117
|
-
# This preserves the stub rows that the caller added
|
|
118
|
-
local temp_csv_backup="${temp_csv_file}.backup"
|
|
119
|
-
if [[ -f "$temp_csv_file" ]]; then
|
|
120
|
-
cp "$temp_csv_file" "$temp_csv_backup"
|
|
121
|
-
else
|
|
87
|
+
|
|
88
|
+
# Verify temp CSV exists
|
|
89
|
+
if [[ ! -f "$temp_csv_file" ]]; then
|
|
122
90
|
echo "[ERROR] Temp CSV file not found at start: $temp_csv_file" >&2
|
|
123
91
|
return 1
|
|
124
92
|
fi
|
|
@@ -137,103 +105,68 @@ call_ai_for_ideation() {
|
|
|
137
105
|
|
|
138
106
|
if [[ ${#models[@]} -eq 0 ]]; then
|
|
139
107
|
echo "[ERROR] No models configured for ideation" >&2
|
|
140
|
-
rm -f "$temp_csv_backup"
|
|
141
108
|
return 1
|
|
142
109
|
fi
|
|
143
110
|
|
|
144
|
-
#
|
|
111
|
+
# Pick one random model (no fallback)
|
|
145
112
|
local num_models=${#models[@]}
|
|
146
|
-
local
|
|
113
|
+
local random_index=$((RANDOM % num_models))
|
|
114
|
+
local model="${models[$random_index]}"
|
|
147
115
|
|
|
148
|
-
|
|
149
|
-
local ordered_models=()
|
|
150
|
-
for ((i=0; i<num_models; i++)); do
|
|
151
|
-
local idx=$(((start_index + i) % num_models))
|
|
152
|
-
ordered_models+=("${models[$idx]}")
|
|
153
|
-
done
|
|
116
|
+
echo "[AI] Selected $model for ideate (random from $num_models models)" >&2
|
|
154
117
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
echo "[DEBUG] After $model: original=$original_csv_count, new=$new_csv_count, added=$added_count" >&2
|
|
177
|
-
|
|
178
|
-
# Check if row count is correct (should be same since we're editing stubs, not adding)
|
|
179
|
-
if [[ $new_csv_count -eq $original_csv_count ]]; then
|
|
180
|
-
# Count remaining placeholders - there should be none if AI did its job
|
|
181
|
-
local placeholder_count
|
|
182
|
-
placeholder_count=$(grep -c "PLACEHOLDER" "$temp_csv_file" 2>/dev/null || echo "0")
|
|
183
|
-
# Strip whitespace and ensure we have a clean integer
|
|
184
|
-
placeholder_count=$(echo "$placeholder_count" | tr -d '[:space:]')
|
|
185
|
-
placeholder_count=${placeholder_count:-0}
|
|
186
|
-
|
|
187
|
-
if [[ $placeholder_count -eq 0 ]]; then
|
|
188
|
-
echo "[INFO] CSV modified by $model: filled $expected_count placeholder rows ✓" >&2
|
|
189
|
-
|
|
190
|
-
# Post-process to ensure all description fields are quoted
|
|
191
|
-
local fixed_csv_file="${temp_csv_file}.fixed"
|
|
192
|
-
|
|
193
|
-
# Use the CSV fixer script
|
|
194
|
-
if "$PYTHON_CMD" "$SCRIPT_DIR/../lib/csv_fixer.py" "$temp_csv_file" "$fixed_csv_file"; then
|
|
195
|
-
mv "$fixed_csv_file" "$temp_csv_file"
|
|
196
|
-
echo "[INFO] CSV format validated and fixed if needed" >&2
|
|
197
|
-
else
|
|
198
|
-
echo "[WARN] CSV format validation failed, using original" >&2
|
|
199
|
-
fi
|
|
200
|
-
|
|
201
|
-
# Clean up backup file
|
|
202
|
-
rm -f "$temp_csv_backup"
|
|
203
|
-
|
|
204
|
-
# Echo the successful model name for caller to capture
|
|
205
|
-
echo "$model"
|
|
206
|
-
return 0
|
|
207
|
-
else
|
|
208
|
-
echo "[WARN] $model left $placeholder_count placeholders unfilled - trying next model" >&2
|
|
209
|
-
# Continue to next model
|
|
210
|
-
fi
|
|
211
|
-
elif [[ $added_count -lt 0 ]]; then
|
|
212
|
-
echo "[WARN] $model deleted rows ($added_count) - trying next model" >&2
|
|
213
|
-
# Continue to next model
|
|
214
|
-
elif [[ $added_count -gt 0 ]]; then
|
|
215
|
-
echo "[WARN] $model added extra rows ($added_count) instead of editing stubs - trying next model" >&2
|
|
216
|
-
# Continue to next model
|
|
217
|
-
else
|
|
218
|
-
echo "[INFO] CSV unchanged after $model (exit code: $ai_exit_code)" >&2
|
|
219
|
-
# Log last few lines of AI output to help debug why it succeeded but didn't change the file
|
|
220
|
-
if [[ -n "$ai_output" ]]; then
|
|
221
|
-
echo "[AI] Last 10 lines of $model output:" >&2
|
|
222
|
-
echo "$ai_output" | tail -n 10 >&2
|
|
223
|
-
echo "[AI] ---" >&2
|
|
224
|
-
fi
|
|
225
|
-
# Continue to next model
|
|
226
|
-
fi
|
|
118
|
+
# Call the model directly
|
|
119
|
+
local ai_output
|
|
120
|
+
ai_output=$(call_ai_model_configured "$model" "$prompt")
|
|
121
|
+
local ai_exit_code=$?
|
|
122
|
+
|
|
123
|
+
# Check if the file was modified correctly
|
|
124
|
+
if [[ ! -f "$temp_csv_file" ]]; then
|
|
125
|
+
echo "[ERROR] Temp CSV file not found after $model: $temp_csv_file" >&2
|
|
126
|
+
return 1
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
local new_csv_count
|
|
130
|
+
new_csv_count=$(grep -v '^[[:space:]]*$' "$temp_csv_file" | tail -n +2 | wc -l | tr -d '[:space:]')
|
|
131
|
+
local added_count=$((new_csv_count - original_csv_count))
|
|
132
|
+
|
|
133
|
+
echo "[DEBUG] After $model: original=$original_csv_count, new=$new_csv_count, added=$added_count" >&2
|
|
134
|
+
|
|
135
|
+
# Check if row count is correct (should be same since we're editing stubs, not adding)
|
|
136
|
+
if [[ $new_csv_count -ne $original_csv_count ]]; then
|
|
137
|
+
if [[ $added_count -lt 0 ]]; then
|
|
138
|
+
echo "[ERROR] $model deleted rows ($added_count)" >&2
|
|
227
139
|
else
|
|
228
|
-
echo "[
|
|
229
|
-
# Continue to next model
|
|
140
|
+
echo "[ERROR] $model added extra rows ($added_count) instead of editing stubs" >&2
|
|
230
141
|
fi
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
142
|
+
return 1
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
# Count remaining placeholders - there should be none if AI did its job
|
|
146
|
+
local placeholder_count
|
|
147
|
+
placeholder_count=$(grep -c "PLACEHOLDER" "$temp_csv_file" 2>/dev/null || echo "0")
|
|
148
|
+
placeholder_count=$(echo "$placeholder_count" | tr -d '[:space:]')
|
|
149
|
+
placeholder_count=${placeholder_count:-0}
|
|
150
|
+
|
|
151
|
+
if [[ $placeholder_count -ne 0 ]]; then
|
|
152
|
+
echo "[ERROR] $model left $placeholder_count placeholders unfilled" >&2
|
|
153
|
+
return 1
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
echo "[INFO] CSV modified by $model: filled $expected_count placeholder rows ✓" >&2
|
|
157
|
+
|
|
158
|
+
# Post-process to ensure all description fields are quoted
|
|
159
|
+
local fixed_csv_file="${temp_csv_file}.fixed"
|
|
160
|
+
if "$PYTHON_CMD" "$SCRIPT_DIR/../lib/csv_fixer.py" "$temp_csv_file" "$fixed_csv_file"; then
|
|
161
|
+
mv "$fixed_csv_file" "$temp_csv_file"
|
|
162
|
+
echo "[INFO] CSV format validated and fixed if needed" >&2
|
|
163
|
+
else
|
|
164
|
+
echo "[WARN] CSV format validation failed, using original" >&2
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# Echo the successful model name for caller to capture
|
|
168
|
+
echo "$model"
|
|
169
|
+
return 0
|
|
237
170
|
}
|
|
238
171
|
|
|
239
172
|
# Parse arguments
|
|
@@ -654,7 +587,7 @@ IMPORTANT: Output the complete modified CSV file. Do not add any explanation or
|
|
|
654
587
|
local modified_csv
|
|
655
588
|
local stderr_file="$FULL_EVOLUTION_DIR/stderr-$$.txt"
|
|
656
589
|
if ! modified_csv=$(call_ai_for_ideation "$csv_prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
|
|
657
|
-
echo "[ERROR]
|
|
590
|
+
echo "[ERROR] AI model failed to modify CSV" >&2
|
|
658
591
|
cat "$stderr_file" >&2
|
|
659
592
|
rm -f "$temp_csv" "$stderr_file"
|
|
660
593
|
return 1
|
|
@@ -1138,7 +1071,7 @@ CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CS
|
|
|
1138
1071
|
local stderr_file="stderr-$$.txt"
|
|
1139
1072
|
# Temporarily show stderr for debugging
|
|
1140
1073
|
if ! ai_response=$(call_ai_for_ideation "$prompt" "$CURRENT_GENERATION" "$count" "$temp_csv_basename"); then
|
|
1141
|
-
echo "[ERROR]
|
|
1074
|
+
echo "[ERROR] AI model failed to generate novel ideas" >&2
|
|
1142
1075
|
cat "$stderr_file" >&2
|
|
1143
1076
|
safe_popd
|
|
1144
1077
|
rm -f "$temp_csv" "$stderr_file"
|
|
@@ -1291,7 +1224,7 @@ CRITICAL INSTRUCTIONS:
|
|
|
1291
1224
|
local stderr_file="stderr-$$.txt"
|
|
1292
1225
|
# Temporarily show stderr for debugging
|
|
1293
1226
|
if ! ai_response=$(call_ai_for_ideation "$prompt" "$CURRENT_GENERATION" "$count" "$temp_csv_basename"); then
|
|
1294
|
-
echo "[ERROR]
|
|
1227
|
+
echo "[ERROR] AI model failed to generate hill climbing ideas" >&2
|
|
1295
1228
|
cat "$stderr_file" >&2
|
|
1296
1229
|
safe_popd
|
|
1297
1230
|
rm -f "$temp_csv" "$stderr_file"
|
|
@@ -1434,7 +1367,7 @@ CRITICAL INSTRUCTIONS:
|
|
|
1434
1367
|
local stderr_file="stderr-$$.txt"
|
|
1435
1368
|
# Temporarily show stderr for debugging
|
|
1436
1369
|
if ! ai_response=$(call_ai_for_ideation "$prompt" "$CURRENT_GENERATION" "$count" "$temp_csv_basename"); then
|
|
1437
|
-
echo "[ERROR]
|
|
1370
|
+
echo "[ERROR] AI model failed to generate structural mutation ideas" >&2
|
|
1438
1371
|
cat "$stderr_file" >&2
|
|
1439
1372
|
safe_popd
|
|
1440
1373
|
rm -f "$temp_csv" "$stderr_file"
|
|
@@ -1577,7 +1510,7 @@ CRITICAL INSTRUCTIONS:
|
|
|
1577
1510
|
local stderr_file="stderr-$$.txt"
|
|
1578
1511
|
# Temporarily show stderr for debugging
|
|
1579
1512
|
if ! ai_response=$(call_ai_for_ideation "$prompt" "$CURRENT_GENERATION" "$count" "$temp_csv_basename"); then
|
|
1580
|
-
echo "[ERROR]
|
|
1513
|
+
echo "[ERROR] AI model failed to generate crossover hybrid ideas" >&2
|
|
1581
1514
|
cat "$stderr_file" >&2
|
|
1582
1515
|
safe_popd
|
|
1583
1516
|
rm -f "$temp_csv" "$stderr_file"
|
|
@@ -1697,7 +1630,7 @@ CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CS
|
|
|
1697
1630
|
local ai_response
|
|
1698
1631
|
local stderr_file="stderr-$$.txt"
|
|
1699
1632
|
if ! ai_response=$(call_ai_for_ideation "$prompt" "$CURRENT_GENERATION" "$TOTAL_IDEAS" "$temp_csv_basename" 2>"$stderr_file"); then
|
|
1700
|
-
echo "[ERROR]
|
|
1633
|
+
echo "[ERROR] AI model failed to generate ideas" >&2
|
|
1701
1634
|
cat "$stderr_file" >&2
|
|
1702
1635
|
safe_popd
|
|
1703
1636
|
rm -f "$temp_csv" "$stderr_file"
|
package/bin/claude-evolve-worker
CHANGED
|
@@ -110,7 +110,7 @@ else
|
|
|
110
110
|
load_config
|
|
111
111
|
fi
|
|
112
112
|
|
|
113
|
-
# AI
|
|
113
|
+
# AI random selection function for code evolution
|
|
114
114
|
call_ai_for_evolution() {
|
|
115
115
|
local prompt="$1"
|
|
116
116
|
local candidate_id="$2"
|
|
@@ -118,104 +118,44 @@ call_ai_for_evolution() {
|
|
|
118
118
|
# Get target file path from worker context
|
|
119
119
|
local target_file="$FULL_OUTPUT_DIR/evolution_${candidate_id}.py"
|
|
120
120
|
|
|
121
|
-
#
|
|
122
|
-
local
|
|
123
|
-
local
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
# Capture file state before AI call
|
|
129
|
-
local file_hash_before=""
|
|
130
|
-
local file_mtime_before=""
|
|
131
|
-
if [[ -f "$target_file" ]]; then
|
|
132
|
-
file_hash_before=$(shasum -a 256 "$target_file" 2>/dev/null | cut -d' ' -f1)
|
|
133
|
-
file_mtime_before=$(stat -f %m "$target_file" 2>/dev/null || stat -c %Y "$target_file" 2>/dev/null)
|
|
134
|
-
fi
|
|
121
|
+
# Capture file state before AI call
|
|
122
|
+
local file_hash_before=""
|
|
123
|
+
local file_mtime_before=""
|
|
124
|
+
if [[ -f "$target_file" ]]; then
|
|
125
|
+
file_hash_before=$(shasum -a 256 "$target_file" 2>/dev/null | cut -d' ' -f1)
|
|
126
|
+
file_mtime_before=$(stat -f %m "$target_file" 2>/dev/null || stat -c %Y "$target_file" 2>/dev/null)
|
|
127
|
+
fi
|
|
135
128
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
129
|
+
# Use the centralized AI library for evolution (random model selection)
|
|
130
|
+
local ai_output
|
|
131
|
+
ai_output=$(call_ai_random "$prompt" "run")
|
|
132
|
+
local ai_exit_code=$?
|
|
133
|
+
|
|
134
|
+
# Check if the target file was actually modified
|
|
135
|
+
local file_was_modified=false
|
|
136
|
+
if [[ -f "$target_file" ]]; then
|
|
137
|
+
local file_hash_after
|
|
138
|
+
local file_mtime_after
|
|
139
|
+
file_hash_after=$(shasum -a 256 "$target_file" 2>/dev/null | cut -d' ' -f1)
|
|
140
|
+
file_mtime_after=$(stat -f %m "$target_file" 2>/dev/null || stat -c %Y "$target_file" 2>/dev/null)
|
|
141
|
+
|
|
142
|
+
if [[ "$file_hash_before" != "$file_hash_after" ]] || [[ "$file_mtime_before" != "$file_mtime_after" ]]; then
|
|
143
|
+
file_was_modified=true
|
|
142
144
|
fi
|
|
145
|
+
fi
|
|
143
146
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
local ai_exit_code=$?
|
|
151
|
-
|
|
152
|
-
# Handle special exit codes
|
|
153
|
-
if [[ $ai_exit_code -eq 3 ]]; then
|
|
154
|
-
# All models hit usage limits
|
|
155
|
-
if [[ $retry_count -lt $max_retries ]]; then
|
|
156
|
-
((retry_count++))
|
|
157
|
-
echo "[WORKER-$] All models hit usage limits (retry $retry_count/$max_retries)" >&2
|
|
158
|
-
echo "[WORKER-$] Waiting $wait_seconds seconds ($(($wait_seconds / 60)) minutes) before retrying..." >&2
|
|
159
|
-
|
|
160
|
-
# Sleep with countdown
|
|
161
|
-
local remaining=$wait_seconds
|
|
162
|
-
while [[ $remaining -gt 0 ]]; do
|
|
163
|
-
if [[ $((remaining % 60)) -eq 0 ]]; then
|
|
164
|
-
echo "[WORKER-$] Retrying in $((remaining / 60)) minutes..." >&2
|
|
165
|
-
fi
|
|
166
|
-
sleep 60
|
|
167
|
-
remaining=$((remaining - 60))
|
|
168
|
-
done
|
|
169
|
-
|
|
170
|
-
echo "[WORKER-$] Retrying AI call (attempt #$((retry_count + 1)))..." >&2
|
|
171
|
-
|
|
172
|
-
# Exponential backoff: double the wait time, up to max
|
|
173
|
-
wait_seconds=$((wait_seconds * 2))
|
|
174
|
-
if [[ $wait_seconds -gt $max_wait_seconds ]]; then
|
|
175
|
-
wait_seconds=$max_wait_seconds
|
|
176
|
-
fi
|
|
177
|
-
|
|
178
|
-
# Continue to retry
|
|
179
|
-
continue
|
|
180
|
-
else
|
|
181
|
-
# Exhausted retries
|
|
182
|
-
echo "[WORKER-$] All models hit usage limits after $max_retries retries" >&2
|
|
183
|
-
echo "[WORKER-$] Unable to complete evolution due to API limits" >&2
|
|
184
|
-
# Clean up any partial target file before exiting
|
|
185
|
-
rm -f "$target_file"
|
|
186
|
-
exit 3
|
|
187
|
-
fi
|
|
188
|
-
fi
|
|
189
|
-
|
|
147
|
+
# Success only if the target file was actually modified.
|
|
148
|
+
# Even if AI exited with code 0, if there were no changes, treat as failure to avoid stale copies.
|
|
149
|
+
if [[ "$file_was_modified" == "true" ]]; then
|
|
150
|
+
echo "[WORKER-$$] AI successfully modified $target_file (exit code: $ai_exit_code)" >&2
|
|
151
|
+
return 0
|
|
152
|
+
fi
|
|
190
153
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
local file_mtime_after
|
|
197
|
-
file_hash_after=$(shasum -a 256 "$target_file" 2>/dev/null | cut -d' ' -f1)
|
|
198
|
-
file_mtime_after=$(stat -f %m "$target_file" 2>/dev/null || stat -c %Y "$target_file" 2>/dev/null)
|
|
199
|
-
|
|
200
|
-
if [[ "$file_hash_before" != "$file_hash_after" ]] || [[ "$file_mtime_before" != "$file_mtime_after" ]]; then
|
|
201
|
-
file_was_modified=true
|
|
202
|
-
fi
|
|
203
|
-
fi
|
|
204
|
-
|
|
205
|
-
# Success only if the target file was actually modified.
|
|
206
|
-
# Even if AI exited with code 0, if there were no changes, treat as failure to avoid stale copies.
|
|
207
|
-
if [[ "$file_was_modified" == "true" ]]; then
|
|
208
|
-
echo "[WORKER-$] AI successfully modified $target_file (exit code: $ai_exit_code)" >&2
|
|
209
|
-
return 0
|
|
210
|
-
fi
|
|
211
|
-
|
|
212
|
-
# Non-limit failure - no modification detected; clean up the copied file
|
|
213
|
-
echo "[WORKER-$] AI changed nothing or failed; cleaning up temporary file" >&2
|
|
214
|
-
rm -f "$target_file"
|
|
215
|
-
echo "[WORKER-$] AI failed: exit code $ai_exit_code, no file changes detected" >&2
|
|
216
|
-
return 1
|
|
217
|
-
done
|
|
218
|
-
|
|
154
|
+
# No modification detected; clean up the copied file
|
|
155
|
+
echo "[WORKER-$$] AI changed nothing or failed; cleaning up temporary file" >&2
|
|
156
|
+
rm -f "$target_file"
|
|
157
|
+
echo "[WORKER-$$] AI failed: exit code $ai_exit_code, no file changes detected" >&2
|
|
158
|
+
return 1
|
|
219
159
|
}
|
|
220
160
|
|
|
221
161
|
# Validate paths
|
|
@@ -370,9 +310,9 @@ CRITICAL: If you do not know how to implement what was asked for, or if the requ
|
|
|
370
310
|
return 1
|
|
371
311
|
}
|
|
372
312
|
|
|
373
|
-
#
|
|
313
|
+
# Call AI with random model selection
|
|
374
314
|
if ! call_ai_for_evolution "$evolution_prompt" "$candidate_id"; then
|
|
375
|
-
echo "[WORKER-$$] ERROR:
|
|
315
|
+
echo "[WORKER-$$] ERROR: AI model failed to generate code - leaving as pending for retry" >&2
|
|
376
316
|
safe_popd
|
|
377
317
|
rm -f "$target_file" # Clean up on failure
|
|
378
318
|
# Return with special code to indicate AI failure (should remain pending)
|
package/lib/ai-cli.sh
CHANGED
|
@@ -298,14 +298,13 @@ get_models_for_command() {
|
|
|
298
298
|
echo "$model_list"
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
-
# Call AI with random selection
|
|
302
|
-
# Usage:
|
|
301
|
+
# Call AI with random model selection (no fallback)
|
|
302
|
+
# Usage: call_ai_random <prompt> <command>
|
|
303
303
|
# command: "run" or "ideate"
|
|
304
|
-
#
|
|
305
|
-
|
|
304
|
+
# Picks one random model from the list and uses it
|
|
305
|
+
call_ai_random() {
|
|
306
306
|
local prompt="$1"
|
|
307
307
|
local command="$2"
|
|
308
|
-
local hash_value="${3:-0}"
|
|
309
308
|
|
|
310
309
|
# Get model list for this command
|
|
311
310
|
local model_list
|
|
@@ -324,69 +323,43 @@ call_ai_with_round_robin() {
|
|
|
324
323
|
return 1
|
|
325
324
|
fi
|
|
326
325
|
|
|
327
|
-
#
|
|
326
|
+
# Pick one random model
|
|
328
327
|
local num_models=${#models[@]}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
# Swap models[i] and models[j]
|
|
332
|
-
local temp="${models[i]}"
|
|
333
|
-
models[i]="${models[j]}"
|
|
334
|
-
models[j]="$temp"
|
|
335
|
-
done
|
|
328
|
+
local random_index=$((RANDOM % num_models))
|
|
329
|
+
local model="${models[$random_index]}"
|
|
336
330
|
|
|
337
|
-
|
|
338
|
-
local ordered_models=("${models[@]}")
|
|
331
|
+
echo "[AI] Selected $model for $command (random from $num_models models)" >&2
|
|
339
332
|
|
|
340
|
-
#
|
|
341
|
-
|
|
333
|
+
# Call the AI model
|
|
334
|
+
local ai_output
|
|
335
|
+
ai_output=$(call_ai_model_configured "$model" "$prompt")
|
|
336
|
+
local ai_exit_code=$?
|
|
342
337
|
|
|
343
|
-
#
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
echo "[AI] $model returned exit code 0" >&2
|
|
367
|
-
fi
|
|
368
|
-
# Export the successful model for tracking (used by worker)
|
|
369
|
-
export SUCCESSFUL_RUN_MODEL="$model"
|
|
370
|
-
# Debug: log what AI returned on success
|
|
371
|
-
if [[ "${DEBUG_AI_SUCCESS:-}" == "true" ]]; then
|
|
372
|
-
echo "[AI] $model success output preview:" >&2
|
|
373
|
-
echo "$ai_output" | head -10 >&2
|
|
374
|
-
echo "[AI] (truncated to first 10 lines)" >&2
|
|
375
|
-
fi
|
|
376
|
-
# Output the cleaned result
|
|
377
|
-
echo "$ai_output"
|
|
378
|
-
return 0
|
|
379
|
-
fi
|
|
380
|
-
|
|
381
|
-
echo "[AI] $model returned exit code $ai_exit_code, trying next model..." >&2
|
|
382
|
-
done
|
|
383
|
-
|
|
384
|
-
# All models have been tried
|
|
385
|
-
echo "[AI] All models have been tried without success" >&2
|
|
386
|
-
return 1
|
|
338
|
+
# Clean output if needed
|
|
339
|
+
ai_output=$(clean_ai_output "$ai_output" "$model")
|
|
340
|
+
|
|
341
|
+
# Export the model used for tracking (used by worker)
|
|
342
|
+
export SUCCESSFUL_RUN_MODEL="$model"
|
|
343
|
+
|
|
344
|
+
# Log result
|
|
345
|
+
if [[ $ai_exit_code -eq 0 ]]; then
|
|
346
|
+
echo "[AI] $model returned exit code 0" >&2
|
|
347
|
+
elif [[ $ai_exit_code -eq 124 ]]; then
|
|
348
|
+
echo "[AI] $model timed out (exit code: 124)" >&2
|
|
349
|
+
else
|
|
350
|
+
echo "[AI] $model returned exit code $ai_exit_code" >&2
|
|
351
|
+
fi
|
|
352
|
+
|
|
353
|
+
# Output the result
|
|
354
|
+
echo "$ai_output"
|
|
355
|
+
return $ai_exit_code
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
# Legacy function names for compatibility
|
|
359
|
+
call_ai_with_round_robin() {
|
|
360
|
+
call_ai_random "$@"
|
|
387
361
|
}
|
|
388
362
|
|
|
389
|
-
# Legacy function name for compatibility
|
|
390
363
|
call_ai_with_fallbacks() {
|
|
391
|
-
|
|
364
|
+
call_ai_random "$@"
|
|
392
365
|
}
|
package/lib/config.sh
CHANGED
|
@@ -60,7 +60,7 @@ DEFAULT_WORKER_MAX_CANDIDATES=3
|
|
|
60
60
|
# Default LLM CLI configuration
|
|
61
61
|
DEFAULT_LLM_RUN="glm-zai kimi-coder glm-zai kimi-coder glm-zai kimi-coder codex-oss-local haiku"
|
|
62
62
|
# Ideate: Commercial models for idea generation + local fallback
|
|
63
|
-
DEFAULT_LLM_IDEATE="opus-
|
|
63
|
+
DEFAULT_LLM_IDEATE="opus-think kimi-k2-openrouter gemini-3-pro-preview sonnet-think gpt5high grok-4-openrouter deepseek-openrouter glm-zai"
|
|
64
64
|
|
|
65
65
|
# Load configuration from a YAML file and update variables
|
|
66
66
|
_load_yaml_config() {
|