Skip to content

Commit c41f153

Browse files
style: format code with Black
This commit fixes the style issues introduced in 319a56d according to the output from Black. Details: None
1 parent 319a56d commit c41f153

5 files changed

Lines changed: 573 additions & 328 deletions

File tree

ai_controller.py

Lines changed: 84 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@
2222
from utils.context_builder import ContextBuilder
2323
from utils.notifier import Notifier
2424

25+
2526
class AIController:
2627
"""Controls AI operations and decision making."""
2728

2829
def __init__(self, session_dir: str, config_path: str):
2930
"""Initialize the AI controller.
30-
31+
3132
Args:
3233
session_dir: Directory to store session data
3334
config_path: Path to configuration file
@@ -39,7 +40,7 @@ def __init__(self, session_dir: str, config_path: str):
3940
self.notifier = Notifier(session_dir, config_path)
4041
self.report_generator = ReportGenerator(self.session_dir)
4142
self.output_format = "all" # Default output format
42-
43+
4344
# Initialize session data
4445
self.session_data = {
4546
"start_time": datetime.now().isoformat(),
@@ -48,43 +49,48 @@ def __init__(self, session_dir: str, config_path: str):
4849
"findings": [],
4950
"execution_history": [],
5051
"ai_decisions": [],
51-
"errors": []
52+
"errors": [],
5253
}
5354

5455
@RateLimiter(max_calls=5, time_window=60)
55-
async def process_query(self, query: str, context: Optional[Dict[str, Any]] = None,
56-
session_id: Optional[str] = None, identifier: str = 'default') -> Dict[str, Any]:
56+
async def process_query(
57+
self,
58+
query: str,
59+
context: Optional[Dict[str, Any]] = None,
60+
session_id: Optional[str] = None,
61+
identifier: str = "default",
62+
) -> Dict[str, Any]:
5763
"""Process an AI query with authentication and rate limiting.
58-
64+
5965
Args:
6066
query: The query to process
6167
context: Optional context data
6268
session_id: Optional session ID for authentication
6369
identifier: Rate limit identifier
64-
70+
6571
Returns:
6672
Dictionary containing the response and metadata
67-
73+
6874
Raises:
6975
PermissionError: If authentication fails
7076
"""
7177
# SECURITY: Validate input
7278
if not isinstance(query, str) or not query.strip():
7379
raise ValueError("Query must be a non-empty string")
74-
80+
7581
# SECURITY: Limit query length to prevent abuse
7682
if len(query) > 5000:
7783
raise ValueError("Query too long (max 5000 characters)")
78-
84+
7985
# SECURITY: Sanitize query for logging
8086
safe_query = SecurityValidator.sanitize_log_input(query[:100])
8187
self.logger.info("Processing AI query: %s...", safe_query)
82-
88+
8389
# SECURITY: Check authentication if session_id provided
8490
if session_id:
8591
auth_manager = get_auth_manager()
8692
auth_manager.require_permission(session_id, Permission.AI_QUERY)
87-
93+
8894
try:
8995
# Prepare context
9096
context_str = ""
@@ -93,7 +99,7 @@ async def process_query(self, query: str, context: Optional[Dict[str, Any]] = No
9399
if not isinstance(context, dict):
94100
raise ValueError("Context must be a dictionary")
95101
context_str = json.dumps(context, indent=2)
96-
102+
97103
# Create prompt
98104
prompt = f"""You are a security expert. Please provide guidance on the following query:
99105
@@ -110,20 +116,20 @@ async def process_query(self, query: str, context: Optional[Dict[str, Any]] = No
110116
5. Safety considerations
111117
112118
Provide a detailed response:"""
113-
119+
114120
# Get AI response
115121
response = await self._get_ai_response(prompt)
116-
122+
117123
# Log response
118124
self.logger.info("AI response received")
119-
125+
120126
return {
121127
"answer": response,
122128
# Return an empty log list as the logger doesn't expose in-memory logs
123129
"logs": [],
124-
"prompt": prompt
130+
"prompt": prompt,
125131
}
126-
132+
127133
except ValueError as e:
128134
# SECURITY: Don't expose internal errors
129135
self.logger.error("Validation error: %s", str(e))
@@ -135,52 +141,71 @@ async def process_query(self, query: str, context: Optional[Dict[str, Any]] = No
135141

136142
async def execute_intent(self, intent: Dict[str, Any]) -> Dict[str, Any]:
137143
"""Execute a structured action intent from the Agentic AI.
138-
144+
139145
Args:
140146
intent: The structured intent JSON.
141-
147+
142148
Returns:
143149
Result of the execution.
144150
"""
145-
self.logger.info("Executing intent: %s on %s", intent.get("type"), intent.get("target"))
146-
151+
self.logger.info(
152+
"Executing intent: %s on %s", intent.get("type"), intent.get("target")
153+
)
154+
147155
action_type = intent.get("type")
148156
target = intent.get("target")
149157
value = intent.get("value")
150-
158+
151159
try:
152160
if action_type == "module_call":
153161
if target == "recon_scan":
154162
# Placeholder for recon trigger logic
155-
return {"status": "success", "message": f"Triggered recon scan on {value}"}
163+
return {
164+
"status": "success",
165+
"message": f"Triggered recon scan on {value}",
166+
}
156167
elif target == "robin_search":
157-
return {"status": "success", "message": f"Triggered Robin search for {value}"}
158-
168+
return {
169+
"status": "success",
170+
"message": f"Triggered Robin search for {value}",
171+
}
172+
159173
elif action_type == "tool_call":
160174
if target == "install_tool":
161-
return {"status": "info", "message": f"Suggested installation of tool: {value}"}
162-
175+
return {
176+
"status": "info",
177+
"message": f"Suggested installation of tool: {value}",
178+
}
179+
163180
elif action_type == "ui_click":
164181
return {"status": "ui_intent", "action": "navigate", "tab": target}
165-
182+
166183
elif action_type == "ui_input":
167-
return {"status": "ui_intent", "action": "fill", "element": target, "value": value}
168-
169-
return {"status": "error", "message": f"Unknown intent type or target: {action_type}/{target}"}
170-
184+
return {
185+
"status": "ui_intent",
186+
"action": "fill",
187+
"element": target,
188+
"value": value,
189+
}
190+
191+
return {
192+
"status": "error",
193+
"message": f"Unknown intent type or target: {action_type}/{target}",
194+
}
195+
171196
except Exception as e:
172197
self.logger.error(f"Intent execution failed: {e}")
173198
return {"status": "error", "message": str(e)}
174199

175200
async def _get_ai_response(self, prompt: str) -> str:
176201
"""Get response from AI model with timeout.
177-
202+
178203
Args:
179204
prompt: The prompt to send to the AI
180-
205+
181206
Returns:
182207
The AI's response
183-
208+
184209
Raises:
185210
TimeoutError: If request times out
186211
"""
@@ -190,7 +215,7 @@ async def _get_ai_response(self, prompt: str) -> str:
190215
# TODO: Implement actual AI model call
191216
# For now, return a placeholder response
192217
return "This is a placeholder response. AI integration pending."
193-
218+
194219
except asyncio.TimeoutError:
195220
self.logger.error("AI request timed out")
196221
raise TimeoutError("AI request timed out after 300 seconds")
@@ -200,75 +225,82 @@ async def _get_ai_response(self, prompt: str) -> str:
200225

201226
def _generate_report(self) -> Dict[str, str]:
202227
"""Generate reports for the current session.
203-
228+
204229
Returns:
205230
Dictionary mapping report types to their file paths
206231
"""
207232
self.logger.info("Generating reports in %s format...", self.output_format)
208-
233+
209234
try:
210235
# Prepare context data
211236
context = {
212237
"target": {
213238
"domain": self.session_data.get("target_domain"),
214239
"ip": self.session_data.get("target_ip"),
215240
"scan_time": self.session_data.get("start_time"),
216-
"duration": self._calculate_duration()
241+
"duration": self._calculate_duration(),
217242
},
218243
"modules": self.session_data["modules"],
219244
"tools": self.session_data["tools"],
220245
"vulnerabilities": self.session_data.get("findings", []),
221246
"exploits": self.session_data.get("execution_history", []),
222247
"defensive_measures": self.session_data.get("defensive_measures", []),
223248
"recommendations": self.session_data.get("recommendations", []),
224-
"errors": self.session_data["errors"]
249+
"errors": self.session_data["errors"],
225250
}
226-
251+
227252
# Generate reports
228-
report_paths = self.report_generator.generate_reports(context, self.output_format)
229-
253+
report_paths = self.report_generator.generate_reports(
254+
context, self.output_format
255+
)
256+
230257
self.logger.info("Reports generated successfully")
231258
return report_paths
232-
259+
233260
except Exception as e:
234261
self.logger.error("Error generating reports: %s", str(e))
235262
raise
236263

237264
def _calculate_duration(self) -> str:
238265
"""Calculate session duration.
239-
266+
240267
Returns:
241268
Formatted duration string
242269
"""
243270
start_time = datetime.fromisoformat(self.session_data["start_time"])
244271
end_time = datetime.now()
245272
duration = end_time - start_time
246-
273+
247274
hours = duration.seconds // 3600
248275
minutes = (duration.seconds % 3600) // 60
249276
seconds = duration.seconds % 60
250-
277+
251278
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
252279

253280
def setup_ai(self) -> bool:
254281
"""Setup AI environment: check Ollama service and model availability."""
255282
try:
256-
if hasattr(self, 'ollama'):
283+
if hasattr(self, "ollama"):
257284
client = self.ollama
258285
else:
259286
from ai_integration import OllamaClient
287+
260288
client = OllamaClient()
261289
if not client.is_available():
262-
self.logger.error("Ollama service not available. Start with: ollama serve")
290+
self.logger.error(
291+
"Ollama service not available. Start with: ollama serve"
292+
)
263293
return False
264294
models = client.list_models()
265295
if not models:
266296
self.logger.info("No models found. Pulling default model...")
267297
if not client.pull_model(client.main_model):
268298
self.logger.error("Failed to pull default model")
269299
return False
270-
self.logger.info("AI setup complete. Available models: %s", [m['name'] for m in models])
300+
self.logger.info(
301+
"AI setup complete. Available models: %s", [m["name"] for m in models]
302+
)
271303
return True
272304
except Exception as e:
273305
self.logger.error("Error in setup_ai: %s", e)
274-
return False
306+
return False

0 commit comments

Comments
 (0)