"""Message types flowing between nodes.""" from dataclasses import dataclass, field, asdict @dataclass class Envelope: """What flows between nodes.""" text: str user_id: str = "anon" session_id: str = "" timestamp: str = "" @dataclass class InputAnalysis: """Structured classification from Input node.""" who: str = "unknown" language: str = "en" intent: str = "request" # question | request | social | action | feedback topic: str = "" tone: str = "casual" # casual | frustrated | playful | urgent complexity: str = "simple" # trivial | simple | complex context: str = "" @dataclass class Command: """Input node's structured perception of what was heard.""" analysis: InputAnalysis source_text: str metadata: dict = field(default_factory=dict) @property def instruction(self) -> str: """Backward-compatible summary string for logging/thinker.""" a = self.analysis return f"{a.who} ({a.intent}, {a.tone}): {a.topic}" @dataclass class DirectorPlan: """Director v2's output — tells Thinker exactly what to execute.""" goal: str = "" steps: list = field(default_factory=list) # ["query_db('SHOW TABLES')", ...] present_as: str = "summary" # table | summary | machine tool_sequence: list = field(default_factory=list) # [{"tool": "query_db", "args": {...}}, ...] reasoning: str = "" # Director's internal reasoning (for audit) response_hint: str = "" # How to phrase the response if no tools needed @property def has_tools(self) -> bool: return bool(self.tool_sequence) @property def is_direct_response(self) -> bool: return not self.tool_sequence and bool(self.response_hint) @dataclass class InterpretedResult: """Interpreter's factual summary of tool output.""" summary: str # Factual text summary row_count: int = 0 # Number of data rows (for DB) key_facts: list = field(default_factory=list) # ["693 customers", "avg 5.2 devices"] confidence: str = "high" # high | medium | low @dataclass class PARouting: """PA's routing decision — which expert handles this, what's the job.""" expert: str = "none" # "eras" | "plankiste" | "none" job: str = "" # Self-contained task for the expert thinking_message: str = "" # Shown to user while expert works response_hint: str = "" # If expert="none", PA answers directly language: str = "de" # Response language @dataclass class Artifact: """A typed workspace item. The unit of workspace content.""" id: str # unique ID type: str # entity_detail | data_table | document_page | action_bar | status data: dict = field(default_factory=dict) # type-specific payload actions: list = field(default_factory=list) # [{label, action, payload?}] meta: dict = field(default_factory=dict) # {entity?, related?, source_query?} def to_dict(self) -> dict: return asdict(self) @dataclass class ThoughtResult: """Thinker node's output — either a direct answer or tool results.""" response: str tool_used: str = "" tool_output: str = "" actions: list = field(default_factory=list) # [{label, action, payload?}] state_updates: dict = field(default_factory=dict) # {key: value} from set_state display_items: list = field(default_factory=list) # [{type, label, value?, style?}] from emit_display machine_ops: list = field(default_factory=list) # [{op, id, ...}] from machine tools errors: list = field(default_factory=list) # [{query, error, describe?}] from failed retries artifacts: list = field(default_factory=list) # [Artifact] from emit_artifact