"""Steward application entry point.""" import logging import sys from datetime import time from telegram.ext import ContextTypes from steward.bot.telegram import build_application, send_proposal from steward.config import get_settings from steward.llm.client import LLMClient from steward.memory.thread_store import ThreadMemoryStore from steward.proposals.generator import ProposalGenerator from steward.tools.client import ToolClient logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s", ) logger = logging.getLogger(__name__) async def _run_scheduled_analysis(context: ContextTypes.DEFAULT_TYPE) -> None: """Scheduled job: run analysis and push proposal via Telegram.""" logger.info("Running scheduled analysis") generator: ProposalGenerator = context.bot_data["generator"] user_ids: list[int] = context.bot_data["user_ids"] proposal = await generator.run() if proposal: await send_proposal(context.application, proposal, user_ids) else: logger.info("No proposal generated (generator returned None)") def main() -> None: """Start Steward.""" settings = get_settings() if not settings.telegram_bot_token: logger.error("TELEGRAM_BOT_TOKEN is not set – cannot start") sys.exit(1) if not settings.openai_api_key: logger.error("OPENAI_API_KEY is not set – cannot start") sys.exit(1) llm = LLMClient(settings) thread_store = ThreadMemoryStore(settings.thread_memory_path) tool_client: ToolClient | None = None if settings.mcp_server_url: tool_client = ToolClient( base_url=settings.mcp_server_url, api_key=settings.mcp_server_api_key, ) logger.info("MCP tool server configured: %s", settings.mcp_server_url) else: logger.info("No MCP_SERVER_URL configured – tool calling disabled") app = build_application(settings, llm, thread_store, tool_client) generator = ProposalGenerator(settings, llm) app.bot_data["generator"] = generator app.bot_data["user_ids"] = settings.telegram_allowed_user_ids if app.job_queue is not None: app.job_queue.run_daily( _run_scheduled_analysis, time=time(hour=settings.analysis_cron_hour, minute=settings.analysis_cron_minute), ) else: logger.warning("JobQueue not available – scheduled analysis disabled") logger.info( "Steward starting: model=%s analysis_url=%s tools=%s", settings.openai_model, settings.analysis_target_url or "(none)", settings.mcp_server_url or "(none)", ) app.run_polling(allowed_updates=["message"]) if __name__ == "__main__": main()