11import logging
22import os
3+ import json
4+ import re
35from typing import Dict , Any
46from langchain_google_genai import ChatGoogleGenerativeAI
57from langchain_core .messages import HumanMessage
68from app .core .config import settings
79from .prompts .intent_analysis import GITHUB_INTENT_ANALYSIS_PROMPT
810from .tools .search import handle_web_search
911from .tools .github_support import handle_github_supp
10- # TODO: Implement all tools
1112from .tools .contributor_recommendation import handle_contributor_recommendation
12- # from .tools.repository_query import handle_repo_query
13- # from .tools.issue_creation import handle_issue_creation
14- # from .tools.documentation_generation import handle_documentation_generation
1513from .tools .general_github_help import handle_general_github_help
14+
1615logger = logging .getLogger (__name__ )
1716
1817DEFAULT_ORG = os .getenv ("GITHUB_ORG" )
1918
19+
2020def normalize_org (org_from_user : str = None ) -> str :
21- """
22- Always fallback to env org if user does not specify one.
23- """
21+ """Fallback to env org if user does not specify one."""
2422 if org_from_user and org_from_user .strip ():
2523 return org_from_user .strip ()
2624 return DEFAULT_ORG
@@ -52,41 +50,29 @@ def __init__(self):
5250 ]
5351
5452 async def classify_intent (self , user_query : str ) -> Dict [str , Any ]:
55- """
56- Classify intent and return classification with reasoning.
57-
58- Args:
59- user_query: The user's request or question
60-
61- Returns:
62- Dictionary containing classification, reasoning, and confidence
63- """
53+ """Classify intent and return classification with reasoning."""
6454 logger .info (f"Classifying intent for query: { user_query [:100 ]} " )
6555
6656 try :
6757 prompt = GITHUB_INTENT_ANALYSIS_PROMPT .format (user_query = user_query )
6858 response = await self .llm .ainvoke ([HumanMessage (content = prompt )])
6959
70- import json
71- import re
72-
7360 content = response .content .strip ()
7461
75- candidates = []
76- cb = re .search (r'```(?:json)?\s*({[\s\S]*?})\s*```' , content , flags = re .IGNORECASE )
77- if cb :
78- candidates .append (cb .group (1 ))
79- candidates .extend (m .group (0 ) for m in re .finditer (r'\{[\s\S]*?\}' , content ))
80-
81- result = None
82- for payload in candidates :
83- try :
84- result = json .loads (payload )
85- break
86- except json .JSONDecodeError :
87- continue
88- if result is None :
89- raise json .JSONDecodeError ("No valid JSON object found in LLM response" , content , 0 )
62+ try :
63+ result = json .loads (content )
64+ except json .JSONDecodeError :
65+ match = re .search (r"\{.*\}" , content , re .DOTALL )
66+ if match :
67+ result = json .loads (match .group ())
68+ else :
69+ logger .error (f"Invalid JSON in LLM response: { content } " )
70+ return {
71+ "classification" : "general_github_help" ,
72+ "reasoning" : "Failed to parse LLM response as JSON" ,
73+ "confidence" : "low" ,
74+ "query" : user_query
75+ }
9076
9177 classification = result .get ("classification" )
9278 if classification not in self .tools :
@@ -96,21 +82,12 @@ async def classify_intent(self, user_query: str) -> Dict[str, Any]:
9682
9783 result ["query" ] = user_query
9884
99- logger .info (f"Classified intent as for query: { user_query } is: { classification } " )
85+ logger .info (f"Classified intent for query: { user_query } -> { classification } " )
10086 logger .info (f"Reasoning: { result .get ('reasoning' , 'No reasoning provided' )} " )
10187 logger .info (f"Confidence: { result .get ('confidence' , 'unknown' )} " )
10288
10389 return result
10490
105- except json .JSONDecodeError as e :
106- logger .error (f"Error parsing JSON response from LLM: { str (e )} " )
107- logger .error (f"Raw response: { response .content } " )
108- return {
109- "classification" : "general_github_help" ,
110- "reasoning" : f"Failed to parse LLM response: { str (e )} " ,
111- "confidence" : "low" ,
112- "query" : user_query
113- }
11491 except Exception as e :
11592 logger .error (f"Error in intent classification: { str (e )} " )
11693 return {
@@ -121,9 +98,7 @@ async def classify_intent(self, user_query: str) -> Dict[str, Any]:
12198 }
12299
123100 async def execute (self , query : str ) -> Dict [str , Any ]:
124- """
125- Main execution method - classifies intent and delegates to appropriate tools
126- """
101+ """Main execution method - classifies intent and delegates to appropriate tools"""
127102 logger .info (f"Executing GitHub toolkit for query: { query [:100 ]} " )
128103
129104 try :
@@ -140,13 +115,10 @@ async def execute(self, query: str) -> Dict[str, Any]:
140115 result ["org_used" ] = org
141116 elif classification == "repo_support" :
142117 result = "Not implemented"
143- # result = await handle_repo_query(query)
144118 elif classification == "issue_creation" :
145119 result = "Not implemented"
146- # result = await handle_issue_creation(query)
147120 elif classification == "documentation_generation" :
148121 result = "Not implemented"
149- # result = await handle_documentation_generation(query)
150122 elif classification == "web_search" :
151123 result = await handle_web_search (query )
152124 else :
0 commit comments