Padmanav commited on
Commit
4d69fe0
·
1 Parent(s): d34b7bd

feat: convert to async/await with parallel agent execution via asyncio.gather

Browse files
app/agents/bug_detection_agent.py CHANGED
@@ -7,7 +7,7 @@ from app.core.prompts import BUG_DETECTION_PROMPT
7
  from app.models.issue import IssueReport, Bug, Warning, Suggestion
8
 
9
 
10
- def run(local_path: str) -> IssueReport:
11
  """
12
  Detect bugs, warnings and suggestions in a repository.
13
  """
@@ -53,7 +53,7 @@ Code Samples:
53
 
54
  # Step 5 - Call LLM
55
  prompt = BUG_DETECTION_PROMPT.format(code_info=code_info)
56
- llm_response = call_llm(prompt)
57
 
58
  # Step 6 - Parse response
59
  try:
 
7
  from app.models.issue import IssueReport, Bug, Warning, Suggestion
8
 
9
 
10
+ async def run(local_path: str) -> IssueReport:
11
  """
12
  Detect bugs, warnings and suggestions in a repository.
13
  """
 
53
 
54
  # Step 5 - Call LLM
55
  prompt = BUG_DETECTION_PROMPT.format(code_info=code_info)
56
+ llm_response = await call_llm(prompt)
57
 
58
  # Step 6 - Parse response
59
  try:
app/agents/code_review_agent.py CHANGED
@@ -6,7 +6,7 @@ from app.models.review import ReviewSuggestions
6
  from app.models.repository import RepositoryMetadata
7
 
8
 
9
- def run(local_path: str, metadata: RepositoryMetadata) -> ReviewSuggestions:
10
  """
11
  Perform AI-powered code review on repository.
12
  """
@@ -36,7 +36,7 @@ def run(local_path: str, metadata: RepositoryMetadata) -> ReviewSuggestions:
36
  # Step 3 - Call LLM
37
  source_code = "\n\n".join(source_samples)
38
  prompt = CODE_REVIEW_PROMPT.format(source_code=source_code)
39
- llm_response = call_llm(prompt)
40
 
41
  # Step 4 - Parse response
42
  try:
 
6
  from app.models.repository import RepositoryMetadata
7
 
8
 
9
+ async def run(local_path: str, metadata: RepositoryMetadata) -> ReviewSuggestions:
10
  """
11
  Perform AI-powered code review on repository.
12
  """
 
36
  # Step 3 - Call LLM
37
  source_code = "\n\n".join(source_samples)
38
  prompt = CODE_REVIEW_PROMPT.format(source_code=source_code)
39
+ llm_response = await call_llm(prompt)
40
 
41
  # Step 4 - Parse response
42
  try:
app/agents/repo_analysis_agent.py CHANGED
@@ -6,7 +6,7 @@ from app.core.prompts import REPO_ANALYSIS_PROMPT
6
  from app.models.repository import RepositoryMetadata
7
 
8
 
9
- def run(repo_url: str, local_path: str) -> RepositoryMetadata:
10
  """
11
  Analyze a repository and return structured metadata.
12
  """
@@ -32,7 +32,7 @@ Functions Found: {sum(len(r['functions']) for r in ast_results)}
32
 
33
  # Step 3 - Call LLM
34
  prompt = REPO_ANALYSIS_PROMPT.format(repo_info=repo_info)
35
- llm_response = call_llm(prompt)
36
 
37
  # Step 4 - Parse response
38
  try:
 
6
  from app.models.repository import RepositoryMetadata
7
 
8
 
9
+ async def run(repo_url: str, local_path: str) -> RepositoryMetadata:
10
  """
11
  Analyze a repository and return structured metadata.
12
  """
 
32
 
33
  # Step 3 - Call LLM
34
  prompt = REPO_ANALYSIS_PROMPT.format(repo_info=repo_info)
35
+ llm_response = await call_llm(prompt)
36
 
37
  # Step 4 - Parse response
38
  try:
app/agents/report_generator_agent.py CHANGED
@@ -7,7 +7,7 @@ from app.models.review import ReviewSuggestions, GeneratedTests
7
  from app.models.report import EngineeringReport
8
 
9
 
10
- def run(
11
  metadata: RepositoryMetadata,
12
  issues: IssueReport,
13
  tests: GeneratedTests,
@@ -56,7 +56,7 @@ Summary: {review.summary}
56
  tests=tests_summary,
57
  review=review_summary
58
  )
59
- full_report = call_llm(prompt, max_tokens=3000)
60
 
61
  # Step 3 - Build final report
62
  report = EngineeringReport(
 
7
  from app.models.report import EngineeringReport
8
 
9
 
10
+ async def run(
11
  metadata: RepositoryMetadata,
12
  issues: IssueReport,
13
  tests: GeneratedTests,
 
56
  tests=tests_summary,
57
  review=review_summary
58
  )
59
+ full_report = await call_llm(prompt, max_tokens=3000)
60
 
61
  # Step 3 - Build final report
62
  report = EngineeringReport(
app/agents/test_generation_agent.py CHANGED
@@ -5,7 +5,7 @@ from app.core.prompts import TEST_GENERATION_PROMPT
5
  from app.models.review import GeneratedTests
6
 
7
 
8
- def run(local_path: str) -> GeneratedTests:
9
  """
10
  Generate pytest test cases for uncovered functions.
11
  """
@@ -48,7 +48,7 @@ def run(local_path: str) -> GeneratedTests:
48
  # Step 3 - Call LLM
49
  source_code = "\n\n".join(source_code_samples)
50
  prompt = TEST_GENERATION_PROMPT.format(source_code=source_code)
51
- llm_response = call_llm(prompt, max_tokens=3000)
52
 
53
  # Step 4 - Count generated tests
54
  test_count = llm_response.count("def test_")
 
5
  from app.models.review import GeneratedTests
6
 
7
 
8
+ async def run(local_path: str) -> GeneratedTests:
9
  """
10
  Generate pytest test cases for uncovered functions.
11
  """
 
48
  # Step 3 - Call LLM
49
  source_code = "\n\n".join(source_code_samples)
50
  prompt = TEST_GENERATION_PROMPT.format(source_code=source_code)
51
+ llm_response = await call_llm(prompt, max_tokens=3000)
52
 
53
  # Step 4 - Count generated tests
54
  test_count = llm_response.count("def test_")
app/api/routes.py CHANGED
@@ -1,3 +1,4 @@
 
1
  from fastapi import APIRouter, HTTPException
2
  from app.models.repository import RepositoryRequest, RepositoryResponse
3
  from app.models.report import EngineeringReport
@@ -19,7 +20,7 @@ def health_check():
19
 
20
 
21
  @router.post("/analyze", response_model=EngineeringReport)
22
- def analyze_repository(request: RepositoryRequest):
23
  """
24
  Full pipeline:
25
  1. Clone repository
@@ -33,11 +34,15 @@ def analyze_repository(request: RepositoryRequest):
33
  local_path = clone_repository(request.github_url)
34
 
35
  # Step 2 - Run agents in order
36
- metadata = repo_analysis_agent.run(request.github_url, local_path)
37
- issues = bug_detection_agent.run(local_path)
38
- tests = test_generation_agent.run(local_path)
39
- review = code_review_agent.run(local_path, metadata)
40
- report = report_generator_agent.run(metadata, issues, tests, review)
 
 
 
 
41
 
42
  return report
43
 
@@ -51,7 +56,7 @@ def analyze_repository(request: RepositoryRequest):
51
 
52
 
53
  @router.post("/quick-analyze", response_model=RepositoryResponse)
54
- def quick_analyze(request: RepositoryRequest):
55
  """
56
  Only run repository analysis agent.
57
  Faster, for testing purposes.
@@ -60,7 +65,7 @@ def quick_analyze(request: RepositoryRequest):
60
 
61
  try:
62
  local_path = clone_repository(request.github_url)
63
- metadata = repo_analysis_agent.run(request.github_url, local_path)
64
 
65
  return RepositoryResponse(
66
  success=True,
 
1
+ import asyncio
2
  from fastapi import APIRouter, HTTPException
3
  from app.models.repository import RepositoryRequest, RepositoryResponse
4
  from app.models.report import EngineeringReport
 
20
 
21
 
22
  @router.post("/analyze", response_model=EngineeringReport)
23
+ async def analyze_repository(request: RepositoryRequest):
24
  """
25
  Full pipeline:
26
  1. Clone repository
 
34
  local_path = clone_repository(request.github_url)
35
 
36
  # Step 2 - Run agents in order
37
+ metadata = await repo_analysis_agent.run(request.github_url, local_path)
38
+
39
+ issues, tests, review = await asyncio.gather(
40
+ bug_detection_agent.run(local_path),
41
+ test_generation_agent.run(local_path),
42
+ code_review_agent.run(local_path, metadata),
43
+ )
44
+
45
+ report = await report_generator_agent.run(metadata, issues, tests, review)
46
 
47
  return report
48
 
 
56
 
57
 
58
  @router.post("/quick-analyze", response_model=RepositoryResponse)
59
+ async def quick_analyze(request: RepositoryRequest):
60
  """
61
  Only run repository analysis agent.
62
  Faster, for testing purposes.
 
65
 
66
  try:
67
  local_path = clone_repository(request.github_url)
68
+ metadata = await repo_analysis_agent.run(request.github_url, local_path)
69
 
70
  return RepositoryResponse(
71
  success=True,
app/core/llm.py CHANGED
@@ -6,7 +6,7 @@ settings = get_settings()
6
  OPENROUTER_API_URL = "https://openrouter.ai/api/v1/chat/completions"
7
 
8
 
9
- def call_llm(prompt: str, system_prompt: str = None, max_tokens: int = 2000) -> str:
10
  """
11
  Call OpenRouter API with any open source model.
12
  Returns the response text.
 
6
  OPENROUTER_API_URL = "https://openrouter.ai/api/v1/chat/completions"
7
 
8
 
9
+ async def call_llm(prompt: str, system_prompt: str = None, max_tokens: int = 2000) -> str:
10
  """
11
  Call OpenRouter API with any open source model.
12
  Returns the response text.