borisxdave 0.3.4__tar.gz → 0.3.5__tar.gz
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.
- {borisxdave-0.3.4/borisxdave.egg-info → borisxdave-0.3.5}/PKG-INFO +1 -1
- {borisxdave-0.3.4 → borisxdave-0.3.5}/boris.py +42 -13
- {borisxdave-0.3.4 → borisxdave-0.3.5/borisxdave.egg-info}/PKG-INFO +1 -1
- {borisxdave-0.3.4 → borisxdave-0.3.5}/setup.py +1 -1
- {borisxdave-0.3.4 → borisxdave-0.3.5}/MANIFEST.in +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/boris_prompt.md +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/boris_prompt_data.py +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/borisxdave.egg-info/SOURCES.txt +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/borisxdave.egg-info/dependency_links.txt +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/borisxdave.egg-info/entry_points.txt +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/borisxdave.egg-info/top_level.txt +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/config.py +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/engine.py +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/file_lock.py +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/git_manager.py +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/planner.py +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/prompts.py +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/requirements.txt +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/setup.cfg +0 -0
- {borisxdave-0.3.4 → borisxdave-0.3.5}/state.py +0 -0
|
@@ -14,6 +14,8 @@ if hasattr(sys.stdout, "reconfigure"):
|
|
|
14
14
|
pass
|
|
15
15
|
os.environ["PYTHONUNBUFFERED"] = "1"
|
|
16
16
|
|
|
17
|
+
import threading
|
|
18
|
+
import time as _time
|
|
17
19
|
import engine
|
|
18
20
|
import git_manager
|
|
19
21
|
import prompts
|
|
@@ -811,30 +813,39 @@ def _print_swarm_dashboard(project_dir: str, batch_num: int, batch_milestones: l
|
|
|
811
813
|
return
|
|
812
814
|
|
|
813
815
|
active = sum(1 for s in statuses.values() if s.get("state") in ("starting", "working"))
|
|
816
|
+
done = sum(1 for s in statuses.values() if s.get("state") == "done")
|
|
814
817
|
total_actions = sum(s.get("actions", 0) for s in statuses.values())
|
|
815
818
|
|
|
819
|
+
elapsed = ""
|
|
820
|
+
started_times = [s.get("started_at", 0) for s in statuses.values() if s.get("started_at")]
|
|
821
|
+
if started_times:
|
|
822
|
+
elapsed_sec = int(_time.time() - min(started_times))
|
|
823
|
+
elapsed = f" | Elapsed: {elapsed_sec // 60}m {elapsed_sec % 60}s"
|
|
824
|
+
|
|
816
825
|
print(flush=True)
|
|
817
|
-
print("
|
|
818
|
-
print(f"Batch {batch_num}
|
|
819
|
-
print(flush=True)
|
|
826
|
+
print("╔══════════════════════════════════════════════════════════════════╗", flush=True)
|
|
827
|
+
print(f"║ BORIS SWARM DASHBOARD │ Batch {batch_num} │ {active} active / {done} done / {len(statuses)} total{elapsed}", flush=True)
|
|
828
|
+
print("╠══════════════════════════════════════════════════════════════════╣", flush=True)
|
|
820
829
|
|
|
821
830
|
for m in batch_milestones:
|
|
822
831
|
status = statuses.get(m.id, {})
|
|
823
|
-
state = status.get("state", "
|
|
832
|
+
state = status.get("state", "waiting")
|
|
824
833
|
actions = status.get("actions", 0)
|
|
825
834
|
reasoning = status.get("reasoning_blocks", 0)
|
|
826
835
|
interrupts = status.get("interrupts", 0)
|
|
827
836
|
last = status.get("last_action", "")
|
|
828
837
|
|
|
829
838
|
# Progress indicator based on reasoning blocks (rough proxy)
|
|
830
|
-
bar_len = min(reasoning,
|
|
831
|
-
bar = "
|
|
839
|
+
bar_len = min(reasoning, 20)
|
|
840
|
+
bar = "█" * bar_len + "░" * (20 - bar_len)
|
|
832
841
|
|
|
842
|
+
state_icons = {"starting": "⏳", "working": "⚙️", "done": "✅", "failed": "❌"}
|
|
843
|
+
icon = state_icons.get(state, "⏸️")
|
|
833
844
|
state_str = state.upper()
|
|
834
|
-
interrupt_str = f"
|
|
835
|
-
print(f"[{m.id}] {m.title[:
|
|
845
|
+
interrupt_str = f" │ ⚠ {interrupts} interrupts" if interrupts > 0 else ""
|
|
846
|
+
print(f"║ {icon} [{m.id}] {m.title[:28]:<28} [{bar}] {state_str:>8} │ {actions:>3} actions{interrupt_str}", flush=True)
|
|
836
847
|
if last:
|
|
837
|
-
print(f"
|
|
848
|
+
print(f"║ └─ {last[:60]}", flush=True)
|
|
838
849
|
|
|
839
850
|
# Show file locks if file_lock.py is available
|
|
840
851
|
try:
|
|
@@ -843,14 +854,29 @@ def _print_swarm_dashboard(project_dir: str, batch_num: int, batch_milestones: l
|
|
|
843
854
|
locks = flm.get_locked_files()
|
|
844
855
|
if locks:
|
|
845
856
|
lock_strs = [f"{os.path.basename(f)} ({owner})" for f, owner in locks.items()]
|
|
846
|
-
print(f"
|
|
857
|
+
print(f"║ 🔒 Locks: {', '.join(lock_strs)}", flush=True)
|
|
847
858
|
except ImportError:
|
|
848
859
|
pass
|
|
849
860
|
|
|
850
|
-
print("
|
|
861
|
+
print("╚══════════════════════════════════════════════════════════════════╝", flush=True)
|
|
851
862
|
print(flush=True)
|
|
852
863
|
|
|
853
864
|
|
|
865
|
+
def _start_live_dashboard(project_dir: str, batch_num: int, batch_milestones: list, interval: float = 10.0):
|
|
866
|
+
"""Start a background thread that prints the swarm dashboard periodically."""
|
|
867
|
+
stop_event = threading.Event()
|
|
868
|
+
|
|
869
|
+
def _loop():
|
|
870
|
+
while not stop_event.is_set():
|
|
871
|
+
stop_event.wait(interval)
|
|
872
|
+
if not stop_event.is_set():
|
|
873
|
+
_print_swarm_dashboard(project_dir, batch_num, batch_milestones)
|
|
874
|
+
|
|
875
|
+
t = threading.Thread(target=_loop, daemon=True)
|
|
876
|
+
t.start()
|
|
877
|
+
return stop_event
|
|
878
|
+
|
|
879
|
+
|
|
854
880
|
def _apply_preset(args):
|
|
855
881
|
"""Apply a swarm preset to args if specified. Preset implies --swarm."""
|
|
856
882
|
if not args.preset:
|
|
@@ -1141,11 +1167,14 @@ def main():
|
|
|
1141
1167
|
tasks.append((prompt, m))
|
|
1142
1168
|
prompt_map[m.id] = prompt
|
|
1143
1169
|
|
|
1144
|
-
# Run all DaveLoops in parallel
|
|
1170
|
+
# Run all DaveLoops in parallel with live dashboard
|
|
1145
1171
|
isolation = getattr(args, 'isolation', 'none') if getattr(args, 'swarm', False) else 'none'
|
|
1172
|
+
_print_swarm_dashboard(project_dir, batch_num, ready)
|
|
1173
|
+
dashboard_stop = _start_live_dashboard(project_dir, batch_num, ready, interval=15.0)
|
|
1146
1174
|
parallel_results = engine.run_parallel(tasks, project_dir, args.max_iter, isolation=isolation)
|
|
1175
|
+
dashboard_stop.set()
|
|
1147
1176
|
|
|
1148
|
-
# Print swarm dashboard after parallel run completes (B7)
|
|
1177
|
+
# Print final swarm dashboard after parallel run completes (B7)
|
|
1149
1178
|
_print_swarm_dashboard(project_dir, batch_num, ready)
|
|
1150
1179
|
engine.clear_worker_statuses(project_dir)
|
|
1151
1180
|
|
|
@@ -2,7 +2,7 @@ from setuptools import setup
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="borisxdave",
|
|
5
|
-
version="0.3.
|
|
5
|
+
version="0.3.5",
|
|
6
6
|
description="Boris - Autonomous Project Orchestrator",
|
|
7
7
|
py_modules=["boris", "engine", "git_manager", "prompts", "state", "planner", "config", "file_lock", "boris_prompt_data"],
|
|
8
8
|
python_requires=">=3.8",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|