87 lines
2.4 KiB
Python
87 lines
2.4 KiB
Python
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)}
|