PraneshJs commited on
Commit
c43538b
·
verified ·
1 Parent(s): 4e9746f

Update agent.py

Browse files
Files changed (1) hide show
  1. agent.py +81 -38
agent.py CHANGED
@@ -1,74 +1,114 @@
 
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,
@@ -76,8 +116,8 @@ def make_agents(repo_url: str):
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,
@@ -85,8 +125,8 @@ def make_agents(repo_url: str):
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,
@@ -94,8 +134,8 @@ def make_agents(repo_url: str):
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,
@@ -103,8 +143,8 @@ def make_agents(repo_url: str):
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,
@@ -112,46 +152,48 @@ def make_agents(repo_url: str):
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)
@@ -164,5 +206,6 @@ def run_repo_review(repo_url: str, brief: str = "") -> str:
164
  manager_agent=manager,
165
  verbose=True,
166
  )
 
167
  result = crew.kickoff()
168
  return str(result)
 
1
+ # agent.py
2
  import os
3
+ from typing import Optional, List
4
  from crewai import Agent, Task, Crew, Process
5
  from crewai_tools import GithubSearchTool
6
+ from google import genai # Gemini client (google-genai package)
7
+ from dotenv import load_dotenv
8
+
9
+ load_dotenv()
10
 
11
  # ---------------------------
12
  # CONFIG
13
  # ---------------------------
 
 
14
  GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
15
+ GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
 
16
 
 
17
  if not GOOGLE_API_KEY:
18
+ raise RuntimeError("❌ Missing GOOGLE_API_KEY (get one from https://aistudio.google.com)")
19
 
20
+ # Gemini Client
21
  client = genai.Client(api_key=GOOGLE_API_KEY)
22
+ MODEL_NAME = os.getenv("GEMINI_MODEL", "gemini-1.5-flash")
23
+
24
+ DEFAULT_CONTENT_TYPES = ["code", "pr", "issue", "repo"]
25
 
26
  # ---------------------------
27
+ # Gemini Embedding Adapter (Free Embeddings)
28
+ # ---------------------------
29
+ class GeminiEmbedding:
30
+ """Uses Google Gemini text-embedding-004 model (free tier)"""
31
+
32
+ def __init__(self, model="text-embedding-004", api_key=None):
33
+ self.model = model
34
+ self.client = genai.Client(api_key=api_key or GOOGLE_API_KEY)
35
+
36
+ def embed_documents(self, texts: List[str]) -> List[List[float]]:
37
+ vectors = []
38
+ for text in texts:
39
+ try:
40
+ res = self.client.models.embed_content(model=self.model, contents=text)
41
+ vectors.append(res.embedding.values)
42
+ except Exception as e:
43
+ print(f"⚠️ Embedding error: {e}")
44
+ vectors.append([])
45
+ return vectors
46
+
47
+ def embed_query(self, text: str) -> List[float]:
48
+ try:
49
+ res = self.client.models.embed_content(model=self.model, contents=text)
50
+ return res.embedding.values
51
+ except Exception as e:
52
+ print(f"⚠️ Embedding query error: {e}")
53
+ return []
54
+
55
+
56
+ # ---------------------------
57
+ # Gemini LLM Wrapper
58
  # ---------------------------
59
  class GeminiLLM:
60
  def __init__(self, model: str):
61
  self.model = model
62
 
63
  def generate(self, prompt: str) -> str:
64
+ """CrewAI-compatible LLM generate method."""
65
  try:
66
  response = client.models.generate_content(
67
  model=self.model,
68
  contents=prompt,
69
+ generation_config={"temperature": 0.7, "max_output_tokens": 1024}
70
  )
71
  return response.text
72
  except Exception as e:
73
  return f"⚠️ Gemini API error: {e}"
74
 
75
+
76
+ # Instantiate LLM + embedder
77
  gemini_llm = GeminiLLM(MODEL_NAME)
78
+ embedder = GeminiEmbedding(api_key=GOOGLE_API_KEY)
79
 
80
  # ---------------------------
81
+ # GitHub Tool using free embeddings
82
  # ---------------------------
83
  def github_tool(repo_url: Optional[str] = None) -> GithubSearchTool:
84
+ """Create a GitHub Search Tool with free Gemini embeddings (no OpenAI key)."""
85
  if not GITHUB_TOKEN:
86
  raise RuntimeError("Missing GITHUB_TOKEN in environment.")
87
+
88
  if repo_url:
89
  return GithubSearchTool(
90
  github_repo=repo_url,
91
  gh_token=GITHUB_TOKEN,
92
  content_types=DEFAULT_CONTENT_TYPES,
93
+ embedder=embedder,
94
  )
95
  return GithubSearchTool(
96
  gh_token=GITHUB_TOKEN,
97
  content_types=DEFAULT_CONTENT_TYPES,
98
+ embedder=embedder,
99
  )
100
 
101
+
102
  # ---------------------------
103
+ # AGENTS
104
  # ---------------------------
105
  def make_agents(repo_url: str):
106
  repo_search = github_tool(repo_url)
107
 
108
  repo_mapper = Agent(
109
  role="Repository Mapper",
110
+ goal="Map repo structure, dependencies, and frameworks.",
111
+ backstory="Understands directory trees, tech stacks, and configuration files.",
112
  tools=[repo_search],
113
  llm=gemini_llm,
114
  verbose=True,
 
116
 
117
  code_reviewer = Agent(
118
  role="Code Reviewer",
119
+ goal="Perform code review for quality, structure, and clarity.",
120
+ backstory="A senior engineer giving actionable review comments with examples.",
121
  tools=[repo_search],
122
  llm=gemini_llm,
123
  verbose=True,
 
125
 
126
  security_auditor = Agent(
127
  role="Security Auditor",
128
+ goal="Identify secrets, vulnerabilities, unsafe APIs, and dependencies.",
129
+ backstory="A white-hat hacker finding issues and giving fixes.",
130
  tools=[repo_search],
131
  llm=gemini_llm,
132
  verbose=True,
 
134
 
135
  doc_explainer = Agent(
136
  role="Documentation Explainer",
137
+ goal="Summarize architecture, data flow, and how to run the project.",
138
+ backstory="Explains tech systems simply and clearly with examples.",
139
  tools=[repo_search],
140
  llm=gemini_llm,
141
  verbose=True,
 
143
 
144
  manager = Agent(
145
  role="Engineering Manager",
146
+ goal="Coordinate all agents and compile a clear, cohesive final report.",
147
+ backstory="Ensures a professional, well-structured final document.",
148
  allow_delegation=True,
149
  llm=gemini_llm,
150
  verbose=True,
 
152
 
153
  return repo_mapper, code_reviewer, security_auditor, doc_explainer, manager
154
 
155
+
156
  # ---------------------------
157
+ # TASKS
158
  # ---------------------------
159
  def make_tasks(repo_url: str, brief: str = ""):
160
+ prefix = f"Target Repository: {repo_url}\nBrief: {brief}\nInclude file paths where relevant."
161
 
162
  t_map = Task(
163
+ description=f"{prefix}\nMap the repository structure, dependencies, languages, and build tools.",
164
+ expected_output="Markdown-formatted repository map with bullets and paths.",
165
  agent_role="Repository Mapper",
166
  )
167
 
168
  t_review = Task(
169
+ description=f"{prefix}\nPerform detailed code review (readability, refactors, testing, etc.).",
170
+ expected_output="Actionable review bullets grouped by issue type.",
171
  agent_role="Code Reviewer",
172
  )
173
 
174
  t_sec = Task(
175
+ description=f"{prefix}\nPerform security audit (secrets, vulnerabilities, dependencies).",
176
+ expected_output="Security findings table (Issue | Evidence | Risk | Fix).",
177
  agent_role="Security Auditor",
178
  )
179
 
180
  t_doc = Task(
181
+ description=f"{prefix}\nExplain architecture, modules, data flow, setup, and usage.",
182
+ expected_output="Readable explanation with Quickstart and architecture overview.",
183
  agent_role="Documentation Explainer",
184
  )
185
 
186
  t_merge = Task(
187
+ description="Merge all outputs into a clean, single Markdown report with clear sections and TOC.",
188
+ expected_output="Final cohesive Markdown report.",
189
  agent_role="Engineering Manager",
190
  )
191
 
192
  return t_map, t_review, t_sec, t_doc, t_merge
193
 
194
+
195
  # ---------------------------
196
+ # RUNNER
197
  # ---------------------------
198
  def run_repo_review(repo_url: str, brief: str = "") -> str:
199
  repo_mapper, reviewer, auditor, explainer, manager = make_agents(repo_url)
 
206
  manager_agent=manager,
207
  verbose=True,
208
  )
209
+
210
  result = crew.kickoff()
211
  return str(result)