101 lines
2.5 KiB
Python
101 lines
2.5 KiB
Python
"""
|
|
Debugger API — pause / resume / step an in-flight pipeline.
|
|
|
|
The engine is set by main.py on startup via `set_engine(...)`. If no
|
|
engine is registered (e.g. when running the mock server), endpoints
|
|
return a structured error rather than crashing.
|
|
"""
|
|
|
|
from fastapi import APIRouter
|
|
from typing import Optional, Any
|
|
|
|
router = APIRouter(prefix="/debugger", tags=["debugger"])
|
|
|
|
# Single in-memory engine reference (set by main.py)
|
|
_ENGINE: Optional[Any] = None
|
|
_DEBUG_STATE: dict = {
|
|
"paused": False,
|
|
"current_step": 0,
|
|
"history": [],
|
|
}
|
|
|
|
|
|
def set_engine(engine):
|
|
global _ENGINE
|
|
_ENGINE = engine
|
|
|
|
|
|
def get_engine():
|
|
return _ENGINE
|
|
|
|
|
|
# -----------------------------
|
|
# RESUME
|
|
# -----------------------------
|
|
@router.post("/resume")
|
|
def resume():
|
|
_DEBUG_STATE["paused"] = False
|
|
if _ENGINE and hasattr(_ENGINE, "resume"):
|
|
_ENGINE.resume()
|
|
return {"state": "running"}
|
|
|
|
|
|
# -----------------------------
|
|
# PAUSE
|
|
# -----------------------------
|
|
@router.post("/pause")
|
|
def pause():
|
|
_DEBUG_STATE["paused"] = True
|
|
if _ENGINE and hasattr(_ENGINE, "pause"):
|
|
_ENGINE.pause()
|
|
return {"state": "paused"}
|
|
|
|
|
|
# -----------------------------
|
|
# STEP
|
|
# -----------------------------
|
|
@router.post("/step")
|
|
def step():
|
|
if _ENGINE and hasattr(_ENGINE, "step"):
|
|
_ENGINE.step()
|
|
_DEBUG_STATE["current_step"] += 1
|
|
return {"state": "stepped", "step": _DEBUG_STATE["current_step"]}
|
|
|
|
|
|
# -----------------------------
|
|
# STEP BACK (replay-only)
|
|
# -----------------------------
|
|
@router.post("/step-back")
|
|
def step_back():
|
|
if _DEBUG_STATE["current_step"] > 0:
|
|
_DEBUG_STATE["current_step"] -= 1
|
|
return {"state": "stepped_back", "step": _DEBUG_STATE["current_step"]}
|
|
|
|
|
|
# -----------------------------
|
|
# STATE
|
|
# -----------------------------
|
|
@router.get("/state")
|
|
def state():
|
|
eng = _ENGINE
|
|
active = eng and hasattr(eng, "is_active") and eng.is_active()
|
|
return {
|
|
"paused": _DEBUG_STATE["paused"],
|
|
"current_step": _DEBUG_STATE["current_step"],
|
|
"engine_attached": eng is not None,
|
|
"engine_active": active,
|
|
}
|
|
|
|
|
|
# -----------------------------
|
|
# Legacy wrapper for api.py facade
|
|
# -----------------------------
|
|
def debugger_endpoint(session_id, registry=None, bus=None):
|
|
"""Legacy — return current debugger state for a session."""
|
|
return {
|
|
"session_id": session_id,
|
|
"paused": _DEBUG_STATE["paused"],
|
|
"current_step": _DEBUG_STATE["current_step"],
|
|
"engine_attached": _ENGINE is not None,
|
|
}
|