from __future__ import annotations from dataclasses import dataclass from typing import Any @dataclass class StreamingConfig: mode: str = "off" chunk_mode: str = "newline" native_transport: bool = False block_enabled: bool = True block_coalesce_min_chars: int = 1500 block_coalesce_idle_ms: int = 1000 @classmethod def from_config(cls, config: dict[str, Any] | None) -> StreamingConfig: if not config: return cls() streaming = config.get("streaming", {}) or {} if isinstance(streaming, str): streaming = {"mode": streaming} mode = _resolve_streaming_mode(config, streaming) chunk_mode = _resolve_chunk_mode(config, streaming) native_transport = _resolve_native_transport(config, streaming) block = streaming.get("block", {}) or {} block_enabled = bool(block.get("enabled", True)) coalesce = block.get("coalesce", {}) or {} return cls( mode=mode, chunk_mode=chunk_mode, native_transport=native_transport, block_enabled=block_enabled, block_coalesce_min_chars=int(coalesce.get("min_chars", 1500)), block_coalesce_idle_ms=int(coalesce.get("idle_ms", 1000)), ) def _resolve_streaming_mode(config: dict[str, Any], streaming: dict[str, Any]) -> str: mode = streaming.get("mode", "") if mode: return mode legacy = str(config.get("streamMode", config.get("streaming", ""))).strip() if legacy in ("off", "partial", "block", "progress"): return legacy return "off" def _resolve_chunk_mode(config: dict[str, Any], streaming: dict[str, Any]) -> str: chunk = streaming.get("chunkMode", "") if chunk: return chunk legacy = str(config.get("chunkMode", "")).strip() if legacy in ("length", "newline"): return legacy return "newline" def _resolve_native_transport(config: dict[str, Any], streaming: dict[str, Any]) -> bool: native = streaming.get("nativeTransport") if native is not None: return bool(native) legacy = config.get("nativeStreaming") if legacy is not None: return bool(legacy) return False