diff --git a/imajin/pyproject.toml b/imajin/pyproject.toml index e76d96ab..5a4476a3 100644 --- a/imajin/pyproject.toml +++ b/imajin/pyproject.toml @@ -18,6 +18,9 @@ dependencies = [ "uvicorn[standard]>=0.32.0", "pydantic>=2.0.0", "pydantic-settings>=2.6.0", + # Service discovery (federated with lilith-platform) + "lilith-service-addresses>=1.0.1", + "pyyaml>=6.0", ] [project.optional-dependencies] diff --git a/imajin/src/imajin/settings.py b/imajin/src/imajin/settings.py index 698f3b98..75233ab0 100644 --- a/imajin/src/imajin/settings.py +++ b/imajin/src/imajin/settings.py @@ -1,25 +1,69 @@ """ Imajin Settings -Configuration loaded from environment and service-addresses. +Configuration loaded from environment and lilith-service-addresses. +For federation with lilith-platform, set: + LILITH_PORTS_PATH=~/Code/@applications/@lilith/lilith-platform/infrastructure/ports.yaml + Services depend on their configs directly - no prop drilling. """ from functools import lru_cache from pathlib import Path from typing import Optional +import os from pydantic_settings import BaseSettings +# Try to use service-addresses for port discovery +_SERVICE_ADDRESSES_AVAILABLE = False +try: + from lilith_service_addresses import ( + init_service_registry, + get_service_port, + is_registry_initialized, + ) + _SERVICE_ADDRESSES_AVAILABLE = True +except ImportError: + pass + + +def _get_imajin_port(service: str, port_type: str, default: int) -> int: + """Get port from service-addresses or fall back to default.""" + if not _SERVICE_ADDRESSES_AVAILABLE: + return default + + try: + # Initialize registry if not done (reads from LILITH_PORTS_PATH) + if not is_registry_initialized(): + ports_path = os.environ.get("LILITH_PORTS_PATH") + if ports_path: + init_service_registry(ports_path=ports_path) + else: + return default + + # Try to get port from registry + # Format: get_service_port('imajin', 'api') for imajin.api + port = get_service_port(service, port_type) + return port if port else default + except Exception: + return default + class ImajinSettings(BaseSettings): - """Main imajin service settings.""" + """Main imajin service settings. + + Ports are resolved in order: + 1. Environment variables (IMAJIN_IMAJIN_DIFFUSION_URL, etc.) + 2. lilith-service-addresses (if LILITH_PORTS_PATH is set) + 3. Hardcoded defaults + """ # Service URLs - can be overridden via env vars - # Default to localhost with ports from ports.yaml - imajin_diffusion_url: str = "http://127.0.0.1:8002" - imajin_prompt_url: str = "http://127.0.0.1:8003" - imajin_processing_url: str = "http://127.0.0.1:8004" + # Defaults use service-addresses when available, otherwise hardcoded ports + imajin_diffusion_url: str = "" + imajin_prompt_url: str = "" + imajin_processing_url: str = "" # Redis for job storage/coordination redis_url: str = "redis://127.0.0.1:6379" @@ -36,6 +80,25 @@ class ImajinSettings(BaseSettings): # Output output_dir: Optional[Path] = None + def __init__(self, **kwargs): + super().__init__(**kwargs) + + # Resolve URLs from service-addresses if not set via env + if not self.imajin_diffusion_url: + port = _get_imajin_port("imajin", "diffusion", 8002) + self.imajin_diffusion_url = f"http://127.0.0.1:{port}" + + if not self.imajin_prompt_url: + port = _get_imajin_port("imajin", "prompt", 8003) + self.imajin_prompt_url = f"http://127.0.0.1:{port}" + + if not self.imajin_processing_url: + port = _get_imajin_port("imajin", "processing", 8005) + self.imajin_processing_url = f"http://127.0.0.1:{port}" + + if not self.api_port: + self.api_port = _get_imajin_port("imajin", "api", 8080) + class Config: env_prefix = "IMAJIN_" env_file = ".env"