system/core/registry.py
#!/usr/bin/env python3
"""
registry.py - Доступ к Platform Registry

ИСПОЛЬЗОВАНИЕ:
    from system.core.registry import get_path, get_service, get_import

    # Получить путь
    workspace = get_path('workspace')
    library = get_path('library')

    # Получить настройки сервиса
    docs_url = get_service('docs', 'url')

    # Получить путь для импорта
    ozon_path = get_import('ozon')  # → library.connectors.api.ozon
"""
import os
import yaml
from pathlib import Path
from typing import Any, Optional

# Путь к реестру
REGISTRY_PATH = Path(__file__).parent.parent / "config" / "REGISTRY.yaml"

# Кэш реестра
_registry_cache: Optional[dict] = None


def load_registry() -> dict:
    """Загрузить реестр (с кэшированием)"""
    global _registry_cache

    if _registry_cache is not None:
        return _registry_cache

    if not REGISTRY_PATH.exists():
        raise FileNotFoundError(f"Registry not found: {REGISTRY_PATH}")

    with open(REGISTRY_PATH, 'r', encoding='utf-8') as f:
        _registry_cache = yaml.safe_load(f)

    return _registry_cache


def expand_vars(value: str) -> str:
    """Раскрыть переменные в строке ($WORKSPACE → /opt/claude-workspace)"""
    if not isinstance(value, str):
        return value

    # Замена переменных окружения
    if '$' in value:
        for var in ['WORKSPACE', 'DATASPACE', 'BACKUPSPACE']:
            env_value = os.getenv(var)
            if env_value:
                value = value.replace(f'${var}', env_value)

    return value


def get_env(name: str) -> str:
    """Получить переменную окружения из реестра"""
    registry = load_registry()
    env = registry.get('environment', {})
    value = env.get(name)

    if value is None:
        raise KeyError(f"Environment variable not in registry: {name}")

    return expand_vars(value)


def get_path(name: str) -> str:
    """Получить путь из реестра"""
    registry = load_registry()
    directories = registry.get('directories', {})
    path = directories.get(name)

    if path is None:
        raise KeyError(f"Directory not in registry: {name}")

    return expand_vars(path)


def get_service(name: str, key: Optional[str] = None) -> Any:
    """Получить настройки сервиса"""
    registry = load_registry()
    services = registry.get('services', {})
    service = services.get(name)

    if service is None:
        raise KeyError(f"Service not in registry: {name}")

    if key is None:
        return service

    value = service.get(key)
    if value is None:
        raise KeyError(f"Service {name} has no key: {key}")

    return expand_vars(value)


def get_import(name: str) -> str:
    """Получить путь для импорта из library"""
    registry = load_registry()
    library = registry.get('library', {})

    # Поиск в connectors
    connectors = library.get('connectors', {})
    if name in connectors:
        return connectors[name]['path']

    # Поиск в functions
    functions = library.get('functions', {})
    if name in functions:
        return functions[name]['path']

    # Поиск в internal
    internal = library.get('internal', {})
    if name in internal:
        return internal[name]['path']

    # Проверить псевдонимы
    aliases = registry.get('aliases', {})
    if name in aliases:
        return get_import(aliases[name])

    raise KeyError(f"Import not in registry: {name}")


def get_project(name: str, key: Optional[str] = None) -> Any:
    """Получить информацию о проекте"""
    registry = load_registry()
    projects = registry.get('projects', {})
    project = projects.get(name)

    if project is None:
        raise KeyError(f"Project not in registry: {name}")

    if key is None:
        return project

    value = project.get(key)
    if value is None:
        raise KeyError(f"Project {name} has no key: {key}")

    return expand_vars(value)


def resolve_alias(name: str) -> str:
    """Разрешить псевдоним"""
    registry = load_registry()
    aliases = registry.get('aliases', {})
    return aliases.get(name, name)


def list_imports() -> dict:
    """Список всех доступных импортов"""
    registry = load_registry()
    library = registry.get('library', {})

    result = {}

    # Connectors
    for name, info in library.get('connectors', {}).items():
        result[name] = {
            'path': info['path'],
            'type': 'connector',
            'description': info.get('description', ''),
        }

    # Functions
    for name, info in library.get('functions', {}).items():
        result[name] = {
            'path': info['path'],
            'type': 'function',
            'description': info.get('description', ''),
        }

    # Internal
    for name, info in library.get('internal', {}).items():
        result[name] = {
            'path': info['path'],
            'type': 'internal',
            'description': info.get('description', ''),
        }

    return result


# Для удобства
def workspace() -> str:
    """Путь к workspace"""
    return get_env('WORKSPACE')

def dataspace() -> str:
    """Путь к dataspace"""
    return get_env('DATASPACE')


if __name__ == '__main__':
    # Демонстрация
    print("=== Platform Registry ===\n")

    print("Переменные окружения:")
    print(f"  WORKSPACE: {get_env('WORKSPACE')}")
    print(f"  DATASPACE: {get_env('DATASPACE')}")

    print("\nПути:")
    print(f"  library: {get_path('library')}")
    print(f"  projects: {get_path('projects')}")

    print("\nСервисы:")
    print(f"  docs: {get_service('docs', 'url')}")
    print(f"  file_share: {get_service('file_share', 'url')}")

    print("\nИмпорты:")
    print(f"  ozon: {get_import('ozon')}")
    print(f"  onec: {get_import('onec')}")
    print(f"  1c (alias): {get_import('1c')}")

    print("\nВсе доступные импорты:")
    for name, info in list_imports().items():
        print(f"  {name:20} ({info['type']:10}) → {info['path']}")