"""Generic start → runner → complete/fail shell.""" from __future__ import annotations from typing import Any, Callable, Dict, Optional from ..callback_client import StateCenterClient from .errors import NodeError from .payloads import build_complete_payload, build_fail_payload Runner = Callable[[], Optional[Dict[str, Any]]] def execute_node( client: StateCenterClient, job_id: str, node_code: str, runner: Runner, *, attempt_no: int = 1, operator: str = "agent", ) -> dict[str, Any]: client.start_node(job_id, node_code, attempt_no=attempt_no, operator=operator) try: output = runner() or {} payload = build_complete_payload(job_id, node_code, attempt_no, output) return client.complete_node(job_id, node_code, payload) except NodeError as exc: return client.fail_node(job_id, node_code, build_fail_payload(attempt_no, exc))