forked from leonvanzyl/autonomous-coding
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprogress.py
More file actions
155 lines (128 loc) · 5.07 KB
/
progress.py
File metadata and controls
155 lines (128 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
"""
Progress Tracking Utilities
===========================
Functions for tracking and displaying progress of the autonomous coding agent.
"""
import json
import os
import urllib.request
from datetime import datetime
from pathlib import Path
WEBHOOK_URL = os.environ.get("PROGRESS_N8N_WEBHOOK_URL")
PROGRESS_CACHE_FILE = ".progress_cache"
def send_progress_webhook(passing: int, total: int, project_dir: Path) -> None:
"""Send webhook notification when progress increases."""
if not WEBHOOK_URL:
return # Webhook not configured
cache_file = project_dir / PROGRESS_CACHE_FILE
previous = 0
previous_passing_tests = set()
# Read previous progress and passing test indices
if cache_file.exists():
try:
cache_data = json.loads(cache_file.read_text())
previous = cache_data.get("count", 0)
previous_passing_tests = set(cache_data.get("passing_indices", []))
except:
previous = 0
# Only notify if progress increased
if passing > previous:
# Find which tests are now passing
tests_file = project_dir / "feature_list.json"
completed_tests = []
current_passing_indices = []
if tests_file.exists():
try:
with open(tests_file, "r") as f:
tests = json.load(f)
for i, test in enumerate(tests):
if test.get("passes", False):
current_passing_indices.append(i)
if i not in previous_passing_tests:
# This test is newly passing
desc = test.get("description", f"Test #{i+1}")
category = test.get("category", "")
if category:
completed_tests.append(f"[{category}] {desc}")
else:
completed_tests.append(desc)
except:
pass
payload = {
"event": "test_progress",
"passing": passing,
"total": total,
"percentage": round((passing / total) * 100, 1) if total > 0 else 0,
"previous_passing": previous,
"tests_completed_this_session": passing - previous,
"completed_tests": completed_tests,
"project": project_dir.name,
"timestamp": datetime.utcnow().isoformat() + "Z"
}
try:
req = urllib.request.Request(
WEBHOOK_URL,
data=json.dumps([payload]).encode('utf-8'), # n8n expects array
headers={'Content-Type': 'application/json'}
)
urllib.request.urlopen(req, timeout=5)
except Exception as e:
print(f"[Webhook notification failed: {e}]")
# Update cache with count and passing indices
cache_file.write_text(json.dumps({
"count": passing,
"passing_indices": current_passing_indices
}))
else:
# Update cache even if no change (for initial state)
if not cache_file.exists():
tests_file = project_dir / "feature_list.json"
current_passing_indices = []
if tests_file.exists():
try:
with open(tests_file, "r") as f:
tests = json.load(f)
for i, test in enumerate(tests):
if test.get("passes", False):
current_passing_indices.append(i)
except:
pass
cache_file.write_text(json.dumps({
"count": passing,
"passing_indices": current_passing_indices
}))
def count_passing_tests(project_dir: Path) -> tuple[int, int]:
"""
Count passing and total tests in feature_list.json.
Args:
project_dir: Directory containing feature_list.json
Returns:
(passing_count, total_count)
"""
tests_file = project_dir / "feature_list.json"
if not tests_file.exists():
return 0, 0
try:
with open(tests_file, "r") as f:
tests = json.load(f)
total = len(tests)
passing = sum(1 for test in tests if test.get("passes", False))
return passing, total
except (json.JSONDecodeError, IOError):
return 0, 0
def print_session_header(session_num: int, is_initializer: bool) -> None:
"""Print a formatted header for the session."""
session_type = "INITIALIZER" if is_initializer else "CODING AGENT"
print("\n" + "=" * 70)
print(f" SESSION {session_num}: {session_type}")
print("=" * 70)
print()
def print_progress_summary(project_dir: Path) -> None:
"""Print a summary of current progress."""
passing, total = count_passing_tests(project_dir)
if total > 0:
percentage = (passing / total) * 100
print(f"\nProgress: {passing}/{total} tests passing ({percentage:.1f}%)")
send_progress_webhook(passing, total, project_dir)
else:
print("\nProgress: feature_list.json not yet created")