feat(mma): Implement MMA Dashboard, Event Handling, and Step Approval Modal in gui_2.py
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import ai_client
|
||||
import json
|
||||
import asyncio
|
||||
from typing import List, Optional
|
||||
from dataclasses import asdict
|
||||
import events
|
||||
from models import Ticket, Track, WorkerContext
|
||||
from file_cache import ASTParser
|
||||
|
||||
@@ -8,8 +11,24 @@ class ConductorEngine:
|
||||
"""
|
||||
Orchestrates the execution of tickets within a track.
|
||||
"""
|
||||
def __init__(self, track: Track):
|
||||
def __init__(self, track: Track, event_queue: Optional[events.AsyncEventQueue] = None):
|
||||
self.track = track
|
||||
self.event_queue = event_queue
|
||||
|
||||
async def _push_state(self, status: str = "running", active_tier: str = None):
|
||||
if not self.event_queue:
|
||||
return
|
||||
|
||||
payload = {
|
||||
"status": status,
|
||||
"active_tier": active_tier,
|
||||
"track": {
|
||||
"id": self.track.id,
|
||||
"title": self.track.description,
|
||||
},
|
||||
"tickets": [asdict(t) for t in self.track.tickets]
|
||||
}
|
||||
await self.event_queue.put("mma_state_update", payload)
|
||||
|
||||
def parse_json_tickets(self, json_str: str):
|
||||
"""
|
||||
@@ -38,13 +57,15 @@ class ConductorEngine:
|
||||
except KeyError as e:
|
||||
print(f"Missing required field in ticket definition: {e}")
|
||||
|
||||
def run_linear(self):
|
||||
async def run_linear(self):
|
||||
"""
|
||||
Executes tickets sequentially according to their dependencies.
|
||||
Iterates through the track's executable tickets until no more can be run.
|
||||
Supports dynamic execution as tickets added during runtime will be picked up
|
||||
in the next iteration of the main loop.
|
||||
"""
|
||||
await self._push_state(status="running", active_tier="Tier 2 (Tech Lead)")
|
||||
|
||||
while True:
|
||||
executable = self.track.get_executable_tickets()
|
||||
if not executable:
|
||||
@@ -52,14 +73,17 @@ class ConductorEngine:
|
||||
all_done = all(t.status == "completed" for t in self.track.tickets)
|
||||
if all_done:
|
||||
print("Track completed successfully.")
|
||||
await self._push_state(status="done", active_tier=None)
|
||||
else:
|
||||
# If we have no executable tickets but some are not completed, we might be blocked
|
||||
# or there are simply no more tickets to run at this moment.
|
||||
incomplete = [t for t in self.track.tickets if t.status != "completed"]
|
||||
if not incomplete:
|
||||
print("Track completed successfully.")
|
||||
await self._push_state(status="done", active_tier=None)
|
||||
else:
|
||||
print(f"No more executable tickets. {len(incomplete)} tickets remain incomplete.")
|
||||
await self._push_state(status="blocked", active_tier=None)
|
||||
break
|
||||
|
||||
for ticket in executable:
|
||||
@@ -69,6 +93,9 @@ class ConductorEngine:
|
||||
continue
|
||||
|
||||
print(f"Executing ticket {ticket.id}: {ticket.description}")
|
||||
ticket.status = "running"
|
||||
await self._push_state(active_tier=f"Tier 3 (Worker): {ticket.id}")
|
||||
|
||||
# For now, we use a default model name or take it from config
|
||||
context = WorkerContext(
|
||||
ticket_id=ticket.id,
|
||||
@@ -76,6 +103,7 @@ class ConductorEngine:
|
||||
messages=[]
|
||||
)
|
||||
run_worker_lifecycle(ticket, context)
|
||||
await self._push_state(active_tier="Tier 2 (Tech Lead)")
|
||||
|
||||
def confirm_execution(payload: str) -> bool:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user