"""Synchronize Ollama Models endpoints into Hermes' native model picker.""" from __future__ import annotations import json import logging import os from pathlib import Path from typing import Any from hermes_constants import get_hermes_home logger = logging.getLogger(__name__) LOCAL_PROVIDER_KEY = "ollama-manager-local" REMOTE_PROVIDER_KEY = "ollama-manager-remote" _OWNED_PROVIDER_KEYS = {LOCAL_PROVIDER_KEY, REMOTE_PROVIDER_KEY} def _running_in_container() -> bool: return Path("/.dockerenv").exists() or Path("/run/.containerenv").exists() def _default_endpoint() -> str: configured = os.environ.get("OLLAMA_HOST", "").strip().rstrip("/") if configured: return configured return "http://ollama:11434" if _running_in_container() else "http://localhost:11434" def _connections() -> dict[str, str]: path = get_hermes_home() / "ollama-manager" / "connections.json" try: value = json.loads(path.read_text(encoding="utf-8")) except (OSError, ValueError, TypeError): value = {} if not isinstance(value, dict): value = {} return { key: str(value.get(key) or "").strip().rstrip("/") for key in ("active_url", "local_url", "remote_url") } def _endpoint_to_api(endpoint: str) -> str: endpoint = str(endpoint or "").strip().rstrip("/") if endpoint.endswith("/v1"): return endpoint return endpoint + "/v1" def _provider_entry(name: str, endpoint: str) -> dict[str, Any]: return { "name": name, "api": _endpoint_to_api(endpoint), "transport": "chat_completions", "discover_models": True, } def sync_hermes_ollama_providers(connections: dict[str, str] | None = None) -> bool: """Upsert the plugin's local/remote providers without changing defaults.""" try: from hermes_cli.config import load_config, save_config saved = connections or _connections() local = saved.get("local_url") or saved.get("active_url") or _default_endpoint() remote = saved.get("remote_url") if remote and remote == local: remote = "" config = load_config() providers = config.get("providers") if not isinstance(providers, dict): providers = {} config["providers"] = providers for key in _OWNED_PROVIDER_KEYS: providers.pop(key, None) providers[LOCAL_PROVIDER_KEY] = _provider_entry("Ollama Models (Local)", local) if remote: providers[REMOTE_PROVIDER_KEY] = _provider_entry("Ollama Models (Remote)", remote) # The provider is selectable, not the active default. Do not touch # model.default or model.provider while installing/updating the plugin. save_config(config, strip_defaults=False) return True except Exception as exc: # provider registration must never break the dashboard logger.warning("Could not synchronize Ollama providers into Hermes config: %s", exc) return False