claude-evolve 1.3.6 → 1.3.8
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-run +36 -60
- package/lib/config.sh +8 -0
- package/lib/csv_helper.py +116 -0
- package/package.json +1 -1
- package/templates/config.yaml +4 -0
package/bin/claude-evolve-run
CHANGED
|
@@ -145,49 +145,20 @@ if [[ ! -f "$FULL_ALGORITHM_PATH" ]]; then
|
|
|
145
145
|
exit 1
|
|
146
146
|
fi
|
|
147
147
|
|
|
148
|
-
# Find oldest pending row (
|
|
148
|
+
# Find oldest pending row (using CSV helper)
|
|
149
149
|
find_empty_row() {
|
|
150
|
-
|
|
151
|
-
local csv_id csv_based_on csv_desc csv_perf csv_status
|
|
152
|
-
while IFS=, read -r csv_id csv_based_on csv_desc csv_perf csv_status; do
|
|
153
|
-
# Look for rows with pending status or empty status (but not complete/failed/running)
|
|
154
|
-
if [[ $csv_status == "pending" || (-z $csv_perf && -z $csv_status) ]]; then
|
|
155
|
-
echo $row_num
|
|
156
|
-
return 0
|
|
157
|
-
fi
|
|
158
|
-
((row_num++))
|
|
159
|
-
done < <(tail -n +2 "$FULL_CSV_PATH")
|
|
160
|
-
return 1
|
|
150
|
+
"$PYTHON_CMD" "$SCRIPT_DIR/../lib/csv_helper.py" find_pending "$FULL_CSV_PATH"
|
|
161
151
|
}
|
|
162
152
|
|
|
163
|
-
# Get CSV row
|
|
164
|
-
get_csv_row() {
|
|
165
|
-
sed -n "${1}p" "$FULL_CSV_PATH"
|
|
166
|
-
}
|
|
153
|
+
# Get CSV row - replaced by csv_helper.py
|
|
167
154
|
|
|
168
|
-
# Update CSV row (
|
|
155
|
+
# Update CSV row (using CSV helper)
|
|
169
156
|
update_csv_row() {
|
|
170
157
|
local row_num="$1"
|
|
171
158
|
local performance="$2"
|
|
172
159
|
local status="$3"
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
local temp_file="${FULL_CSV_PATH}.tmp"
|
|
176
|
-
local current_row=1
|
|
177
|
-
local csv_id csv_based_on csv_desc csv_perf csv_stat
|
|
178
|
-
|
|
179
|
-
while IFS=, read -r csv_id csv_based_on csv_desc csv_perf csv_stat; do
|
|
180
|
-
if [[ $current_row -eq $row_num ]]; then
|
|
181
|
-
# Update this row
|
|
182
|
-
echo "$csv_id,$csv_based_on,$csv_desc,$performance,$status"
|
|
183
|
-
else
|
|
184
|
-
# Keep original row
|
|
185
|
-
echo "$csv_id,$csv_based_on,$csv_desc,$csv_perf,$csv_stat"
|
|
186
|
-
fi
|
|
187
|
-
((current_row++))
|
|
188
|
-
done <"$FULL_CSV_PATH" >"$temp_file"
|
|
189
|
-
|
|
190
|
-
mv "$temp_file" "$FULL_CSV_PATH"
|
|
160
|
+
|
|
161
|
+
"$PYTHON_CMD" "$SCRIPT_DIR/../lib/csv_helper.py" update_row "$FULL_CSV_PATH" "$row_num" "$performance" "$status"
|
|
191
162
|
}
|
|
192
163
|
|
|
193
164
|
# Auto-recovery mechanism for common failures
|
|
@@ -259,46 +230,51 @@ attempt_recovery() {
|
|
|
259
230
|
while true; do
|
|
260
231
|
# Find next candidate
|
|
261
232
|
if ! row_num=$(find_empty_row); then
|
|
262
|
-
echo "[INFO] No more pending candidates found.
|
|
233
|
+
echo "[INFO] No more pending candidates found."
|
|
263
234
|
|
|
264
|
-
# Check if
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
235
|
+
# Check if auto ideation is enabled
|
|
236
|
+
if [[ "$AUTO_IDEATE" == "true" || "$AUTO_IDEATE" == "1" ]]; then
|
|
237
|
+
echo "[INFO] Auto ideation is enabled. Generating new ideas..."
|
|
238
|
+
|
|
239
|
+
# Check if claude-evolve-ideate exists
|
|
240
|
+
ideate_script="$SCRIPT_DIR/claude-evolve-ideate"
|
|
241
|
+
if [[ ! -f "$ideate_script" ]]; then
|
|
242
|
+
echo "[ERROR] claude-evolve-ideate script not found: $ideate_script" >&2
|
|
243
|
+
echo "[INFO] Evolution run complete - no way to generate more ideas."
|
|
244
|
+
exit 0
|
|
245
|
+
fi
|
|
246
|
+
|
|
247
|
+
# Generate new ideas using the multi-strategy approach
|
|
248
|
+
echo "[INFO] Calling claude-evolve-ideate to generate new candidates..."
|
|
249
|
+
if ! "$ideate_script"; then
|
|
250
|
+
echo "[ERROR] Failed to generate new ideas" >&2
|
|
251
|
+
echo "[INFO] Evolution run complete - ideation failed."
|
|
252
|
+
exit 1
|
|
253
|
+
fi
|
|
254
|
+
|
|
255
|
+
echo "[INFO] New ideas generated successfully. Continuing evolution..."
|
|
256
|
+
continue # Go back to start of loop to find the new candidates
|
|
257
|
+
else
|
|
258
|
+
echo "[INFO] Auto ideation is disabled. Evolution run complete."
|
|
269
259
|
exit 0
|
|
270
260
|
fi
|
|
271
|
-
|
|
272
|
-
# Generate new ideas using the multi-strategy approach
|
|
273
|
-
echo "[INFO] Calling claude-evolve-ideate to generate new candidates..."
|
|
274
|
-
if ! "$ideate_script"; then
|
|
275
|
-
echo "[ERROR] Failed to generate new ideas" >&2
|
|
276
|
-
echo "[INFO] Evolution run complete - ideation failed."
|
|
277
|
-
exit 1
|
|
278
|
-
fi
|
|
279
|
-
|
|
280
|
-
echo "[INFO] New ideas generated successfully. Continuing evolution..."
|
|
281
|
-
continue # Go back to start of loop to find the new candidates
|
|
282
261
|
fi
|
|
283
262
|
|
|
284
263
|
# Create log file for this iteration
|
|
285
264
|
LOGFILE="logs/claude-$(date +%Y%m%d_%H%M%S).txt"
|
|
286
265
|
|
|
287
|
-
# Get row data
|
|
288
|
-
|
|
289
|
-
|
|
266
|
+
# Get row data using CSV helper
|
|
267
|
+
eval "$("$PYTHON_CMD" "$SCRIPT_DIR/../lib/csv_helper.py" get_row "$FULL_CSV_PATH" "$row_num")"
|
|
268
|
+
|
|
269
|
+
# Variables are now set: id, basedOnId, description, performance, status
|
|
270
|
+
based_on_id="$basedOnId" # Convert to expected variable name
|
|
290
271
|
|
|
291
272
|
# Check if ID is empty
|
|
292
273
|
if [[ -z $id ]]; then
|
|
293
274
|
echo "[ERROR] Empty ID found at row $row_num. CSV may be malformed." >&2
|
|
294
|
-
echo "[ERROR] Row data: $row_data" >&2
|
|
295
275
|
exit 1
|
|
296
276
|
fi
|
|
297
277
|
|
|
298
|
-
# Clean up description (remove quotes)
|
|
299
|
-
description=${description#\"}
|
|
300
|
-
description=${description%\"}
|
|
301
|
-
|
|
302
278
|
echo "[INFO] Processing candidate ID: $id"
|
|
303
279
|
echo "[INFO] Description: $description"
|
|
304
280
|
echo "[INFO] Based on ID: $based_on_id"
|
package/lib/config.sh
CHANGED
|
@@ -24,6 +24,9 @@ DEFAULT_PARALLEL_ENABLED=false
|
|
|
24
24
|
DEFAULT_MAX_WORKERS=4
|
|
25
25
|
DEFAULT_LOCK_TIMEOUT=30
|
|
26
26
|
|
|
27
|
+
# Default auto ideation value
|
|
28
|
+
DEFAULT_AUTO_IDEATE=true
|
|
29
|
+
|
|
27
30
|
# Load configuration from config file
|
|
28
31
|
load_config() {
|
|
29
32
|
# Accept config file path as parameter
|
|
@@ -52,6 +55,9 @@ load_config() {
|
|
|
52
55
|
MAX_WORKERS="$DEFAULT_MAX_WORKERS"
|
|
53
56
|
LOCK_TIMEOUT="$DEFAULT_LOCK_TIMEOUT"
|
|
54
57
|
|
|
58
|
+
# Set auto ideation default
|
|
59
|
+
AUTO_IDEATE="$DEFAULT_AUTO_IDEATE"
|
|
60
|
+
|
|
55
61
|
# Load config if found
|
|
56
62
|
if [[ -f "$config_file" ]]; then
|
|
57
63
|
echo "[INFO] Loading configuration from: $config_file"
|
|
@@ -127,6 +133,7 @@ load_config() {
|
|
|
127
133
|
output_dir) OUTPUT_DIR="$value" ;;
|
|
128
134
|
parent_selection) PARENT_SELECTION="$value" ;;
|
|
129
135
|
python_cmd) PYTHON_CMD="$value" ;;
|
|
136
|
+
auto_ideate) AUTO_IDEATE="$value" ;;
|
|
130
137
|
esac
|
|
131
138
|
fi
|
|
132
139
|
done < "$config_file"
|
|
@@ -202,4 +209,5 @@ show_config() {
|
|
|
202
209
|
echo " Parallel enabled: $PARALLEL_ENABLED"
|
|
203
210
|
echo " Max workers: $MAX_WORKERS"
|
|
204
211
|
echo " Lock timeout: $LOCK_TIMEOUT"
|
|
212
|
+
echo " Auto ideate: $AUTO_IDEATE"
|
|
205
213
|
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
CSV helper for claude-evolve to properly handle CSV parsing with quoted fields.
|
|
4
|
+
"""
|
|
5
|
+
import csv
|
|
6
|
+
import sys
|
|
7
|
+
import json
|
|
8
|
+
|
|
9
|
+
def find_pending_row(csv_path):
|
|
10
|
+
"""Find the first pending row in the CSV."""
|
|
11
|
+
with open(csv_path, 'r') as f:
|
|
12
|
+
reader = csv.reader(f)
|
|
13
|
+
next(reader) # Skip header
|
|
14
|
+
for row_num, row in enumerate(reader, start=2):
|
|
15
|
+
# Ensure row has at least 5 fields
|
|
16
|
+
while len(row) < 5:
|
|
17
|
+
row.append('')
|
|
18
|
+
|
|
19
|
+
status = row[4].strip()
|
|
20
|
+
# Check if status is pending or empty
|
|
21
|
+
if status == 'pending' or status == '':
|
|
22
|
+
return row_num
|
|
23
|
+
return None
|
|
24
|
+
|
|
25
|
+
def get_row_data(csv_path, row_num):
|
|
26
|
+
"""Get data from a specific row."""
|
|
27
|
+
with open(csv_path, 'r') as f:
|
|
28
|
+
reader = csv.reader(f)
|
|
29
|
+
for i, row in enumerate(reader, start=1):
|
|
30
|
+
if i == row_num:
|
|
31
|
+
# Ensure row has at least 5 fields
|
|
32
|
+
while len(row) < 5:
|
|
33
|
+
row.append('')
|
|
34
|
+
return {
|
|
35
|
+
'id': row[0],
|
|
36
|
+
'basedOnId': row[1],
|
|
37
|
+
'description': row[2],
|
|
38
|
+
'performance': row[3],
|
|
39
|
+
'status': row[4]
|
|
40
|
+
}
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
def update_row(csv_path, row_num, performance, status):
|
|
44
|
+
"""Update a specific row in the CSV."""
|
|
45
|
+
rows = []
|
|
46
|
+
with open(csv_path, 'r') as f:
|
|
47
|
+
reader = csv.reader(f)
|
|
48
|
+
rows = list(reader)
|
|
49
|
+
|
|
50
|
+
# Update the specific row
|
|
51
|
+
if row_num <= len(rows):
|
|
52
|
+
row = rows[row_num - 1]
|
|
53
|
+
# Ensure row has at least 5 fields
|
|
54
|
+
while len(row) < 5:
|
|
55
|
+
row.append('')
|
|
56
|
+
row[3] = performance # performance field
|
|
57
|
+
row[4] = status # status field
|
|
58
|
+
|
|
59
|
+
# Write back
|
|
60
|
+
with open(csv_path, 'w', newline='') as f:
|
|
61
|
+
writer = csv.writer(f)
|
|
62
|
+
writer.writerows(rows)
|
|
63
|
+
|
|
64
|
+
if __name__ == '__main__':
|
|
65
|
+
if len(sys.argv) < 3:
|
|
66
|
+
print("Usage: csv_helper.py <command> <csv_path> [args...]", file=sys.stderr)
|
|
67
|
+
sys.exit(1)
|
|
68
|
+
|
|
69
|
+
command = sys.argv[1]
|
|
70
|
+
csv_path = sys.argv[2]
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
if command == 'find_pending':
|
|
74
|
+
row_num = find_pending_row(csv_path)
|
|
75
|
+
if row_num:
|
|
76
|
+
print(row_num)
|
|
77
|
+
sys.exit(0)
|
|
78
|
+
else:
|
|
79
|
+
sys.exit(1)
|
|
80
|
+
|
|
81
|
+
elif command == 'get_row':
|
|
82
|
+
if len(sys.argv) < 4:
|
|
83
|
+
print("Usage: csv_helper.py get_row <csv_path> <row_num>", file=sys.stderr)
|
|
84
|
+
sys.exit(1)
|
|
85
|
+
row_num = int(sys.argv[3])
|
|
86
|
+
data = get_row_data(csv_path, row_num)
|
|
87
|
+
if data:
|
|
88
|
+
# Output as shell variable assignments
|
|
89
|
+
for key, value in data.items():
|
|
90
|
+
# Escape special characters for shell
|
|
91
|
+
value = value.replace('\\', '\\\\')
|
|
92
|
+
value = value.replace('"', '\\"')
|
|
93
|
+
value = value.replace('$', '\\$')
|
|
94
|
+
value = value.replace('`', '\\`')
|
|
95
|
+
print(f'{key}="{value}"')
|
|
96
|
+
sys.exit(0)
|
|
97
|
+
else:
|
|
98
|
+
sys.exit(1)
|
|
99
|
+
|
|
100
|
+
elif command == 'update_row':
|
|
101
|
+
if len(sys.argv) < 6:
|
|
102
|
+
print("Usage: csv_helper.py update_row <csv_path> <row_num> <performance> <status>", file=sys.stderr)
|
|
103
|
+
sys.exit(1)
|
|
104
|
+
row_num = int(sys.argv[3])
|
|
105
|
+
performance = sys.argv[4]
|
|
106
|
+
status = sys.argv[5]
|
|
107
|
+
update_row(csv_path, row_num, performance, status)
|
|
108
|
+
sys.exit(0)
|
|
109
|
+
|
|
110
|
+
else:
|
|
111
|
+
print(f"Unknown command: {command}", file=sys.stderr)
|
|
112
|
+
sys.exit(1)
|
|
113
|
+
|
|
114
|
+
except Exception as e:
|
|
115
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
116
|
+
sys.exit(1)
|
package/package.json
CHANGED
package/templates/config.yaml
CHANGED
|
@@ -37,6 +37,10 @@ ideation_strategies:
|
|
|
37
37
|
# Python command to use for evaluation
|
|
38
38
|
python_cmd: "python3"
|
|
39
39
|
|
|
40
|
+
# Auto ideation configuration
|
|
41
|
+
# When true, automatically generate new ideas when no pending candidates remain
|
|
42
|
+
auto_ideate: true
|
|
43
|
+
|
|
40
44
|
# Parallel execution configuration
|
|
41
45
|
parallel:
|
|
42
46
|
# Enable parallel execution of evolution candidates
|