# Hybrid Preset-Graph Configuration The hybrid configuration format combines the simplicity of presets with the flexibility of graphs, providing a concise way to define pipelines. ## Overview The hybrid format uses **70% less space** than the verbose node-based DSL while providing the same functionality. ### Comparison **Verbose Node DSL (39 lines):** ```toml [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"] ``` **Hybrid Config (20 lines):** ```toml [pipeline] source = "headlines" camera = { mode = "scroll", speed = 1.0 } effects = [ { name = "noise", intensity = 0.3 } ] display = { backend = "terminal" } ``` ## Syntax ### Basic Structure ```toml [pipeline] source = "headlines" camera = { mode = "scroll", speed = 1.0 } effects = [ { name = "noise", intensity = 0.3 }, { name = "fade", intensity = 0.5 } ] display = { backend = "terminal", positioning = "mixed" } ``` ### Configuration Options #### Source ```toml source = "headlines" # Built-in source: headlines, poetry, empty, etc. ``` #### Camera ```toml # Inline object notation camera = { mode = "scroll", speed = 1.0 } # Or shorthand (uses defaults) camera = "scroll" ``` Available modes: `scroll`, `feed`, `horizontal`, `omni`, `floating`, `bounce`, `radial` #### Effects ```toml # Array of effect configurations effects = [ { name = "noise", intensity = 0.3 }, { name = "fade", intensity = 0.5, enabled = true } ] # Or shorthand (uses defaults) effects = ["noise", "fade"] ``` Available effects: `noise`, `fade`, `glitch`, `firehose`, `tint`, `hud`, etc. #### Display ```toml # Inline object notation display = { backend = "terminal", positioning = "mixed" } # Or shorthand display = "terminal" ``` Available backends: `terminal`, `null`, `websocket`, `pygame` ### Viewport Settings ```toml [pipeline] viewport_width = 80 viewport_height = 24 ``` ## Usage Examples ### Minimal Configuration ```toml [pipeline] source = "headlines" display = "terminal" ``` ### With Camera and Effects ```toml [pipeline] source = "headlines" camera = { mode = "scroll", speed = 1.0 } effects = [ { name = "noise", intensity = 0.3 }, { name = "fade", intensity = 0.5 } ] display = { backend = "terminal", positioning = "mixed" } ``` ### Full Configuration ```toml [pipeline] source = "poetry" camera = { mode = "scroll", speed = 1.5 } effects = [ { name = "noise", intensity = 0.2 }, { name = "fade", intensity = 0.4 }, { name = "glitch", intensity = 0.3 }, { name = "firehose", intensity = 0.5 } ] display = { backend = "terminal", positioning = "mixed" } viewport_width = 100 viewport_height = 30 ``` ## Python API ### Loading from TOML File ```python from engine.pipeline.hybrid_config import load_hybrid_config config = load_hybrid_config("examples/hybrid_config.toml") pipeline = config.to_pipeline() ``` ### Creating Config Programmatically ```python from engine.pipeline.hybrid_config import ( PipelineConfig, CameraConfig, EffectConfig, DisplayConfig, ) config = PipelineConfig( source="headlines", camera=CameraConfig(mode="scroll", speed=1.0), effects=[ EffectConfig(name="noise", intensity=0.3), EffectConfig(name="fade", intensity=0.5), ], display=DisplayConfig(backend="terminal", positioning="mixed"), ) pipeline = config.to_pipeline(viewport_width=80, viewport_height=24) ``` ### Converting to Graph ```python from engine.pipeline.hybrid_config import PipelineConfig config = PipelineConfig(source="headlines", display={"backend": "terminal"}) graph = config.to_graph() # Returns Graph object for further manipulation ``` ## How It Works The hybrid config system: 1. **Parses TOML** into a `PipelineConfig` dataclass 2. **Converts to Graph** internally using automatic linear connections 3. **Reuses existing adapter** to convert graph to pipeline stages 4. **Maintains backward compatibility** with verbose node DSL ### Automatic Connection Logic The system automatically creates linear connections: ``` source -> camera -> effects[0] -> effects[1] -> ... -> display ``` This covers 90% of use cases. For complex DAGs, use the verbose node DSL. ## Migration Guide ### From Presets The hybrid format is very similar to presets: **Preset:** ```toml [presets.custom] source = "headlines" effects = ["noise", "fade"] display = "terminal" ``` **Hybrid:** ```toml [pipeline] source = "headlines" effects = ["noise", "fade"] display = "terminal" ``` The main difference is using `[pipeline]` instead of `[presets.custom]`. ### From Verbose Node DSL **Old (39 lines):** ```toml [nodes.source] type = "source" source = "headlines" [nodes.camera] type = "camera" mode = "scroll" [nodes.noise] type = "effect" effect = "noise" intensity = 0.3 [nodes.display] type = "display" backend = "terminal" [connections] list = ["source -> camera -> noise -> display"] ``` **New (14 lines):** ```toml [pipeline] source = "headlines" camera = { mode = "scroll" } effects = [{ name = "noise", intensity = 0.3 }] display = { backend = "terminal" } ``` ## When to Use Each Format | Format | Use When | Lines (example) | |--------|----------|-----------------| | **Preset** | Simple configurations, no effect intensity tuning | 10 | | **Hybrid** | Most common use cases, need intensity tuning | 20 | | **Verbose Node DSL** | Complex DAGs, branching, custom connections | 39 | | **Python API** | Dynamic configuration, programmatic generation | N/A | ## Examples See `examples/hybrid_config.toml` for a complete working example. Run the demo: ```bash python examples/hybrid_visualization.py ```