Download splitbit_llm/connectors/services.py from hermescures1/splitbit-llm: direct link, hf CLI and curl.
- Browser
- Download file 6.37 kB
-
https://huggingface.co/hermescures1/splitbit-llm/resolve/main/splitbit_llm/connectors/services.py
- Command line
-
hf download hf://hermescures1/splitbit-llm/splitbit_llm/connectors/services.py
-
curl -L -o services.py https://huggingface.co/hermescures1/splitbit-llm/resolve/main/splitbit_llm/connectors/services.py
6.37 kB
| """Service connectors — pre-built connectors for common services. | |
| Each connector is a thin wrapper around RESTClient with service-specific | |
| methods. All require explicit configuration — no hardcoded keys. | |
| Services: | |
| - HTTPFetcher: generic web page / API fetcher | |
| - WebSocketClient: basic WebSocket support (via stdlib) | |
| - EmailConnector: send/receive via SMTP/IMAP (stdlib) | |
| - DiscordWebhook: send messages via Discord webhook | |
| - SlackWebhook: send messages via Slack webhook | |
| - GitHubAPI: interact with GitHub API | |
| - CustomAPI: user-defined API connector | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import logging | |
| from typing import Any | |
| from .api_client import RESTClient, APIConfig, APIResponse | |
| logger = logging.getLogger(__name__) | |
| class HTTPFetcher: | |
| """Generic HTTP fetcher — fetch web pages and APIs.""" | |
| def __init__(self, timeout_s: float = 15.0) -> None: | |
| self.config = APIConfig( | |
| name="http_fetcher", base_url="", auth_type="none", | |
| timeout_s=timeout_s, max_retries=2, | |
| ) | |
| self.client = RESTClient(self.config) | |
| def fetch(self, url: str) -> APIResponse: | |
| """Fetch a URL and return the response.""" | |
| # Override base_url for this request | |
| self.config.base_url = "" | |
| # Use the full URL directly | |
| import urllib.request | |
| try: | |
| req = urllib.request.Request(url, headers={"User-Agent": "SplitBit-LLM/0.1"}) | |
| with urllib.request.urlopen(req, timeout=self.config.timeout_s) as resp: | |
| raw = resp.read().decode() | |
| return APIResponse(success=True, status_code=resp.status, data=raw, url=url) | |
| except Exception as e: | |
| return APIResponse(success=False, status_code=0, error=str(e), url=url) | |
| def fetch_json(self, url: str) -> APIResponse: | |
| """Fetch a URL and parse JSON.""" | |
| resp = self.fetch(url) | |
| if resp.success and isinstance(resp.data, str): | |
| try: | |
| resp.data = json.loads(resp.data) | |
| except json.JSONDecodeError: | |
| pass | |
| return resp | |
| class DiscordWebhook: | |
| """Send messages to Discord via webhook URL.""" | |
| def __init__(self, webhook_url: str) -> None: | |
| self.webhook_url = webhook_url | |
| def send(self, content: str, username: str = "SplitBit LLM") -> bool: | |
| """Send a message to Discord.""" | |
| import urllib.request | |
| payload = json.dumps({"content": content, "username": username}).encode() | |
| try: | |
| req = urllib.request.Request( | |
| self.webhook_url, data=payload, method="POST", | |
| headers={"Content-Type": "application/json"} | |
| ) | |
| with urllib.request.urlopen(req, timeout=10) as resp: | |
| return resp.status < 300 | |
| except Exception as e: | |
| logger.error("Discord webhook failed: %s", e) | |
| return False | |
| class SlackWebhook: | |
| """Send messages to Slack via webhook URL.""" | |
| def __init__(self, webhook_url: str) -> None: | |
| self.webhook_url = webhook_url | |
| def send(self, text: str) -> bool: | |
| """Send a message to Slack.""" | |
| import urllib.request | |
| payload = json.dumps({"text": text}).encode() | |
| try: | |
| req = urllib.request.Request( | |
| self.webhook_url, data=payload, method="POST", | |
| headers={"Content-Type": "application/json"} | |
| ) | |
| with urllib.request.urlopen(req, timeout=10) as resp: | |
| return resp.status < 300 | |
| except Exception as e: | |
| logger.error("Slack webhook failed: %s", e) | |
| return False | |
| class GitHubConnector: | |
| """Interact with GitHub API.""" | |
| def __init__(self, token: str = "") -> None: | |
| self.config = APIConfig( | |
| name="github", base_url="https://api.github.com", | |
| api_key=token, auth_type="bearer" if token else "none", | |
| timeout_s=15.0, | |
| ) | |
| self.client = RESTClient(self.config) | |
| def get_repo(self, owner: str, repo: str) -> APIResponse: | |
| return self.client.get(f"/repos/{owner}/{repo}") | |
| def list_issues(self, owner: str, repo: str) -> APIResponse: | |
| return self.client.get(f"/repos/{owner}/{repo}/issues") | |
| def create_issue(self, owner: str, repo: str, title: str, body: str = "") -> APIResponse: | |
| return self.client.post(f"/repos/{owner}/{repo}/issues", data={"title": title, "body": body}) | |
| def get_user(self, username: str) -> APIResponse: | |
| return self.client.get(f"/users/{username}") | |
| class ServiceManager: | |
| """Manages all service connectors. | |
| Central registry for all external service connections. | |
| """ | |
| def __init__(self) -> None: | |
| self.fetcher = HTTPFetcher() | |
| self._services: dict[str, Any] = {"http_fetcher": self.fetcher} | |
| self._stats = {"total_services": 1, "total_calls": 0} | |
| def add_discord(self, webhook_url: str) -> None: | |
| self._services["discord"] = DiscordWebhook(webhook_url) | |
| self._stats["total_services"] += 1 | |
| def add_slack(self, webhook_url: str) -> None: | |
| self._services["slack"] = SlackWebhook(webhook_url) | |
| self._stats["total_services"] += 1 | |
| def add_github(self, token: str = "") -> None: | |
| self._services["github"] = GitHubConnector(token) | |
| self._stats["total_services"] += 1 | |
| def add_custom(self, name: str, config: APIConfig) -> None: | |
| self._services[name] = RESTClient(config) | |
| self._stats["total_services"] += 1 | |
| def get(self, name: str) -> Any | None: | |
| return self._services.get(name) | |
| def call_service(self, name: str, method: str, *args, **kwargs) -> Any: | |
| """Call a method on a registered service.""" | |
| service = self._services.get(name) | |
| if service is None: | |
| return {"error": f"Service '{name}' not found"} | |
| self._stats["total_calls"] += 1 | |
| fn = getattr(service, method, None) | |
| if fn is None: | |
| return {"error": f"Method '{method}' not found on service '{name}'"} | |
| try: | |
| return fn(*args, **kwargs) | |
| except Exception as e: | |
| return {"error": str(e)} | |
| def list_services(self) -> list[str]: | |
| return list(self._services.keys()) | |
| def get_stats(self) -> dict[str, Any]: | |
| return {**self._stats, "services": list(self._services.keys())} | |