borisxdave 0.3.4__py3-none-any.whl → 0.3.5__py3-none-any.whl

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.
boris.py CHANGED
@@ -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("=== BORIS SWARM STATUS ===", flush=True)
818
- print(f"Batch {batch_num} | Workers: {active} active / {len(statuses)} total | Actions: {total_actions}", flush=True)
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", "unknown")
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, 10)
831
- bar = "#" * bar_len + "-" * (10 - bar_len)
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" | {interrupts} interrupts" if interrupts > 0 else ""
835
- print(f"[{m.id}] {m.title[:30]:<30} [{bar}] {state_str} | {actions} actions{interrupt_str}", flush=True)
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" Last: {last}", flush=True)
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"\nFile locks: {', '.join(lock_strs)}", flush=True)
857
+ print(f"║ 🔒 Locks: {', '.join(lock_strs)}", flush=True)
847
858
  except ImportError:
848
859
  pass
849
860
 
850
- print("===========================", flush=True)
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: borisxdave
3
- Version: 0.3.4
3
+ Version: 0.3.5
4
4
  Summary: Boris - Autonomous Project Orchestrator
5
5
  Requires-Python: >=3.8
6
6
  Dynamic: requires-python
@@ -1,4 +1,4 @@
1
- boris.py,sha256=x758NOe-Gl-57nYlfgMyEyPNfqf0RdfSSjeNVZFak9I,63834
1
+ boris.py,sha256=EyqRUeVvPl8775cq3x8cUnsc26zc0W2tVp0xI0ET8_c,65767
2
2
  boris_prompt_data.py,sha256=ZBvWMrQOBrl07cNFzgeGumJ54cYg0Be9RSSnK6a3YQY,7940
3
3
  config.py,sha256=KfFKyCGasdm1yBvIRFv-ykzA_oRo-zu1Euu9YC7V1Cg,324
4
4
  engine.py,sha256=Pdu0i4XrNxiU246EV8MjXvYp9CBvuJWGLA18QMIYvFM,37468
@@ -7,8 +7,8 @@ git_manager.py,sha256=BuuTT4naPb5-jLhOik1xHM2ztzuKvJ_bnecZmlYgwFs,8493
7
7
  planner.py,sha256=UrU--kBvzvyD1gOVxIn-kdbJiu8tt4rcowsln66WkGw,5670
8
8
  prompts.py,sha256=-eSwZ-oTBR12Wx4Md57sVF816T9vHEFlMsvT4zMkwOg,35187
9
9
  state.py,sha256=2DCPlcM7SBlCkwWvcnIabltcduv74W46FZ7DxKurWkw,5752
10
- borisxdave-0.3.4.dist-info/METADATA,sha256=2xBFOjfdS4w_Tlb5MrdRqFs6rJ4YBWCBvnXhitrWC9I,175
11
- borisxdave-0.3.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
12
- borisxdave-0.3.4.dist-info/entry_points.txt,sha256=a6FLWgxiQjGMJIRSV5sDxaaaaQchunm04ZuzX8N7-6I,61
13
- borisxdave-0.3.4.dist-info/top_level.txt,sha256=C3fTm1vt0QEQyJtvSZiFiOvmR4d0hWmmr6hujJqFrQE,82
14
- borisxdave-0.3.4.dist-info/RECORD,,
10
+ borisxdave-0.3.5.dist-info/METADATA,sha256=Dtf07RlDONn9a_8nRi2elIb3mi6w7CTEy2hJQ_UIOU4,175
11
+ borisxdave-0.3.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
12
+ borisxdave-0.3.5.dist-info/entry_points.txt,sha256=a6FLWgxiQjGMJIRSV5sDxaaaaQchunm04ZuzX8N7-6I,61
13
+ borisxdave-0.3.5.dist-info/top_level.txt,sha256=C3fTm1vt0QEQyJtvSZiFiOvmR4d0hWmmr6hujJqFrQE,82
14
+ borisxdave-0.3.5.dist-info/RECORD,,