from __future__ import annotations import logging from dataclasses import dataclass, field from .file_consent import FileConsentStore from .graph import MSTeamsGraphClient from .polls import PollStore from .sdk import BotFrameworkAdapter from .sent_message_cache import SentMessageCache from .sso import SSOTokenStore from .user_agent import GraphRateLimiter logger = logging.getLogger(__name__) @dataclass class MSTeamsRuntime: adapter: BotFrameworkAdapter | None = None conversation_store: object | None = None poll_store: PollStore | None = None sent_message_cache: SentMessageCache = field(default_factory=SentMessageCache) file_consent_store: FileConsentStore = field(default_factory=FileConsentStore) sso_token_store: SSOTokenStore = field(default_factory=SSOTokenStore) graph_client: MSTeamsGraphClient | None = None graph_rate_limiter: GraphRateLimiter = field(default_factory=GraphRateLimiter) is_running: bool = False @property def has_graph_client(self) -> bool: return self.graph_client is not None def get_graph_client(self) -> MSTeamsGraphClient | None: if self.graph_client and self.graph_rate_limiter.can_proceed(): self.graph_rate_limiter.record() return self.graph_client if self.graph_client: logger.warning("Graph API rate limit reached (%d remaining)", self.graph_rate_limiter.remaining) return None def shutdown(self) -> None: self.is_running = False if self.poll_store: self.poll_store.save() self.sent_message_cache.cleanup()