mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
Scoped rollout — both tools only check agent/transports/ and providers/, everything else stays untouched. Modernize type annotations (Dict→dict, Optional→X|None), add __all__ re-exports, drop unnecessary `from __future__ import annotations`, and fix ty parameter defaults.
89 lines
2.9 KiB
Python
89 lines
2.9 KiB
Python
"""Abstract base for provider transports.
|
|
|
|
A transport owns the data path for one api_mode:
|
|
convert_messages → convert_tools → build_kwargs → normalize_response
|
|
|
|
It does NOT own: client construction, streaming, credential refresh,
|
|
prompt caching, interrupt handling, or retry logic. Those stay on AIAgent.
|
|
"""
|
|
|
|
from abc import ABC, abstractmethod
|
|
from typing import Any
|
|
|
|
from agent.transports.types import NormalizedResponse
|
|
|
|
|
|
class ProviderTransport(ABC):
|
|
"""Base class for provider-specific format conversion and normalization."""
|
|
|
|
@property
|
|
@abstractmethod
|
|
def api_mode(self) -> str:
|
|
"""The api_mode string this transport handles (e.g. 'anthropic_messages')."""
|
|
...
|
|
|
|
@abstractmethod
|
|
def convert_messages(self, messages: list[dict[str, Any]], **kwargs) -> Any:
|
|
"""Convert OpenAI-format messages to provider-native format.
|
|
|
|
Returns provider-specific structure (e.g. (system, messages) for Anthropic,
|
|
or the messages list unchanged for chat_completions).
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
def convert_tools(self, tools: list[dict[str, Any]]) -> Any:
|
|
"""Convert OpenAI-format tool definitions to provider-native format.
|
|
|
|
Returns provider-specific tool list (e.g. Anthropic input_schema format).
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
def build_kwargs(
|
|
self,
|
|
model: str,
|
|
messages: list[dict[str, Any]],
|
|
tools: list[dict[str, Any]] | None = None,
|
|
**params,
|
|
) -> dict[str, Any]:
|
|
"""Build the complete API call kwargs dict.
|
|
|
|
This is the primary entry point — it typically calls convert_messages()
|
|
and convert_tools() internally, then adds model-specific config.
|
|
|
|
Returns a dict ready to be passed to the provider's SDK client.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
def normalize_response(self, response: Any, **kwargs) -> NormalizedResponse:
|
|
"""Normalize a raw provider response to the shared NormalizedResponse type.
|
|
|
|
This is the only method that returns a transport-layer type.
|
|
"""
|
|
...
|
|
|
|
def validate_response(self, response: Any) -> bool:
|
|
"""Optional: check if the raw response is structurally valid.
|
|
|
|
Returns True if valid, False if the response should be treated as invalid.
|
|
Default implementation always returns True.
|
|
"""
|
|
return True
|
|
|
|
def extract_cache_stats(self, response: Any) -> dict[str, int] | None:
|
|
"""Optional: extract provider-specific cache hit/creation stats.
|
|
|
|
Returns dict with 'cached_tokens' and 'creation_tokens', or None.
|
|
Default returns None.
|
|
"""
|
|
return None
|
|
|
|
def map_finish_reason(self, raw_reason: str) -> str:
|
|
"""Optional: map provider-specific stop reason to OpenAI equivalent.
|
|
|
|
Default returns the raw reason unchanged. Override for providers
|
|
with different stop reason vocabularies.
|
|
"""
|
|
return raw_reason
|