Skip to content

Commit ea97cbe

Browse files
committed
added coderabbit changes
1 parent 60916e0 commit ea97cbe

File tree

9 files changed

+57
-168
lines changed

9 files changed

+57
-168
lines changed

backend/app/agents/devrel/github/github_toolkit.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,24 @@ async def classify_intent(self, user_query: str) -> Dict[str, Any]:
5757

5858
import json
5959
import re
60-
60+
6161
content = response.content.strip()
62-
63-
# Try to extract JSON from markdown code blocks if present
64-
json_match = re.search(r'```(?:json)?\s*(\{.*?\})\s*```', content, re.DOTALL)
65-
if json_match:
66-
content = json_match.group(1)
67-
68-
json_match = re.search(r'\{.*\}', content, re.DOTALL)
69-
if json_match:
70-
content = json_match.group(0)
71-
72-
result = json.loads(content)
62+
63+
candidates = []
64+
cb = re.search(r'```(?:json)?\s*({[\s\S]*?})\s*```', content, flags=re.IGNORECASE)
65+
if cb:
66+
candidates.append(cb.group(1))
67+
candidates.extend(m.group(0) for m in re.finditer(r'\{[\s\S]*?\}', content))
68+
69+
result = None
70+
for payload in candidates:
71+
try:
72+
result = json.loads(payload)
73+
break
74+
except json.JSONDecodeError:
75+
continue
76+
if result is None:
77+
raise json.JSONDecodeError("No valid JSON object found in LLM response", content, 0)
7378

7479
classification = result.get("classification")
7580
if classification not in self.tools:

backend/app/agents/devrel/github/services/github_mcp_client.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22
from typing import Dict, Any, Optional
33
import aiohttp
4+
import asyncio
45

56
logger = logging.getLogger(__name__)
67

@@ -15,7 +16,7 @@ def __init__(self, mcp_server_url: str = "http://localhost:8001"):
1516

1617
async def __aenter__(self):
1718
# Async context manager entry
18-
self.session = aiohttp.ClientSession()
19+
self.session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=15))
1920
return self
2021

2122
async def __aexit__(self, exc_type, exc_val, exc_tb):
@@ -29,7 +30,6 @@ async def get_repo_info(self, owner: str, repo: str) -> Dict[str, Any]:
2930
raise RuntimeError("Client not initialized. Use async context manager.")
3031

3132
try:
32-
# Try the direct repo_info endpoint first (simpler)
3333
payload = {
3434
"owner": owner,
3535
"repo": repo
@@ -65,5 +65,7 @@ async def is_server_available(self) -> bool:
6565
try:
6666
async with self.session.get(f"{self.mcp_server_url}/health", timeout=5) as response:
6767
return response.status == 200
68-
except:
68+
69+
except (aiohttp.ClientError, asyncio.TimeoutError) as e:
70+
logger.debug(f"Health check failed: {e}")
6971
return False

backend/app/agents/devrel/github/services/github_mcp_server.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
import os
22
import logging
3-
from dotenv import load_dotenv
3+
from dotenv import load_dotenv, find_dotenv
44
from fastapi import FastAPI, HTTPException
55
from pydantic import BaseModel
66
from .github_mcp_service import GitHubMCPService
7+
from typing import Optional
78

8-
load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), "../../../../.env"))
9+
dotenv_path = find_dotenv(usecwd=True)
10+
if dotenv_path:
11+
load_dotenv(dotenv_path=dotenv_path)
12+
else:
13+
load_dotenv()
914

1015
logging.basicConfig(level=logging.INFO)
1116
logger = logging.getLogger(__name__)
1217

1318
app = FastAPI(title="GitHub MCP Server", version="1.0.0")
1419

20+
github_service: Optional[GitHubMCPService] = None
1521
try:
16-
github_service = GitHubMCPService(token=os.getenv("GITHUB_TOKEN"))
22+
token = os.getenv("GITHUB_TOKEN") or os.getenv("GH_TOKEN")
23+
if not token:
24+
logger.warning("GITHUB_TOKEN/GH_TOKEN not set; GitHub API calls may be rate-limited or fail.")
25+
github_service = GitHubMCPService(token=token)
1726
logger.info("GitHub service initialized successfully")
1827
except Exception as e:
1928
logger.error(f"Failed to initialize GitHub service: {e}")
@@ -51,6 +60,8 @@ async def mcp_endpoint(request: dict):
5160
if not owner or not repo:
5261
return {"error": "Missing owner or repo parameter"}
5362

63+
if not github_service:
64+
return {"error": "GitHub service not available"}
5465
result = github_service.repo_query(owner, repo)
5566
return {"result": result}
5667
else:
@@ -59,7 +70,7 @@ async def mcp_endpoint(request: dict):
5970
return {"error": f"Unknown method: {method}"}
6071

6172
except Exception as e:
62-
logger.error(f"Error in MCP endpoint: {e}")
73+
logger.exception("Error in MCP endpoint")
6374
return {"error": str(e)}
6475

6576
@app.post("/repo_info")

backend/app/agents/devrel/github/services/github_mcp_service.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,15 @@ def __init__(self, token: str = None):
2020
def repo_query(self, owner: str, repo: str) -> dict:
2121

2222
url = f"{self.base_url}/repos/{owner}/{repo}"
23-
headers = {"Authorization": f"token {self.token}"}
23+
headers = {
24+
"Authorization": f"Bearer {self.token}",
25+
"Accept": "application/vnd.github+json",
26+
"X-GitHub-Api-Version": "2022-11-28",
27+
"User-Agent": "DevrAI-GitHubMCPService/0.1"
28+
}
2429

2530
try:
26-
resp = requests.get(url, headers=headers)
31+
resp = requests.get(url, headers=headers, timeout=15)
2732
resp.raise_for_status()
2833
except requests.exceptions.RequestException as e:
2934
return {"error": "Request failed", "message": str(e)}

backend/app/agents/devrel/github/test_repo_query.py

Lines changed: 0 additions & 21 deletions
This file was deleted.

backend/app/agents/devrel/github/tools/repository_query.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
from ..services.github_mcp_client import GitHubMCPClient
22
import re
33

4-
OWNER_REPO_RE = re.compile(r"([A-Za-z0-9_.-]+)/([A-Za-z0-9_.-]+)")
4+
#GitHub URL forms: https(s)://github.com/owner/repo[.git][...], git@github.com:owner/repo[.git]
5+
GH_URL_RE = re.compile(
6+
r'(?:https?://|git@)github\.com[/:]'
7+
r'([A-Za-z0-9](?:-?[A-Za-z0-9]){0,38})/'
8+
r'([A-Za-z0-9._-]+?)(?:\.git)?(?:/|$)',
9+
re.IGNORECASE,
10+
)
11+
12+
OWNER_REPO_RE = re.compile(
13+
r'\b([A-Za-z0-9](?:-?[A-Za-z0-9]){0,38})/([A-Za-z0-9._-]{1,100})\b'
14+
)
515

616
async def handle_repo_query(user_query: str) -> dict:
7-
m = OWNER_REPO_RE.search(user_query)
17+
m = GH_URL_RE.search(user_query) or OWNER_REPO_RE.search(user_query)
818
if not m:
9-
return {"status": "error", "message": "Usage: include owner/repo in query."}
19+
return {"status": "error", "message": "Usage: include a GitHub owner/repo (e.g., AOSSIE-Org/Devr.AI) or a GitHub URL."}
1020

1121
owner, repo = m.group(1), m.group(2)
1222

backend/test_github_integration.py

Lines changed: 0 additions & 75 deletions
This file was deleted.

backend/test_mcp_server.py

Lines changed: 0 additions & 47 deletions
This file was deleted.

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ dependencies = [
2626
"uvicorn (>=0.35.0,<0.36.0)",
2727
"ddgs (>=9.0.2,<10.0.0)",
2828
"fastmcp>=2.11.3,<3.0.0",
29-
"PyGithub>=2.5.0,<3.0.0",
3029
"discord-py (>=2.5.2,<3.0.0)",
3130
]
3231

0 commit comments

Comments
 (0)