added cli installer ]

This commit is contained in:
rarebuffalo
2026-05-15 12:54:58 +05:30
parent 61797fbb97
commit 542f607f25
13 changed files with 2050 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
"""
AI Client
=========
Thin, model-agnostic wrapper around LiteLLM.
The CLI uses this instead of directly calling litellm
so we have one place to handle retries, logging, and key injection.
"""
import json
import asyncio
import logging
from typing import Optional
logger = logging.getLogger(__name__)
async def call_ai(
prompt: str,
api_key: str,
model: str,
temperature: float = 0.3,
json_mode: bool = False,
conversation_history: Optional[list] = None,
) -> str:
"""
Single entry-point for all AI calls in the CLI.
Parameters
----------
prompt : The prompt to send (added as last user message)
api_key : LiteLLM-compatible API key
model : LiteLLM model string (e.g. "gemini/gemini-2.0-flash")
temperature : Creativity (0=deterministic, 1=creative)
json_mode : Ask the model to respond with valid JSON only
conversation_history : Optional list of {"role": ..., "content": ...} dicts
for multi-turn chat sessions
"""
import litellm
litellm.suppress_debug_info = True
messages = list(conversation_history or [])
messages.append({"role": "user", "content": prompt})
kwargs: dict = {
"model": model,
"messages": messages,
"temperature": temperature,
"api_key": api_key if api_key else None,
}
if json_mode:
kwargs["response_format"] = {"type": "json_object"}
try:
response = await litellm.acompletion(**kwargs)
return response.choices[0].message.content or ""
except Exception as e:
logger.error(f"AI call failed [{model}]: {e}")
return ""
async def call_ai_json(
prompt: str,
api_key: str,
model: str,
temperature: float = 0.2,
) -> Optional[dict]:
"""Convenience wrapper — calls AI in JSON mode and parses the result."""
raw = await call_ai(prompt, api_key, model, temperature=temperature, json_mode=True)
if not raw:
return None
try:
return json.loads(raw)
except json.JSONDecodeError as e:
logger.error(f"JSON parse failed: {e}\nRaw: {raw[:300]}")
return None

View File

@@ -0,0 +1,76 @@
"""
All AI prompts for the CLI agent — kept in one place so they're easy to tune.
"""
def triage_prompt(file_list: str, max_files: int) -> str:
return (
"You are a Senior Application Security Engineer. "
"I have a local codebase with the following files:\n"
f"{file_list}\n\n"
f"Select the {max_files} most critical files to review for security vulnerabilities. "
"Focus on: authentication logic, database access, API routes, config files, "
"secret/credential handling, input validation, and file upload handlers.\n"
"Also prioritise any file that contains the words: secret, password, token, key, "
"auth, login, admin, cred, jwt, session, crypto, hash.\n"
"Return a JSON object with a single key 'critical_files' containing the list of "
"exact file paths. Do not select more than "
f"{max_files} files."
)
def analysis_prompt(file_path: str, content: str) -> str:
return (
f"Review the following code from '{file_path}' for security vulnerabilities.\n"
"Focus on OWASP Top 10:\n"
" A01 Broken Access Control, A02 Cryptographic Failures, A03 Injection,\n"
" A04 Insecure Design, A05 Security Misconfiguration, A06 Vulnerable Components,\n"
" A07 Auth Failures, A08 Integrity Failures, A09 Logging Failures, A10 SSRF.\n"
"Also check for: hardcoded secrets/API keys, debug flags left on, insecure defaults.\n\n"
f"CODE:\n{content}\n\n"
"Return a JSON object with key 'vulnerabilities' — a list of objects, each with:\n"
" 'severity' : Critical | High | Medium | Low\n"
" 'issue' : Short title of the vulnerability\n"
" 'explanation' : 1-2 sentences explaining the risk\n"
" 'suggested_fix' : Concrete code snippet or clear instruction to fix it\n"
" 'line_number' : Integer line number, or null if not applicable\n"
"If no vulnerabilities are found, return {\"vulnerabilities\": []}."
)
def summary_prompt(target: str, issues_json: str) -> str:
return (
"You are a Senior AppSec Manager writing an executive security report.\n"
f"Target: {target}\n\n"
"Here are all vulnerabilities found in the automated scan:\n"
f"{issues_json}\n\n"
"Write a 2-3 paragraph executive summary of the overall security posture. "
"Highlight the most critical risks, explain what an attacker could do with them, "
"and recommend the top 3 immediate priorities. "
"Keep it professional, direct, and actionable — avoid generic fluff."
)
def chat_prompt(target: str, scan_context: str, user_question: str) -> str:
return (
"You are SecureLens AI, an expert cybersecurity assistant embedded in a CLI tool.\n"
f"The developer just scanned: {target}\n\n"
"Here are the full scan results:\n"
f"{scan_context}\n\n"
f"Developer's question: {user_question}\n\n"
"Answer clearly and practically. Reference specific findings from the scan when relevant. "
"If asked about a fix, show concrete code where possible."
)
def web_summary_prompt(url: str, issues_json: str, score: int, grade: str) -> str:
return (
"You are SecureLens AI, a web security expert.\n"
f"I just ran a security scan on: {url}\n"
f"Overall score: {score}/100 Grade: {grade}\n\n"
"Issues found:\n"
f"{issues_json}\n\n"
"Write a concise 2-paragraph summary: first explain what the key risks are and how "
"an attacker could exploit them; second, give the top 3 most impactful fixes. "
"Be direct — the reader is a developer, not a manager."
)