from __future__ import annotations import logging from datetime import date from typing import Optional from sqlalchemy.orm import Session from app.agent.report_writer import ReportWriter from app.core.config import Settings from app.db.repository import AgentRepository from app.integrations.github_client import GitHubHotProjectClient from app.integrations.news_search_client import NewsSearchClient from app.llm.grok_client import GrokIntelligenceClient from app.schemas.agent import RunResponse logger = logging.getLogger(__name__) class AgentRunner: """Coordinates source collection, persistence, and report writing.""" def __init__(self, db: Session, settings: Settings) -> None: self.repo = AgentRepository(db) self.db = db self.github = GitHubHotProjectClient(settings) self.news = NewsSearchClient(settings) self.grok = GrokIntelligenceClient(settings) self.writer = ReportWriter(settings.report_dir) def run_daily(self, run_date: Optional[date] = None) -> RunResponse: # Runner统一编排候选采集、模型研判和持久化,保证一次运行只有一种业务路径。 current_date = run_date or date.today() request_payload = { "run_date": current_date.isoformat(), "mode": "grok_agent", } run = self.repo.create_run(request_payload=request_payload) logger.info("agent_run_started run_id=%s run_date=%s mode=grok_agent", run.id, current_date) try: topics = self.repo.list_enabled_topics() news_candidates = self.news.collect_ai_news(run_date=current_date) github_projects = self.github.collect_hot_projects(run_date=current_date) result = self.grok.collect_daily_intelligence( topics=topics, news_candidates=news_candidates, github_projects=github_projects, run_date=current_date, ) signals = self.repo.save_signals(run=run, items=result.signals) report_path = self.writer.write_daily_report(current_date, result.report_markdown) self.repo.save_report( run=run, title=result.title, content_md=result.report_markdown, file_path=str(report_path), ) self.repo.mark_run_complete( run=run, raw_response={ "mode": "grok_agent", "topic_count": len(topics), "news_candidate_count": len(news_candidates), "github_project_count": len(github_projects), "model": self.grok.settings.llm_model, "model_response": result.raw_response, }, ) self.db.commit() logger.info( "agent_run_completed run_id=%s signals=%s report_path=%s", run.id, len(signals), report_path, ) return RunResponse(run_id=run.id, status=run.status, report_path=str(report_path)) except Exception as exc: self.repo.mark_run_failed(run=run, error=str(exc)) self.db.commit() logger.exception("agent_run_failed run_id=%s error=%s", run.id, exc) raise