[build-system]
requires = ["setuptools>=77.0.0"]
build-backend = "setuptools.build_meta"

[project]
name = "sglang-omni"
dynamic = ["version"]
description = "Multi-stage pipeline framework for omni models"
readme = "README.md"
license = "Apache-2.0"
license-files = ["LICENSE"]
requires-python = ">=3.10,<3.13"
dependencies = [
    # Core dependencies
    "pyzmq>=25.0.0",          # ZMQ messaging for control plane
    "msgpack>=1.0.0",         # Message serialization
    "msgspec",                # msgspec.Struct support
    "numpy>=1.24.0",          # Array operations
    "pydantic>=2.0.0",        # Data validation and serialization
    "PyYAML>=6.0",            # YAML config parsing
    "pybase64>=1.4.0",        # Fast base64 decoding for inline media payloads
    "torch==2.11.0",          # PyTorch for tensor operations
    "torchvision==0.26.0",    # torchvision for vision processor, pinned version based on torch 2.11.0
    "accelerate>=0.27.0",     # init_empty_weights for meta initialization
    "transformers==5.12.1",  # Match SGLang 0.5.16
    "safetensors>=0.4.3",     # Direct weight loading
    "pillow>=10.0.0",         # Required by AutoImageProcessor
    "huggingface-hub[hf_xet]>=0.36.0",# HF model downloads with Xet transport
    "datasets>=2.14.0",       # Arrow-based SeedTTS dataset loading
    "fastapi>=0.110.0",       # OpenAI-compatible API adapter
    "uvicorn>=0.23.0",        # ASGI server for FastAPI
    "sglang==0.5.16",
    "flashinfer_python[cu13]==0.6.14",  # SGLang 0.5.16 pin. Do NOT add flashinfer-cubin: PyPI has no 0.6.14 cubin, and any leftover cubin wheel fails MiniMax DIT import.
    "cache-dit==1.3.0",      # MiniMax Music 3 DIT (hard import, not optional)
    "addict==2.4.0",         # sglang.multimodal_gen server_args; MiniMax DIT import
    "imageio==2.36.0",       # sglang.multimodal_gen vision utils; MiniMax DIT import
    "imageio-ffmpeg==0.5.1", # Pinned with SGLang 0.5.16 diffusion extra
    "flash-attn-4>=4.0.0b18",  # Required by SGLang 0.5.16; pairs with cutlass-dsl 4.6.0
    "kernels>=0.14.1,<0.15",  # Match the SGLang 0.5.16 stack
    "nixl-cu13>=1.1.0",  # CUDA 13 relay wheel; the generic nixl/-cu12 wheel breaks on cu130
    "mooncake-transfer-engine-cuda13>=0.3.10",  # CUDA 13 relay wheel; generic mooncake-transfer-engine pulls cu12 and breaks import mooncake on cu130
    "logger",
    "httpx",
    "xxhash>=3.0.0",
    # Note: (Jiaxin Deng) the documented install line for the Qwen3-TTS model
    # package is `--no-deps qwen-tts==0.1.1`, and --no-deps is exactly what drops
    # sox, so `import qwen_tts` raises ModuleNotFoundError before a worker binds
    # a port.
    "sox>=1.4.1",
    "av>=16.1.0",
    "qwen-vl-utils==0.0.11",
    "numba==0.65.1",  # Match SGLang 0.5.16
    "librosa>=0.11.0",
    "pandas",
    "tabulate",
    "typer>=0.9.0",
    "openai==2.6.1",
    "openai-harmony==0.0.4",
    "soundfile>=0.12.0",
    "mistral_common[audio]>=1.11.0",
    # /v1/realtime — server-side VAD
    "silero-vad>=5.1",
    "onnxruntime>=1.17",
    "websockets>=12.0",       # FastAPI WebSocket library + example clients
    # Testing
    "pytest>=7.0.0",
    "pytest-asyncio>=0.21.0",
    "jiwer",
    "zhon>=2.0.2",            # note (yzxiao): shared Chinese WER normalization uses zhon.hanzi punctuation.
    "scipy>=1.10.0",
    "openai-whisper==20250625",
    # SeedTTS speaker similarity (WavLM-large SV head). The pip-installed
    # package supplies s3prl.upstream.wavlm.hubconf at runtime, so no source
    # clone is required.
    "s3prl>=0.4.18",
    # S2-Pro
    "tiktoken",
    "hydra-core",
    "omegaconf",
    "torchaudio==2.11.0",
    "torchcodec==0.11.1",     # Matches torch 2.11.x / sglang 0.5.16
    # Gradio playground
    "gradio>=4.0.0",
    # dots.tts model operators; serving/runtime stays owned by sglang-omni
    "dots.tts==0.2.1",
    # Ming-Omni
    "diffusers==0.37.0",      # Omni's own Ming-Omni pin; not an sglang core dependency
    "x-transformers",          # Ming talker rotary embeddings
    # ZONOS2 written->spoken text normalization; pulls pynini + sacremoses.
    "nemo_text_processing==1.2.0",
]

[project.optional-dependencies]
audar-tts = [
    "llama-cpp-python==0.3.34",
    "neucodec==0.0.6",
]

[project.scripts]
sgl-omni = "sglang_omni.cli:app"
sgl-omni-router = "sglang_omni_router.serve:main"

[project.entry-points."sglang.serve_backends"]
omni = "sglang_omni.cli.sglang_backend:create_backend"

[project.urls]
Documentation = "https://sgl-project.github.io/sglang-omni/"
Issues = "https://github.com/sgl-project/sglang-omni/issues"
Repository = "https://github.com/sgl-project/sglang-omni"

[tool.uv]
override-dependencies = [
    "protobuf>=6.31.1,<7.0.0",
]

[tool.pytest.ini_options]
pythonpath = ["."]
markers = [
    "benchmark: performance benchmark tests (may require GPU and long runtime)",
    "tts_stage(name): select an in-file TTS benchmark CI stage",
    "gpu: requires a CUDA device (auto-skipped without one)",
]

[tool.setuptools.packages.find]
where = ["."]
include = ["sglang_omni*"]

[tool.setuptools.dynamic]
version = {attr = "sglang_omni.__version__"}

# Non-Python data files that must ship with the wheel.
[tool.setuptools.package-data]
"sglang_omni.models.fishaudio_s2_pro" = ["fish_speech/configs/*.yaml"]
"sglang_omni.models.higgs_tts" = ["configs/*.json"]
"sglang_omni.models.zonos2" = ["moe_configs/*/*.json"]
