"""Executor — dispatches plan steps to tools, never raises.""" from __future__ import annotations from core.state import PlanStep, StepResult, StepStatus from runtime.tool_registry import ToolRegistry class Executor: """Executes a PlanStep by delegating to the appropriate tool handler.""" def __init__(self, registry: ToolRegistry) -> None: self._registry = registry def execute(self, step: PlanStep) -> StepResult: """ Execute a step. All exceptions are caught and returned as a FAILED StepResult — the caller never needs to handle exceptions. """ handler = self._registry.get(step.kind) if handler is None: return StepResult( step_id=step.step_id, status=StepStatus.FAILED, error=f"No handler registered for step kind '{step.kind}'", ) try: return handler(step) except Exception as exc: # noqa: BLE001 return StepResult( step_id=step.step_id, status=StepStatus.FAILED, error=f"{type(exc).__name__}: {exc}", )