67 lines
2.4 KiB
Python
67 lines
2.4 KiB
Python
"""Shared base classes for the pluggable-backend provider ABCs.
|
|
|
|
Every tool-provider ABC shares the same identity + ``hermes tools`` picker surface.
|
|
Concrete ABCs subclass :class:`ProviderBase` (or :class:`CatalogProviderBase` when
|
|
the backend also exposes a model catalog and is available by default) and add only
|
|
their domain methods. Plugins keep subclassing the concrete ABC, so ``isinstance``
|
|
checks and abstract-method sets are unchanged.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import abc
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
|
|
class ProviderBase(abc.ABC):
|
|
"""Identity + picker metadata common to every provider ABC."""
|
|
|
|
@property
|
|
@abc.abstractmethod
|
|
def name(self) -> str:
|
|
"""Stable short identifier used as the provider's config-key value.
|
|
|
|
Lowercase, no spaces (hyphens allowed where they preserve an existing
|
|
user-visible name). Registries key providers by this string.
|
|
"""
|
|
|
|
@property
|
|
def display_name(self) -> str:
|
|
"""Human-readable label shown in ``hermes tools``. Defaults to ``name``."""
|
|
return self.name
|
|
|
|
def get_setup_schema(self) -> Dict[str, Any]:
|
|
"""Provider row for the ``hermes tools`` picker.
|
|
|
|
Shape: ``{"name", "badge", "tag", "env_vars": [{"key", "prompt", "url"}, ...]}``
|
|
(browser providers may add ``"post_setup"``). Override to expose API key
|
|
prompts and badges.
|
|
"""
|
|
return {"name": self.display_name, "badge": "", "tag": "", "env_vars": []}
|
|
|
|
|
|
class CatalogProviderBase(ProviderBase):
|
|
"""Provider with a model catalog; available by default, ``display_name`` is title-cased."""
|
|
|
|
@property
|
|
def display_name(self) -> str:
|
|
"""Human-readable label shown in ``hermes tools``. Defaults to ``name.title()``."""
|
|
return self.name.title()
|
|
|
|
def is_available(self) -> bool:
|
|
"""True when this provider can service calls (API key present, SDK importable).
|
|
|
|
Must NOT raise and must NOT make network calls — the picker and
|
|
``hermes setup`` call it on every paint.
|
|
"""
|
|
return True
|
|
|
|
def list_models(self) -> List[Dict[str, Any]]:
|
|
"""Model catalog entries (``{"id": ..., "display": ...}`` + provider-specific keys)."""
|
|
return []
|
|
|
|
def default_model(self) -> Optional[str]:
|
|
"""Id of the first catalog entry, or None when the catalog is empty."""
|
|
models = self.list_models()
|
|
return models[0].get("id") if models else None
|