from abc import ABC, abstractmethod from dataclasses import dataclass, field from typing import Any @dataclass class EffectContext: terminal_width: int terminal_height: int scroll_cam: int ticker_height: int camera_x: int = 0 mic_excess: float = 0.0 grad_offset: float = 0.0 frame_number: int = 0 has_message: bool = False items: list = field(default_factory=list) @dataclass class EffectConfig: enabled: bool = True intensity: float = 1.0 params: dict[str, Any] = field(default_factory=dict) class EffectPlugin(ABC): name: str config: EffectConfig @abstractmethod def process(self, buf: list[str], ctx: EffectContext) -> list[str]: ... @abstractmethod def configure(self, config: EffectConfig) -> None: ... def create_effect_context( terminal_width: int = 80, terminal_height: int = 24, scroll_cam: int = 0, ticker_height: int = 0, camera_x: int = 0, mic_excess: float = 0.0, grad_offset: float = 0.0, frame_number: int = 0, has_message: bool = False, items: list | None = None, ) -> EffectContext: """Factory function to create EffectContext with sensible defaults.""" return EffectContext( terminal_width=terminal_width, terminal_height=terminal_height, scroll_cam=scroll_cam, ticker_height=ticker_height, camera_x=camera_x, mic_excess=mic_excess, grad_offset=grad_offset, frame_number=frame_number, has_message=has_message, items=items or [], ) @dataclass class PipelineConfig: order: list[str] = field(default_factory=list) effects: dict[str, EffectConfig] = field(default_factory=dict)