claude-evolve 1.3.42 → 1.3.44
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 +6 -19
- package/lib/csv-lock.sh +3 -0
- package/lib/csv_helper_robust.py +121 -0
- package/package.json +1 -1
package/bin/claude-evolve-worker
CHANGED
|
@@ -382,41 +382,28 @@ echo "[WORKER-$$] Running evaluation..."
|
|
|
382
382
|
eval_output=""
|
|
383
383
|
eval_exit_code=0
|
|
384
384
|
|
|
385
|
-
# Stream evaluator output in real-time while capturing it
|
|
386
|
-
eval_tempfile=$(mktemp)
|
|
387
385
|
if [[ -n $timeout_seconds ]]; then
|
|
388
386
|
echo "[WORKER-$$] Evaluation timeout: ${timeout_seconds}s"
|
|
389
|
-
#
|
|
390
|
-
if EXPERIMENT_ID="$id" timeout "$timeout_seconds" "$PYTHON_CMD" "$FULL_EVALUATOR_PATH" "$output_file"
|
|
391
|
-
|
|
392
|
-
echo "[EVALUATOR] $line" >&2
|
|
393
|
-
done; then
|
|
394
|
-
eval_exit_code=${PIPESTATUS[0]}
|
|
387
|
+
# For Modal compatibility, don't capture stderr
|
|
388
|
+
if eval_output=$(EXPERIMENT_ID="$id" timeout "$timeout_seconds" "$PYTHON_CMD" "$FULL_EVALUATOR_PATH" "$output_file"); then
|
|
389
|
+
eval_exit_code=0
|
|
395
390
|
else
|
|
396
391
|
eval_exit_code=$?
|
|
397
392
|
if [[ $eval_exit_code -eq 124 ]]; then
|
|
398
393
|
echo "[ERROR] Evaluation timed out" >&2
|
|
399
394
|
update_csv_row_with_lock "$candidate_id" "status" "timeout"
|
|
400
|
-
rm -f "$eval_tempfile"
|
|
401
395
|
exit 1
|
|
402
396
|
fi
|
|
403
397
|
fi
|
|
404
398
|
else
|
|
405
|
-
#
|
|
406
|
-
if EXPERIMENT_ID="$id" "$PYTHON_CMD" "$FULL_EVALUATOR_PATH" "$output_file"
|
|
407
|
-
|
|
408
|
-
echo "[EVALUATOR] $line" >&2
|
|
409
|
-
done; then
|
|
410
|
-
eval_exit_code=${PIPESTATUS[0]}
|
|
399
|
+
# For Modal compatibility, don't capture stderr
|
|
400
|
+
if eval_output=$(EXPERIMENT_ID="$id" "$PYTHON_CMD" "$FULL_EVALUATOR_PATH" "$output_file"); then
|
|
401
|
+
eval_exit_code=0
|
|
411
402
|
else
|
|
412
403
|
eval_exit_code=$?
|
|
413
404
|
fi
|
|
414
405
|
fi
|
|
415
406
|
|
|
416
|
-
# Read the complete output from temp file
|
|
417
|
-
eval_output=$(cat "$eval_tempfile")
|
|
418
|
-
rm -f "$eval_tempfile"
|
|
419
|
-
|
|
420
407
|
# Log evaluator output
|
|
421
408
|
{
|
|
422
409
|
echo "=== WORKER $$ - EVALUATOR OUTPUT ==="
|
package/lib/csv-lock.sh
CHANGED
|
@@ -251,6 +251,9 @@ with open('$csv_file', 'r') as f:
|
|
|
251
251
|
candidate_id = None
|
|
252
252
|
original_status = None
|
|
253
253
|
for i in range(1, len(rows)):
|
|
254
|
+
# Skip empty rows
|
|
255
|
+
if not rows[i] or len(rows[i]) == 0:
|
|
256
|
+
continue
|
|
254
257
|
# If row has fewer than 5 fields, it's pending
|
|
255
258
|
if len(rows[i]) < 5:
|
|
256
259
|
candidate_id = rows[i][0]
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Robust CSV helper for evolution system that handles edge cases properly."""
|
|
3
|
+
|
|
4
|
+
import csv
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def is_valid_candidate_row(row):
|
|
9
|
+
"""Check if a row represents a valid candidate (not empty, has ID)."""
|
|
10
|
+
if not row:
|
|
11
|
+
return False
|
|
12
|
+
if len(row) == 0:
|
|
13
|
+
return False
|
|
14
|
+
# First column should have a non-empty ID
|
|
15
|
+
if not row[0] or row[0].strip() == '':
|
|
16
|
+
return False
|
|
17
|
+
return True
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def is_pending_candidate(row):
|
|
21
|
+
"""Check if a candidate row is pending (needs processing)."""
|
|
22
|
+
if not is_valid_candidate_row(row):
|
|
23
|
+
return False
|
|
24
|
+
|
|
25
|
+
# Must have at least 5 columns to check status
|
|
26
|
+
if len(row) < 5:
|
|
27
|
+
return True # Incomplete row is pending
|
|
28
|
+
|
|
29
|
+
# Check status field (5th column, index 4)
|
|
30
|
+
status = row[4].strip().lower() if row[4] else ''
|
|
31
|
+
|
|
32
|
+
# Blank, missing, "pending", or "running" all mean pending
|
|
33
|
+
if not status or status in ['pending', 'running']:
|
|
34
|
+
return True
|
|
35
|
+
|
|
36
|
+
# Check for retry statuses
|
|
37
|
+
if status.startswith('failed-retry'):
|
|
38
|
+
return True
|
|
39
|
+
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_pending_candidates(csv_file):
|
|
44
|
+
"""Get list of pending candidate IDs from CSV."""
|
|
45
|
+
pending = []
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
with open(csv_file, 'r') as f:
|
|
49
|
+
reader = csv.reader(f)
|
|
50
|
+
# Skip header
|
|
51
|
+
next(reader, None)
|
|
52
|
+
|
|
53
|
+
for row in reader:
|
|
54
|
+
if is_pending_candidate(row):
|
|
55
|
+
candidate_id = row[0].strip()
|
|
56
|
+
status = row[4].strip() if len(row) > 4 else ''
|
|
57
|
+
pending.append((candidate_id, status))
|
|
58
|
+
|
|
59
|
+
except Exception as e:
|
|
60
|
+
print(f"Error reading CSV: {e}", file=sys.stderr)
|
|
61
|
+
return []
|
|
62
|
+
|
|
63
|
+
return pending
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def update_candidate_status(csv_file, candidate_id, new_status):
|
|
67
|
+
"""Update the status of a specific candidate."""
|
|
68
|
+
rows = []
|
|
69
|
+
updated = False
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
# Read all rows
|
|
73
|
+
with open(csv_file, 'r') as f:
|
|
74
|
+
reader = csv.reader(f)
|
|
75
|
+
rows = list(reader)
|
|
76
|
+
|
|
77
|
+
# Update the specific candidate
|
|
78
|
+
for i, row in enumerate(rows):
|
|
79
|
+
if is_valid_candidate_row(row) and row[0].strip() == candidate_id:
|
|
80
|
+
# Ensure row has at least 5 columns
|
|
81
|
+
while len(row) < 5:
|
|
82
|
+
row.append('')
|
|
83
|
+
row[4] = new_status
|
|
84
|
+
updated = True
|
|
85
|
+
break
|
|
86
|
+
|
|
87
|
+
# Write back if updated
|
|
88
|
+
if updated:
|
|
89
|
+
with open(csv_file, 'w', newline='') as f:
|
|
90
|
+
writer = csv.writer(f)
|
|
91
|
+
writer.writerows(rows)
|
|
92
|
+
|
|
93
|
+
return updated
|
|
94
|
+
|
|
95
|
+
except Exception as e:
|
|
96
|
+
print(f"Error updating CSV: {e}", file=sys.stderr)
|
|
97
|
+
return False
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if __name__ == '__main__':
|
|
101
|
+
# Test functionality
|
|
102
|
+
if len(sys.argv) < 2:
|
|
103
|
+
print("Usage: csv_helper_robust.py <csv_file> [command]")
|
|
104
|
+
sys.exit(1)
|
|
105
|
+
|
|
106
|
+
csv_file = sys.argv[1]
|
|
107
|
+
command = sys.argv[2] if len(sys.argv) > 2 else 'list'
|
|
108
|
+
|
|
109
|
+
if command == 'list':
|
|
110
|
+
pending = get_pending_candidates(csv_file)
|
|
111
|
+
for candidate_id, status in pending:
|
|
112
|
+
print(f"{candidate_id}|{status}")
|
|
113
|
+
|
|
114
|
+
elif command == 'update' and len(sys.argv) >= 5:
|
|
115
|
+
candidate_id = sys.argv[3]
|
|
116
|
+
new_status = sys.argv[4]
|
|
117
|
+
if update_candidate_status(csv_file, candidate_id, new_status):
|
|
118
|
+
print(f"Updated {candidate_id} to {new_status}")
|
|
119
|
+
else:
|
|
120
|
+
print(f"Failed to update {candidate_id}")
|
|
121
|
+
sys.exit(1)
|