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: api:
retry_attempts: 3 retry_attempts: 3
retry_delay_seconds: 2 retry_delay_seconds: 2
# TODO Magari implementare un sistema per settare i providers market_providers: [BinanceWrapper, YFinanceWrapper, CoinBaseWrapper, CryptoCompareWrapper]
market_providers: [BinanceWrapper, YFinanceWrapper] news_providers: [GoogleNewsWrapper, DuckDuckGoWrapper, NewsApiWrapper, CryptoPanicWrapper]
news_providers: [GoogleNewsWrapper, DuckDuckGoWrapper] social_providers: [RedditWrapper, XWrapper, ChanWrapper]
social_providers: [RedditWrapper]
agents: agents:
strategy: Conservative strategy: Conservative

View File

@@ -2,30 +2,46 @@ from agno.tools import Toolkit
from app.api.wrapper_handler import WrapperHandler from app.api.wrapper_handler import WrapperHandler
from app.api.core.markets import MarketWrapper, Price, ProductInfo from app.api.core.markets import MarketWrapper, Price, ProductInfo
from app.api.markets import BinanceWrapper, CoinBaseWrapper, CryptoCompareWrapper, YFinanceWrapper from app.api.markets import BinanceWrapper, CoinBaseWrapper, CryptoCompareWrapper, YFinanceWrapper
from app.configs import AppConfig
class MarketAPIsTool(MarketWrapper, Toolkit): class MarketAPIsTool(MarketWrapper, Toolkit):
""" """
Class that aggregates multiple market API wrappers and manages them using WrapperHandler. Class that aggregates multiple market API wrappers and manages them using WrapperHandler.
This class supports retrieving product information and historical prices. 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. 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: Providers can be configured in configs.yaml under api.market_providers.
- BinanceWrapper
- YFinanceWrapper
- CoinBaseWrapper
- CryptoCompareWrapper
""" """
# Mapping of wrapper names to wrapper classes
_WRAPPER_MAP = {
'BinanceWrapper': BinanceWrapper,
'YFinanceWrapper': YFinanceWrapper,
'CoinBaseWrapper': CoinBaseWrapper,
'CryptoCompareWrapper': CryptoCompareWrapper,
}
def __init__(self): def __init__(self):
""" """
Initialize the MarketAPIsTool with multiple market API wrappers. Initialize the MarketAPIsTool with market API wrappers configured in configs.yaml.
The following wrappers are included in this order: The order of wrappers is determined by the api.market_providers list in the configuration.
- BinanceWrapper
- YFinanceWrapper
- CoinBaseWrapper
- CryptoCompareWrapper
""" """
wrappers: list[type[MarketWrapper]] = [BinanceWrapper, YFinanceWrapper, CoinBaseWrapper, CryptoCompareWrapper] config = AppConfig()
self.handler = WrapperHandler.build_wrappers(wrappers)
# 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 Toolkit.__init__( # type: ignore
self, self,

View File

@@ -2,33 +2,49 @@ from agno.tools import Toolkit
from app.api.wrapper_handler import WrapperHandler from app.api.wrapper_handler import WrapperHandler
from app.api.core.news import NewsWrapper, Article from app.api.core.news import NewsWrapper, Article
from app.api.news import NewsApiWrapper, GoogleNewsWrapper, CryptoPanicWrapper, DuckDuckGoWrapper from app.api.news import NewsApiWrapper, GoogleNewsWrapper, CryptoPanicWrapper, DuckDuckGoWrapper
from app.configs import AppConfig
class NewsAPIsTool(NewsWrapper, Toolkit): class NewsAPIsTool(NewsWrapper, Toolkit):
""" """
Aggregates multiple news API wrappers and manages them using WrapperHandler. Aggregates multiple news API wrappers and manages them using WrapperHandler.
This class supports retrieving top headlines and latest news articles by querying multiple sources: This class supports retrieving top headlines and latest news articles by querying multiple sources.
- GoogleNewsWrapper Providers can be configured in configs.yaml under api.news_providers.
- DuckDuckGoWrapper
- NewsApiWrapper
- CryptoPanicWrapper
By default, it returns results from the first successful wrapper. By default, it returns results from the first successful wrapper.
Optionally, it can be configured to collect articles from all wrappers. Optionally, it can be configured to collect articles from all wrappers.
If no wrapper succeeds, an exception is raised. 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): def __init__(self):
""" """
Initialize the NewsAPIsTool with multiple news API wrappers. Initialize the NewsAPIsTool with news API wrappers configured in configs.yaml.
The tool uses WrapperHandler to manage and invoke the different news API wrappers. The order of wrappers is determined by the api.news_providers list in the configuration.
The following wrappers are included in this order:
- GoogleNewsWrapper.
- DuckDuckGoWrapper.
- NewsApiWrapper.
- CryptoPanicWrapper.
""" """
wrappers: list[type[NewsWrapper]] = [GoogleNewsWrapper, DuckDuckGoWrapper, NewsApiWrapper, CryptoPanicWrapper] config = AppConfig()
self.handler = WrapperHandler.build_wrappers(wrappers)
# 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 Toolkit.__init__( # type: ignore
self, self,

View File

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

View File

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