PraneshJs commited on
Commit
e147c33
·
verified ·
1 Parent(s): afba3ec

Create agent.py

Browse files
Files changed (1) hide show
  1. agent.py +168 -0
agent.py ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from typing import Optional
3
+ from crewai import Agent, Task, Crew, Process
4
+ from crewai_tools import GithubSearchTool
5
+ from google import genai # Google's Gemini client
6
+
7
+ # ---------------------------
8
+ # CONFIG
9
+ # ---------------------------
10
+
11
+ # Required environment variables
12
+ GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
13
+ GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY") # from AI Studio
14
+ DEFAULT_CONTENT_TYPES = ["code", "pr", "issue", "repo"]
15
+
16
+ # Gemini client setup
17
+ if not GOOGLE_API_KEY:
18
+ raise ValueError("❌ Missing GOOGLE_API_KEY (get one from https://aistudio.google.com)")
19
+
20
+ client = genai.Client(api_key=GOOGLE_API_KEY)
21
+ MODEL_NAME = os.getenv("GEMINI_MODEL", "gemini-1.5-flash") # fast & cheap
22
+
23
+ # ---------------------------
24
+ # Custom Gemini-backed LLM wrapper
25
+ # ---------------------------
26
+ class GeminiLLM:
27
+ def __init__(self, model: str):
28
+ self.model = model
29
+
30
+ def generate(self, prompt: str) -> str:
31
+ """CrewAI-compatible .generate() interface."""
32
+ try:
33
+ response = client.models.generate_content(
34
+ model=self.model,
35
+ contents=prompt,
36
+ generation_config={"temperature": 0.7}
37
+ )
38
+ return response.text
39
+ except Exception as e:
40
+ return f"⚠️ Gemini API error: {e}"
41
+
42
+ # Instantiate a Gemini LLM
43
+ gemini_llm = GeminiLLM(MODEL_NAME)
44
+
45
+ # ---------------------------
46
+ # GithubSearchTool
47
+ # ---------------------------
48
+ def github_tool(repo_url: Optional[str] = None) -> GithubSearchTool:
49
+ if not GITHUB_TOKEN:
50
+ raise RuntimeError("Missing GITHUB_TOKEN in environment.")
51
+ if repo_url:
52
+ return GithubSearchTool(
53
+ github_repo=repo_url,
54
+ gh_token=GITHUB_TOKEN,
55
+ content_types=DEFAULT_CONTENT_TYPES,
56
+ )
57
+ return GithubSearchTool(
58
+ gh_token=GITHUB_TOKEN,
59
+ content_types=DEFAULT_CONTENT_TYPES,
60
+ )
61
+
62
+ # ---------------------------
63
+ # Agents
64
+ # ---------------------------
65
+ def make_agents(repo_url: str):
66
+ repo_search = github_tool(repo_url)
67
+
68
+ repo_mapper = Agent(
69
+ role="Repository Mapper",
70
+ goal="Map repository structure, dependencies, and build tools.",
71
+ backstory="Understands folder trees and project metadata deeply.",
72
+ tools=[repo_search],
73
+ llm=gemini_llm,
74
+ verbose=True,
75
+ )
76
+
77
+ code_reviewer = Agent(
78
+ role="Code Reviewer",
79
+ goal="Perform detailed code reviews for quality, readability, and maintainability.",
80
+ backstory="An experienced engineer identifying refactors and anti-patterns.",
81
+ tools=[repo_search],
82
+ llm=gemini_llm,
83
+ verbose=True,
84
+ )
85
+
86
+ security_auditor = Agent(
87
+ role="Security Auditor",
88
+ goal="Detect security vulnerabilities, secrets, and risky dependencies.",
89
+ backstory="Thinks like a red team but reports like a white hat.",
90
+ tools=[repo_search],
91
+ llm=gemini_llm,
92
+ verbose=True,
93
+ )
94
+
95
+ doc_explainer = Agent(
96
+ role="Documentation Explainer",
97
+ goal="Explain project architecture, flow, and quickstart guide.",
98
+ backstory="A great teacher simplifying complex systems.",
99
+ tools=[repo_search],
100
+ llm=gemini_llm,
101
+ verbose=True,
102
+ )
103
+
104
+ manager = Agent(
105
+ role="Engineering Manager",
106
+ goal="Coordinate all other agents and compile a cohesive final report.",
107
+ backstory="A senior manager ensuring thoroughness and clarity.",
108
+ allow_delegation=True,
109
+ llm=gemini_llm,
110
+ verbose=True,
111
+ )
112
+
113
+ return repo_mapper, code_reviewer, security_auditor, doc_explainer, manager
114
+
115
+ # ---------------------------
116
+ # Tasks
117
+ # ---------------------------
118
+ def make_tasks(repo_url: str, brief: str = ""):
119
+ preface = f"Target repository: {repo_url}\n{brief}\nPrefer file references and clear sections."
120
+
121
+ t_map = Task(
122
+ description=f"{preface}\nMap repo structure and dependencies.",
123
+ expected_output="Markdown summary of repo structure.",
124
+ agent_role="Repository Mapper",
125
+ )
126
+
127
+ t_review = Task(
128
+ description=f"{preface}\nCode review with key issues, refactors, and suggestions.",
129
+ expected_output="Concise bullet-based code review with examples.",
130
+ agent_role="Code Reviewer",
131
+ )
132
+
133
+ t_sec = Task(
134
+ description=f"{preface}\nSecurity audit (secrets, unsafe libs, injections, etc.).",
135
+ expected_output="Security findings in table format.",
136
+ agent_role="Security Auditor",
137
+ )
138
+
139
+ t_doc = Task(
140
+ description=f"{preface}\nExplain architecture, modules, and how to run the project.",
141
+ expected_output="Readable architecture explanation and quickstart.",
142
+ agent_role="Documentation Explainer",
143
+ )
144
+
145
+ t_merge = Task(
146
+ description="Merge all findings into one cohesive Markdown report with clear sections.",
147
+ expected_output="Final Markdown report.",
148
+ agent_role="Engineering Manager",
149
+ )
150
+
151
+ return t_map, t_review, t_sec, t_doc, t_merge
152
+
153
+ # ---------------------------
154
+ # Runner
155
+ # ---------------------------
156
+ def run_repo_review(repo_url: str, brief: str = "") -> str:
157
+ repo_mapper, reviewer, auditor, explainer, manager = make_agents(repo_url)
158
+ t_map, t_review, t_sec, t_doc, t_merge = make_tasks(repo_url, brief)
159
+
160
+ crew = Crew(
161
+ agents=[repo_mapper, reviewer, auditor, explainer, manager],
162
+ tasks=[t_map, t_review, t_sec, t_doc, t_merge],
163
+ process=Process.hierarchical,
164
+ manager_agent=manager,
165
+ verbose=True,
166
+ )
167
+ result = crew.kickoff()
168
+ return str(result)