# debugger/interactive_engine.py import asyncio class InteractiveDebuggerEngine: def __init__(self, nodes, graph, scheduler, timeline, ws): self.nodes = nodes self.graph = graph self.scheduler = scheduler self.timeline = timeline self.ws = ws self.paused = True self.step_mode = True self.current_index = 0 self.actions = [] # ----------------------------- # LOAD EXECUTION PLAN # ----------------------------- def load_plan(self, actions): self.actions = actions self.current_index = 0 # ----------------------------- # CONTROL # ----------------------------- def pause(self): self.paused = True def resume(self): self.paused = False def step(self): self.paused = False # ----------------------------- # MAIN EXECUTION LOOP # ----------------------------- async def run(self): while self.current_index < len(self.actions): action = self.actions[self.current_index] # ----------------------------- # SCHEDULER PREVIEW (NO EXECUTION YET) # ----------------------------- decision = self.scheduler.choose_best_node( self.nodes, action ) preview_event = { "type": "debugger_preview", "data": { "action": action["name"], "selected_node": decision["best_node"]["name"], "alternatives": decision["explanation"]["top_candidates"], "state": "awaiting_step" } } await self.ws.broadcast(preview_event) self.timeline.record(preview_event) # ----------------------------- # WAIT FOR USER STEP # ----------------------------- while self.paused: await asyncio.sleep(0.05) # auto-pause again after step self.paused = True # ----------------------------- # EXECUTE ACTION # ----------------------------- node = decision["best_node"] exec_event = { "type": "node", "data": { "action": action["name"], "node": node["name"], "state": "running", "mode": "debug_step" } } await self.ws.broadcast(exec_event) self.timeline.record(exec_event) # simulate execution hook (replace with real executor) rc = await self.execute(action, node) final_state = "done" if rc == 0 else "failed" final_event = { "type": "node", "data": { "action": action["name"], "node": node["name"], "state": final_state, "mode": "debug_step" } } await self.ws.broadcast(final_event) self.timeline.record(final_event) self.current_index += 1 # ----------------------------- # EXECUTION HOOK # ----------------------------- async def execute(self, action, node): """ Replace with distcc / lxc / libvirt execution layer """ await asyncio.sleep(0.2) return 0