125 lines
3.4 KiB
Python
125 lines
3.4 KiB
Python
# 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
|