"""TOML-based graph configuration loader.""" from pathlib import Path from typing import Any import tomllib from engine.pipeline.graph import Graph, NodeType from engine.pipeline.graph_adapter import graph_to_pipeline def load_graph_from_toml(toml_path: str | Path) -> Graph: """Load a graph from a TOML file. Args: toml_path: Path to the TOML file Returns: Graph instance loaded from the TOML file """ with open(toml_path, "rb") as f: data = tomllib.load(f) return graph_from_dict(data) def graph_from_dict(data: dict[str, Any]) -> Graph: """Create a graph from a dictionary (TOML-compatible structure). Args: data: Dictionary with 'nodes' and 'connections' keys Returns: Graph instance """ graph = Graph() # Parse nodes nodes_data = data.get("nodes", {}) for name, node_info in nodes_data.items(): if isinstance(node_info, str): # Simple format: "source": "headlines" graph.node(name, NodeType.SOURCE, source=node_info) elif isinstance(node_info, dict): # Full format: {"type": "camera", "mode": "scroll"} node_type = node_info.get("type", "custom") config = {k: v for k, v in node_info.items() if k != "type"} graph.node(name, node_type, **config) # Parse connections connections_data = data.get("connections", {}) if isinstance(connections_data, dict): # Format: {"list": ["source -> camera -> display"]} connections_list = connections_data.get("list", []) else: # Format: ["source -> camera -> display"] connections_list = connections_data for conn in connections_list: if isinstance(conn, str): # Parse "source -> target" format parts = conn.split("->") if len(parts) >= 2: # Connect all nodes in the chain for i in range(len(parts) - 1): source = parts[i].strip() target = parts[i + 1].strip() graph.connect(source, target) return graph def load_pipeline_from_toml( toml_path: str | Path, viewport_width: int = 80, viewport_height: int = 24 ): """Load a pipeline from a TOML file. Args: toml_path: Path to the TOML file viewport_width: Terminal width for the pipeline viewport_height: Terminal height for the pipeline Returns: Pipeline instance loaded from the TOML file """ graph = load_graph_from_toml(toml_path) return graph_to_pipeline(graph, viewport_width, viewport_height) # Example TOML structure: EXAMPLE_TOML = """ # Graph-based pipeline configuration [nodes.source] type = "source" source = "headlines" [nodes.camera] type = "camera" mode = "scroll" speed = 1.0 [nodes.noise] type = "effect" effect = "noise" intensity = 0.3 [nodes.display] type = "display" backend = "terminal" [connections] list = ["source -> camera -> noise -> display"] """