import logging import os from contextlib import asynccontextmanager import httpx from dotenv import load_dotenv from fastapi import FastAPI, HTTPException from agents.issue_triage.IssueTriageAgent import IssueTriageAgent from agents.issue_triage.context_builder import YouTrackContextBuilder from agents.registry import AgentRegistry from common.llm_client import LLMClient from common.youtrack_mcp_client import YouTrackMCPClient, IssueNotFound logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) load_dotenv() def env(key: str) -> str: value = os.environ.get(key) if not value: raise RuntimeError(f"Missing required env var: {key}") return value @asynccontextmanager async def lifespan(app: FastAPI): mcp = await YouTrackMCPClient( str(os.getenv('YOUTRACK_MCP_SERVER')), str(os.getenv('YOUTRACK_MCP_TOKEN')), ).connect() # # # res = await mcp.call_tool( # "add_issue_comment", # {"issueId": "ARCH-229", "text": "test"} # ) # logger.info(res) http_for_attachments = httpx.AsyncClient( headers={"Authorization": f"Bearer {env('YOUTRACK_MCP_TOKEN')}"}, proxy=env("HTTPS_PROXY"), timeout=httpx.Timeout(30.0, connect=10.0, read=60.0), follow_redirects=True, ) app.state.issue_reader_agent = IssueTriageAgent( YouTrackContextBuilder(mcp, http_for_attachments), LLMClient( base_url=env("LLM_ADDRESS"), api_key=env("LLM_API_KEY"), model=env("LLM_MODEL"), ), AgentRegistry(), mcp ) yield # ---- shutdown ---- await mcp.close() app = FastAPI(lifespan=lifespan) @app.get("/") async def root(): return {"message": "Hello World"} @app.get("/hello/{name}") async def say_hello(name: str): return {"message": f"Hello {name}"} @app.get("/consume_task") async def decomposing_issue(issue: str): agent: IssueTriageAgent = app.state.issue_reader_agent try: logger.info(f"Received an issue: {issue}") plan = await agent.plan_issue(issue) logger.info("Task planning successful.") logger.info(plan.render()) return {"plan": plan} except IssueNotFound: logger.error(f"Issue {issue} not found.") raise HTTPException(status_code=404, detail=f"Issue {issue} not found") except Exception as e: logger.exception("An unexpected error occurred") return {"error": str(e)}