Implement configurable API providers from configs.yaml

Co-authored-by: Berack96 <31776951+Berack96@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-10-22 14:08:37 +00:00
parent 02574ca17a
commit 6e01f1caea
5 changed files with 94 additions and 40 deletions

View File

@@ -32,10 +32,9 @@ models:
api:
retry_attempts: 3
retry_delay_seconds: 2
# TODO Magari implementare un sistema per settare i providers
market_providers: [BinanceWrapper, YFinanceWrapper]
news_providers: [GoogleNewsWrapper, DuckDuckGoWrapper]
social_providers: [RedditWrapper]
market_providers: [BinanceWrapper, YFinanceWrapper, CoinBaseWrapper, CryptoCompareWrapper]
news_providers: [GoogleNewsWrapper, DuckDuckGoWrapper, NewsApiWrapper, CryptoPanicWrapper]
social_providers: [RedditWrapper, XWrapper, ChanWrapper]
agents:
strategy: Conservative

View File

@@ -2,30 +2,46 @@ from agno.tools import Toolkit
from app.api.wrapper_handler import WrapperHandler
from app.api.core.markets import MarketWrapper, Price, ProductInfo
from app.api.markets import BinanceWrapper, CoinBaseWrapper, CryptoCompareWrapper, YFinanceWrapper
from app.configs import AppConfig
class MarketAPIsTool(MarketWrapper, Toolkit):
"""
Class that aggregates multiple market API wrappers and manages them using WrapperHandler.
This class supports retrieving product information and historical prices.
This class can also aggregate data from multiple sources to provide a more comprehensive view of the market.
The following wrappers are included in this order:
- BinanceWrapper
- YFinanceWrapper
- CoinBaseWrapper
- CryptoCompareWrapper
Providers can be configured in configs.yaml under api.market_providers.
"""
# Mapping of wrapper names to wrapper classes
_WRAPPER_MAP = {
'BinanceWrapper': BinanceWrapper,
'YFinanceWrapper': YFinanceWrapper,
'CoinBaseWrapper': CoinBaseWrapper,
'CryptoCompareWrapper': CryptoCompareWrapper,
}
def __init__(self):
"""
Initialize the MarketAPIsTool with multiple market API wrappers.
The following wrappers are included in this order:
- BinanceWrapper
- YFinanceWrapper
- CoinBaseWrapper
- CryptoCompareWrapper
Initialize the MarketAPIsTool with market API wrappers configured in configs.yaml.
The order of wrappers is determined by the api.market_providers list in the configuration.
"""
wrappers: list[type[MarketWrapper]] = [BinanceWrapper, YFinanceWrapper, CoinBaseWrapper, CryptoCompareWrapper]
self.handler = WrapperHandler.build_wrappers(wrappers)
config = AppConfig()
# Get wrapper classes based on configuration
wrappers: list[type[MarketWrapper]] = []
for provider_name in config.api.market_providers:
if provider_name in self._WRAPPER_MAP:
wrappers.append(self._WRAPPER_MAP[provider_name])
# Fallback to all wrappers if none configured
if not wrappers:
wrappers = [BinanceWrapper, YFinanceWrapper, CoinBaseWrapper, CryptoCompareWrapper]
self.handler = WrapperHandler.build_wrappers(
wrappers,
try_per_wrapper=config.api.retry_attempts,
retry_delay=config.api.retry_delay_seconds
)
Toolkit.__init__( # type: ignore
self,

View File

@@ -2,33 +2,49 @@ from agno.tools import Toolkit
from app.api.wrapper_handler import WrapperHandler
from app.api.core.news import NewsWrapper, Article
from app.api.news import NewsApiWrapper, GoogleNewsWrapper, CryptoPanicWrapper, DuckDuckGoWrapper
from app.configs import AppConfig
class NewsAPIsTool(NewsWrapper, Toolkit):
"""
Aggregates multiple news API wrappers and manages them using WrapperHandler.
This class supports retrieving top headlines and latest news articles by querying multiple sources:
- GoogleNewsWrapper
- DuckDuckGoWrapper
- NewsApiWrapper
- CryptoPanicWrapper
This class supports retrieving top headlines and latest news articles by querying multiple sources.
Providers can be configured in configs.yaml under api.news_providers.
By default, it returns results from the first successful wrapper.
Optionally, it can be configured to collect articles from all wrappers.
If no wrapper succeeds, an exception is raised.
"""
# Mapping of wrapper names to wrapper classes
_WRAPPER_MAP = {
'GoogleNewsWrapper': GoogleNewsWrapper,
'DuckDuckGoWrapper': DuckDuckGoWrapper,
'NewsApiWrapper': NewsApiWrapper,
'CryptoPanicWrapper': CryptoPanicWrapper,
}
def __init__(self):
"""
Initialize the NewsAPIsTool with multiple news API wrappers.
The tool uses WrapperHandler to manage and invoke the different news API wrappers.
The following wrappers are included in this order:
- GoogleNewsWrapper.
- DuckDuckGoWrapper.
- NewsApiWrapper.
- CryptoPanicWrapper.
Initialize the NewsAPIsTool with news API wrappers configured in configs.yaml.
The order of wrappers is determined by the api.news_providers list in the configuration.
"""
wrappers: list[type[NewsWrapper]] = [GoogleNewsWrapper, DuckDuckGoWrapper, NewsApiWrapper, CryptoPanicWrapper]
self.handler = WrapperHandler.build_wrappers(wrappers)
config = AppConfig()
# Get wrapper classes based on configuration
wrappers: list[type[NewsWrapper]] = []
for provider_name in config.api.news_providers:
if provider_name in self._WRAPPER_MAP:
wrappers.append(self._WRAPPER_MAP[provider_name])
# Fallback to all wrappers if none configured
if not wrappers:
wrappers = [GoogleNewsWrapper, DuckDuckGoWrapper, NewsApiWrapper, CryptoPanicWrapper]
self.handler = WrapperHandler.build_wrappers(
wrappers,
try_per_wrapper=config.api.retry_attempts,
retry_delay=config.api.retry_delay_seconds
)
Toolkit.__init__( # type: ignore
self,

View File

@@ -2,29 +2,49 @@ from agno.tools import Toolkit
from app.api.wrapper_handler import WrapperHandler
from app.api.core.social import SocialPost, SocialWrapper
from app.api.social import *
from app.configs import AppConfig
class SocialAPIsTool(SocialWrapper, Toolkit):
"""
Aggregates multiple social media API wrappers and manages them using WrapperHandler.
This class supports retrieving top crypto-related posts by querying multiple sources:
- RedditWrapper
This class supports retrieving top crypto-related posts by querying multiple sources.
Providers can be configured in configs.yaml under api.social_providers.
By default, it returns results from the first successful wrapper.
Optionally, it can be configured to collect posts from all wrappers.
If no wrapper succeeds, an exception is raised.
"""
# Mapping of wrapper names to wrapper classes
_WRAPPER_MAP = {
'RedditWrapper': RedditWrapper,
'XWrapper': XWrapper,
'ChanWrapper': ChanWrapper,
}
def __init__(self):
"""
Initialize the SocialAPIsTool with multiple social media API wrappers.
The tool uses WrapperHandler to manage and invoke the different social media API wrappers.
The following wrappers are included in this order:
- RedditWrapper.
Initialize the SocialAPIsTool with social media API wrappers configured in configs.yaml.
The order of wrappers is determined by the api.social_providers list in the configuration.
"""
config = AppConfig()
wrappers: list[type[SocialWrapper]] = [RedditWrapper, XWrapper, ChanWrapper]
self.handler = WrapperHandler.build_wrappers(wrappers)
# Get wrapper classes based on configuration
wrappers: list[type[SocialWrapper]] = []
for provider_name in config.api.social_providers:
if provider_name in self._WRAPPER_MAP:
wrappers.append(self._WRAPPER_MAP[provider_name])
# Fallback to all wrappers if none configured
if not wrappers:
wrappers = [RedditWrapper, XWrapper, ChanWrapper]
self.handler = WrapperHandler.build_wrappers(
wrappers,
try_per_wrapper=config.api.retry_attempts,
retry_delay=config.api.retry_delay_seconds
)
Toolkit.__init__( # type: ignore
self,

View File

@@ -57,6 +57,9 @@ class AppModel(BaseModel):
class APIConfig(BaseModel):
retry_attempts: int = 3
retry_delay_seconds: int = 2
market_providers: list[str] = []
news_providers: list[str] = []
social_providers: list[str] = []
class Strategy(BaseModel):
name: str = "Conservative"