"""Readable runtime values shared by Workflow orchestration modules.""" from __future__ import annotations from dataclasses import dataclass from enum import StrEnum from typing import Any class WorkflowStatus(StrEnum): """The small set of states useful to operators and future debug tooling.""" STARTING = "starting" WAITING_USER = "waiting_user" ROUTING = "routing" RUNNING_AGENT = "running_agent" RUNNING_ACTION = "running_action" HANDOFF = "handoff" ENDED = "ended" class RouteStatus(StrEnum): """A routing error is deliberately different from a valid no-match.""" MATCHED = "matched" NO_MATCH = "no_match" ERROR = "error" @dataclass(frozen=True) class UserTurn: """One committed user turn that may cross automatic Workflow nodes.""" id: int text: str @dataclass class WorkflowRuntimeState: """Mutable per-call state; graph definitions remain immutable.""" current_node_id: str status: WorkflowStatus = WorkflowStatus.STARTING pending_user_turn: UserTurn | None = None transition_id: int = 0 automatic_hops: int = 0 ended: bool = False _next_turn_id: int = 1 def begin_user_turn(self, text: str) -> UserTurn: turn = UserTurn(id=self._next_turn_id, text=text) self._next_turn_id += 1 self.pending_user_turn = turn self.automatic_hops = 0 return turn def enter(self, node_id: str, status: WorkflowStatus) -> None: self.current_node_id = node_id self.status = status def begin_transition(self) -> int: self.transition_id += 1 return self.transition_id def consume_user_turn(self) -> UserTurn | None: turn = self.pending_user_turn self.pending_user_turn = None return turn def finish(self) -> None: self.ended = True self.status = WorkflowStatus.ENDED self.pending_user_turn = None @dataclass(frozen=True) class LLMRouteResult: """Control-plane result returned by the small routing LLM.""" status: RouteStatus function_name: str | None = None error: str | None = None @dataclass(frozen=True) class EdgeEvaluation: """Final graph-level decision after expression, LLM and default handling.""" status: RouteStatus edge: dict[str, Any] | None = None error: str | None = None