mirror of
https://github.com/CyberSecurityUP/NeuroSploit.git
synced 2026-06-30 07:15:30 +02:00
a5badefc29
Engine:
- Fix: inject IS_SANDBOX=1 so Claude Code's --dangerously-skip-permissions
works under root (real backend runs were exiting rc=1 immediately)
- models: expand to 40 models / 13 providers, tagged CLI vs API
(NVIDIA NIM, DeepSeek, Mistral, Qwen/DashScope, Groq, Together, OpenRouter,
Ollama, Gemini) — Qwen/DeepSeek/Llama usable via API
- backends: on_start callback surfaces the exact argv ("what runs behind it")
- orchestrator: require a Playwright screenshot per confirmed finding; collect
results/activity.json; auto-generate reports after a run
- report.py: HTML always + PDF via Typst engine (.typ source emitted too)
Web dashboard (webgui/, stdlib only — no npm/build):
- Sidebar dashboard (PentAGI-style): Run / Agents / Insights / Reports / Settings
- Multi-target runs; live execution console + per-task activity; finding cards
with screenshots; backend+provider+model pickers (CLI & API)
- Agents tab: browse 213 + add new .md agents from the UI
- Insights: interactive RL-weight + severity charts
- Reports: download/preview PDF + HTML
- Settings/API: execution mode, per-provider API keys, orchestrator, verbosity
- Endpoints: /api/agents (GET/POST), /api/rl, /api/config, /api/reports,
/reports/* + /shots/* static serving
Cleanup: retire replaced web stack (frontend React, FastAPI backend, core
orchestration, old test) to legacy/. Active engine + GUI are fully standalone.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
82 lines
3.0 KiB
Python
Executable File
82 lines
3.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Model Router - Task-type-based LLM routing.
|
|
|
|
Routes requests to different LLM profiles based on task type:
|
|
- reasoning: Complex logic and decision-making
|
|
- analysis: Data analysis and pattern recognition
|
|
- generation: Content and payload generation
|
|
- validation: Result verification and confirmation
|
|
|
|
Enabled/disabled via config. When disabled, callers fall back to their default provider.
|
|
"""
|
|
|
|
import os
|
|
import logging
|
|
from typing import Dict, Optional, Callable
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ModelRouter:
|
|
"""Routes LLM requests to different profiles based on task type."""
|
|
|
|
def __init__(self, config: Dict, llm_manager_factory: Callable):
|
|
"""
|
|
Args:
|
|
config: Full application config dict (must contain 'model_routing' and 'llm' keys)
|
|
llm_manager_factory: Callable that takes a profile name and returns an LLMManager instance
|
|
"""
|
|
routing_config = config.get('model_routing', {})
|
|
self.enabled = routing_config.get('enabled', False)
|
|
|
|
# Allow env var override
|
|
env_override = os.getenv('ENABLE_MODEL_ROUTING', '').strip().lower()
|
|
if env_override == 'true':
|
|
self.enabled = True
|
|
elif env_override == 'false':
|
|
self.enabled = False
|
|
|
|
self.routes = routing_config.get('routes', {})
|
|
self.llm_manager_factory = llm_manager_factory
|
|
self._managers = {} # Cache LLMManager instances per profile
|
|
|
|
if self.enabled:
|
|
logger.info(f"Model routing enabled with routes: {list(self.routes.keys())}")
|
|
else:
|
|
logger.debug("Model routing disabled")
|
|
|
|
def generate(self, prompt: str, system_prompt: Optional[str] = None,
|
|
task_type: str = "default") -> Optional[str]:
|
|
"""Route a generation request to the appropriate LLM profile.
|
|
|
|
Returns None if routing is disabled or no route matches,
|
|
allowing callers to fall back to their default provider.
|
|
"""
|
|
if not self.enabled:
|
|
return None
|
|
|
|
profile = self.routes.get(task_type, self.routes.get('default'))
|
|
if not profile:
|
|
logger.debug(f"No route for task_type '{task_type}', falling back to default")
|
|
return None
|
|
|
|
try:
|
|
if profile not in self._managers:
|
|
self._managers[profile] = self.llm_manager_factory(profile)
|
|
|
|
manager = self._managers[profile]
|
|
logger.debug(f"Routing task_type '{task_type}' to profile '{profile}' "
|
|
f"(provider: {manager.provider}, model: {manager.model})")
|
|
return manager.generate(prompt, system_prompt)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Model routing error for profile '{profile}': {e}")
|
|
return None
|
|
|
|
def get_profile_for_task(self, task_type: str) -> Optional[str]:
|
|
"""Get the profile name that would handle a given task type."""
|
|
if not self.enabled:
|
|
return None
|
|
return self.routes.get(task_type, self.routes.get('default'))
|