""" Pipeline presets - Pre-configured pipeline configurations. Provides PipelinePreset as a unified preset system. Presets can be loaded from TOML files (presets.toml) or defined in code. Loading order: 1. Built-in presets.toml in the package 2. User config ~/.config/mainline/presets.toml 3. Local ./presets.toml (overrides earlier) """ from dataclasses import dataclass, field from typing import Any from engine.pipeline.params import PipelineParams def _load_toml_presets() -> dict[str, Any]: """Load presets from TOML file.""" try: from engine.pipeline.preset_loader import load_presets return load_presets() except Exception: return {} # Pre-load TOML presets _YAML_PRESETS = _load_toml_presets() @dataclass class PipelinePreset: """Pre-configured pipeline with stages and animation. A PipelinePreset packages: - Initial params: Starting configuration - Stages: List of stage configurations to create This is the new unified preset that works with the Pipeline class. """ name: str description: str = "" source: str = "headlines" display: str = "terminal" camera: str = "scroll" effects: list[str] = field(default_factory=list) border: bool = False def to_params(self) -> PipelineParams: """Convert to PipelineParams.""" params = PipelineParams() params.source = self.source params.display = self.display params.border = self.border params.camera_mode = self.camera params.effect_order = self.effects.copy() return params @classmethod def from_yaml(cls, name: str, data: dict[str, Any]) -> "PipelinePreset": """Create a PipelinePreset from YAML data.""" return cls( name=name, description=data.get("description", ""), source=data.get("source", "headlines"), display=data.get("display", "terminal"), camera=data.get("camera", "vertical"), effects=data.get("effects", []), border=data.get("border", False), ) # Built-in presets DEMO_PRESET = PipelinePreset( name="demo", description="Demo mode with effect cycling and camera modes", source="headlines", display="pygame", camera="scroll", effects=["noise", "fade", "glitch", "firehose"], ) POETRY_PRESET = PipelinePreset( name="poetry", description="Poetry feed with subtle effects", source="poetry", display="pygame", camera="scroll", effects=["fade"], ) PIPELINE_VIZ_PRESET = PipelinePreset( name="pipeline", description="Pipeline visualization mode", source="pipeline", display="terminal", camera="trace", effects=[], ) WEBSOCKET_PRESET = PipelinePreset( name="websocket", description="WebSocket display mode", source="headlines", display="websocket", camera="scroll", effects=["noise", "fade", "glitch"], ) SIXEL_PRESET = PipelinePreset( name="sixel", description="Sixel graphics display mode", source="headlines", display="sixel", camera="scroll", effects=["noise", "fade", "glitch"], ) FIREHOSE_PRESET = PipelinePreset( name="firehose", description="High-speed firehose mode", source="headlines", display="pygame", camera="scroll", effects=["noise", "fade", "glitch", "firehose"], ) # Build presets from YAML data def _build_presets() -> dict[str, PipelinePreset]: """Build preset dictionary from all sources.""" result = {} # Add YAML presets yaml_presets = _YAML_PRESETS.get("presets", {}) for name, data in yaml_presets.items(): result[name] = PipelinePreset.from_yaml(name, data) # Add built-in presets as fallback (if not in YAML) builtins = { "demo": DEMO_PRESET, "poetry": POETRY_PRESET, "pipeline": PIPELINE_VIZ_PRESET, "websocket": WEBSOCKET_PRESET, "sixel": SIXEL_PRESET, "firehose": FIREHOSE_PRESET, } for name, preset in builtins.items(): if name not in result: result[name] = preset return result PRESETS: dict[str, PipelinePreset] = _build_presets() def get_preset(name: str) -> PipelinePreset | None: """Get a preset by name.""" return PRESETS.get(name) def list_presets() -> list[str]: """List all available preset names.""" return list(PRESETS.keys()) def create_preset_from_params( params: PipelineParams, name: str = "custom" ) -> PipelinePreset: """Create a preset from PipelineParams.""" return PipelinePreset( name=name, source=params.source, display=params.display, camera=params.camera_mode, effects=params.effect_order.copy() if hasattr(params, "effect_order") else [], )