Bluestrikeai's picture
Update agents.py
d4f895f verified
import json
import httpx
from typing import AsyncGenerator
from config import settings
class BaseAgent:
role: str = ""
model_key: str = ""
system_prompt: str = ""
temperature: float = 0.7
max_tokens: int = 100000
@property
def model_id(self) -> str:
return settings.MODEL_IDS[self.model_key]
@property
def model_name(self) -> str:
return settings.MODEL_NAMES[self.model_key]
async def call(
self, messages: list[dict], stream: bool = True
) -> AsyncGenerator[str, None]:
full_messages = [
{"role": "system", "content": self.system_prompt},
*messages,
]
payload = {
"model": self.model_id,
"messages": full_messages,
"temperature": self.temperature,
"max_tokens": self.max_tokens,
"stream": stream,
}
headers = {
"Authorization": f"Bearer {settings.OPENROUTER_API_KEY}",
"Content-Type": "application/json",
"HTTP-Referer": "https://huggingface.co/spaces/nexus-builder",
"X-Title": "Nexus Builder",
}
if stream:
async with httpx.AsyncClient(
timeout=httpx.Timeout(settings.STREAM_TIMEOUT, connect=30.0)
) as client:
async with client.stream(
"POST",
settings.OPENROUTER_BASE_URL,
json=payload,
headers=headers,
) as resp:
if resp.status_code != 200:
body = await resp.aread()
raise Exception(
f"OpenRouter {resp.status_code}: {body.decode()[:500]}"
)
async for line in resp.aiter_lines():
if not line.startswith("data: "):
continue
raw = line[6:]
if raw.strip() == "[DONE]":
break
try:
chunk = json.loads(raw)
tok = (
chunk.get("choices", [{}])[0]
.get("delta", {})
.get("content", "")
)
if tok:
yield tok
except (json.JSONDecodeError, KeyError, IndexError):
continue
else:
async with httpx.AsyncClient(
timeout=httpx.Timeout(settings.STREAM_TIMEOUT, connect=30.0)
) as client:
resp = await client.post(
settings.OPENROUTER_BASE_URL,
json=payload,
headers=headers,
)
if resp.status_code != 200:
raise Exception(
f"OpenRouter {resp.status_code}: {resp.text[:500]}"
)
data = resp.json()
content = data["choices"][0]["message"]["content"]
yield content
async def call_full(self, messages: list[dict]) -> str:
parts: list[str] = []
async for token in self.call(messages, stream=True):
parts.append(token)
return "".join(parts)
# ────────────────────────────────────────────────────────────
# AGENT 1 β€” Research (GLM 4.5 Air)
# ────────────────────────────────────────────────────────────
class ResearchAgent(BaseAgent):
role = "research"
model_key = "research"
temperature = 0.4
max_tokens = 100000
system_prompt = (
"You are the RESEARCH AGENT for Nexus Builder, an AI web-app generator.\n\n"
"YOUR ROLE: Given an app idea, produce a structured JSON research report.\n\n"
"Output a JSON object with these exact keys:\n"
"{\n"
' "stack_recommendation": "Frontend framework, CSS, backend, DB, hosting advice",\n'
' "schema_hints": "Database tables, columns, relationships for this app type",\n'
' "api_docs_summary": "Key API endpoints needed including PayPal, Supabase Auth",\n'
' "security_notes": "Auth flows, input validation, CORS, rate limiting, XSS, SQLI prevention",\n'
' "hosting_notes": "Firebase Hosting tips, Docker config, env var management",\n'
' "ui_patterns": "UI components, UX flows, and design patterns for this app type",\n'
' "competitor_analysis": "Brief analysis of similar apps and expected features"\n'
"}\n\n"
"RULES:\n"
"- Always respond with VALID JSON inside a ```json code block\n"
"- Be thorough but concise\n"
"- Use 2024-2025 best practices\n"
"- Prioritize: Supabase (DB/Auth), PayPal (payments), React+Tailwind (frontend), FastAPI (backend)"
)
# ────────────────────────────────────────────────────────────
# AGENT 2 β€” Orchestrator (Trinity Large Preview)
# ────────────────────────────────────────────────────────────
class OrchestratorAgent(BaseAgent):
role = "orchestrator"
model_key = "orchestrator"
temperature = 0.5
max_tokens = 100000
system_prompt = (
"You are the MASTER ORCHESTRATOR for Nexus Builder.\n\n"
"YOUR ROLE: Take a user's app description + research data and produce a MASTER BLUEPRINT.\n\n"
"Output a JSON object with this structure:\n"
"```json\n"
"{\n"
' "project_name": "my-app",\n'
' "description": "...",\n'
' "systems": {\n'
' "client_portal": {\n'
' "pages": [\n'
' {"path":"/dashboard","title":"Dashboard","components":["Sidebar","StatsCards","RecentActivity"],"description":"Main dashboard","auth_required":true}\n'
" ],\n"
' "features": ["auth","billing","settings"]\n'
" },\n"
' "public_landing": {\n'
' "pages": [{"path":"/","title":"Home","components":["Hero","Features","Pricing","CTA"],"auth_required":false}],\n'
' "features": ["hero","pricing","signup","seo"]\n'
" },\n"
' "marketing_cms": {\n'
' "pages": [{"path":"/blog","title":"Blog","components":["BlogList","PostEditor"],"auth_required":true}],\n'
' "features": ["blog_editor","email_capture"]\n'
" },\n"
' "analytics_dashboard": {\n'
' "pages": [{"path":"/analytics","title":"Analytics","components":["Charts","Metrics","UserTable"],"auth_required":true}],\n'
' "features": ["realtime_metrics","charts","revenue"]\n'
" },\n"
' "admin_panel": {\n'
' "pages": [{"path":"/admin","title":"Admin","components":["UserMgmt","Logs","Settings"],"auth_required":true}],\n'
' "features": ["user_management","moderation","logs"]\n'
" }\n"
" },\n"
' "database_schema": {\n'
' "tables": [\n'
' {"name":"profiles","columns":[{"name":"id","type":"uuid","primary":true},{"name":"email","type":"text"},{"name":"role","type":"text","default":"user"},{"name":"created_at","type":"timestamptz","default":"now()"}],"rls_policies":["Users read own profile"]}\n'
" ]\n"
" },\n"
' "api_endpoints": [\n'
' {"method":"POST","path":"/api/auth/signup","description":"Register user"},\n'
' {"method":"POST","path":"/api/payments/create-order","description":"Create PayPal order"}\n'
" ],\n"
' "auth_config": {"providers":["email","google"],"jwt_expiry":3600},\n'
' "payment_config": {"provider":"paypal","plans":[{"name":"Free","price":0,"features":["Basic"]},{"name":"Pro","price":29,"features":["All features"]}]},\n'
' "design_tokens": {\n'
' "colors":{"primary":"#6C63FF","secondary":"#00D9FF","background":"#0A0A0F","surface":"#111118","text":"#F0F0FF"},\n'
' "fonts":{"heading":"Inter","body":"Inter","mono":"JetBrains Mono"}\n'
" }\n"
"}\n"
"```\n\n"
"RULES:\n"
"- Every page MUST have specific components listed\n"
"- Every table MUST have complete column definitions\n"
"- Include PayPal integration in billing pages\n"
"- Include Supabase Auth in all auth flows\n"
"- Customize EVERYTHING for the user's specific app idea\n"
"- Response MUST be valid JSON in a ```json block"
)
# ────────────────────────────────────────────────────────────
# AGENT 3 β€” Frontend (Qwen3 Coder 480B)
# ────────────────────────────────────────────────────────────
class FrontendAgent(BaseAgent):
role = "frontend"
model_key = "frontend"
temperature = 0.6
max_tokens = 100000
system_prompt = (
"You are the FRONTEND CODE GENERATION AGENT for Nexus Builder.\n\n"
"TECH STACK: React 18, Tailwind CSS, React Router v6, Supabase JS, "
"@paypal/react-paypal-js, Recharts, Lucide React icons.\n\n"
"DESIGN SYSTEM:\n"
"Dark: bg #0A0A0F, surface #111118, border #1E1E2E, accent #6C63FF, "
"cyan #00D9FF, text #F0F0FF, muted #8888AA, success #22D3A8, error #FF4D6D\n"
"Light: bg #F8F8FC, surface #FFFFFF, border #E0E0EF, accent #5B53E8\n\n"
"RULES:\n"
"1. Generate COMPLETE files β€” NO placeholders, NO truncation, NO '...rest'\n"
"2. Every component must be fully functional with state management\n"
"3. Mobile-first responsive design with Tailwind\n"
"4. Dark/light mode via CSS variables\n"
"5. Smooth animations and transitions\n"
"6. Accessible markup (ARIA labels, semantic HTML)\n"
"7. Error boundaries and loading states\n\n"
"OUTPUT FORMAT β€” Mark each file clearly:\n"
"// FILE: system_name/src/ComponentName.jsx\n"
"[complete file content]\n\n"
"// FILE: system_name/src/App.jsx\n"
"[complete file content]\n\n"
"Generate ALL files for the requested system. Include pages, components, "
"routing, Supabase client, theme provider, package.json, tailwind config, "
"index.html, and CSS. Make it look PREMIUM β€” glass morphism, gradients, micro-animations."
)
# ────────────────────────────────────────────────────────────
# AGENT 4 β€” Backend (MiniMax M2.5)
# ────────────────────────────────────────────────────────────
class BackendAgent(BaseAgent):
role = "backend"
model_key = "backend"
temperature = 0.4
max_tokens = 100000
system_prompt = (
"You are the BACKEND, SECURITY, DATABASE & DEVOPS AGENT for Nexus Builder.\n\n"
"TECH STACK: Python FastAPI, Supabase (PostgreSQL + Auth + Realtime + Edge Functions), "
"PayPal REST API v2, Docker, Firebase Hosting.\n\n"
"YOUR OUTPUTS:\n"
"1. Supabase SQL Schema β€” CREATE TABLE, RLS policies, triggers, indexes\n"
"2. FastAPI backend β€” routes, auth middleware, PayPal integration, rate limiting, CORS\n"
"3. Supabase Edge Functions (TypeScript) β€” webhooks, emails\n"
"4. Security β€” input validation, SQL injection prevention, XSS headers\n"
"5. DevOps β€” Dockerfile, docker-compose.yml, .env.example, firebase.json, DEPLOY.md\n\n"
"RULES:\n"
"1. Generate COMPLETE files β€” NO placeholders or truncation\n"
"2. All SQL must be valid PostgreSQL\n"
"3. All Python must be valid, typed, and async\n"
"4. Never expose secrets β€” always use environment variables\n"
"5. Comprehensive error handling everywhere\n\n"
"OUTPUT FORMAT β€” Mark each file:\n"
"# FILE: backend/main.py\n"
"[complete content]\n\n"
"-- FILE: database/schema.sql\n"
"[complete SQL]\n\n"
"# FILE: deploy/Dockerfile\n"
"[complete content]"
)