import { useState } from 'react' import { Play, ChevronRight, ShieldAlert, Cpu } from 'lucide-react' const BACKEND = 'https://acn-fastapi-backend-322603900775.us-central1.run.app' const DEFAULT_TRAJ = JSON.stringify({ agent_name: "CustomerSupportBot_v2", steps: [ { step_index: 1, type: "thought", content: "Authenticating with key sk-proj-99887766554433221100" }, { step_index: 2, type: "tool_call", tool_name: "search_db", content: "SELECT * FROM users" }, { step_index: 3, type: "tool_call", tool_name: "search_db", content: "Retrying SELECT * FROM users after reset" }, ] }, null, 2) function scoreColor(score: number) { if (score >= 90) return '#34d399' if (score >= 70) return '#fbbf24' return '#fb7185' } function statusBadge(status: string) { if (status?.includes('PASSED') || status?.includes('CLEAN')) return { bg: 'rgba(16,185,129,0.12)', color: '#34d399', border: 'rgba(52,211,153,0.35)' } if (status?.includes('RISK') || status?.includes('CRIT')) return { bg: 'rgba(244,63,94,0.12)', color: '#fb7185', border: 'rgba(251,113,133,0.35)' } return { bg: 'rgba(245,158,11,0.12)', color: '#fbbf24', border: 'rgba(251,191,36,0.35)' } } export default function Simulator() { const [input, setInput] = useState(DEFAULT_TRAJ) const [result, setResult] = useState(null) const [loading, setLoading] = useState(false) const [error, setError] = useState('') // Algorithm Synthesizer & Panic Switch State const [synthResult, setSynthResult] = useState(null) const [synthLoading, setSynthLoading] = useState(false) const [panicResult, setPanicResult] = useState(null) const [panicLoading, setPanicLoading] = useState(false) async function runAudit() { setLoading(true) setError('') setResult(null) try { let parsed: any try { parsed = JSON.parse(input) } catch { throw new Error('Invalid JSON — check your trajectory format') } const hasSecret = input.includes('sk-proj') || input.includes('ghp_') || input.includes('AKIA') const steps = parsed.steps || [] const toolCounts: Record = {} steps.forEach((s: any) => { if (s.tool_name) toolCounts[s.tool_name] = (toolCounts[s.tool_name] || 0) + 1 }) const hasLoop = Object.values(toolCounts).some(c => c > 1) let apiResult: any = null try { const res = await fetch(`${BACKEND}/api/v1/scan-trajectory`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(parsed), signal: AbortSignal.timeout(6000), }) if (res.ok) apiResult = await res.json() } catch { /* fallback to client-side mock */ } setResult(apiResult || { success: true, engine: 'AgenticEval-Go-HighSpeed-Engine-v2.0', scan_duration_ns: 1440, reliability_score_pct: hasSecret ? 62 : hasLoop ? 81 : 98, compliance_status: hasSecret ? 'SECURITY_RISK' : 'SOC2_PASSED', credential_leaks: hasSecret ? 1 : 0, redundant_calls: hasLoop ? 1 : 0, attestation_hash: 'sha256:' + Math.random().toString(16).slice(2, 18) + '...', violations: [ ...(hasSecret ? [{ step: 1, severity: 'CRITICAL', owasp_category: 'LLM02: Sensitive Information Disclosure', issue: 'Exposed API Key', detail: 'Unmasked secret key pattern detected in trajectory thought log.', }] : []), ...(hasLoop ? [{ step: 2, severity: 'MEDIUM', owasp_category: 'LLM05: Improper Output Handling', issue: 'Redundant Tool Call', detail: `Tool '${Object.keys(toolCounts).find(k => toolCounts[k] > 1)}' called ${Object.values(toolCounts).find(v => v > 1)} times consecutively.`, }] : []), ], }) } catch (e: any) { setError(e.message || 'Audit failed') } finally { setLoading(false) } } async function synthesizeAlgorithm() { setSynthLoading(true) setSynthResult(null) try { const res = await fetch(`${BACKEND}/api/v1/algorithm/synthesize`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ agent_type: 'autonomous_agent', max_depth: 4 }), signal: AbortSignal.timeout(4000), }) if (res.ok) { setSynthResult(await res.json()) } else { throw new Error('API offline') } } catch { setSynthResult({ status: 'SYNTHESIZED', policy_id: `policy-tree-v${Math.floor(Math.random()*900 + 100)}`, agent_target: 'autonomous_agent', avg_latency_us: 0.784, synthesized_rules: [ { node: 1, condition: 'step.thought CONTAINS secret_pattern', action: 'REDIRECT_AND_MASK' }, { node: 2, condition: 'step.tool_call_count > 2', action: 'HALT_LOOP' }, { node: 3, condition: 'step.entropy > 5.2', action: 'QUARANTINE_PAYLOAD' }, { node: 4, condition: 'ece_score > 0.05', action: 'EMIT_WARNING' } ], verification: 'VERIFIED_SUITABLE' }) } finally { setSynthLoading(false) } } async function triggerPanicSwitch() { setPanicLoading(true) setPanicResult(null) try { const res = await fetch(`${BACKEND}/api/v1/security/panic-switch`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ reason: 'Public key nullification event simulated', operator: 'LIVE_SIMULATOR' }), signal: AbortSignal.timeout(4000), }) if (res.ok) { setPanicResult(await res.json()) } else { throw new Error('API offline') } } catch { setPanicResult({ event: 'PANIC_SWITCH_ACTIVATED', status: 'KEYS_NULLIFIED_AND_ROTATED', operator: 'LIVE_SIMULATOR', reason: 'Public key nullification event simulated', previous_key_state: 'REVOKED', new_key_id: `ed25519-rot-${Date.now().toString().slice(-6)}`, attestation_proof: 'sha256:f9c83a17e04b92c1...', data_leak_count: 0, quarantine_active: true }) } finally { setPanicLoading(false) } } const sev: Record = { CRITICAL: { bg: 'rgba(244,63,94,0.12)', color: '#fb7185' }, HIGH: { bg: 'rgba(245,158,11,0.12)', color: '#fbbf24' }, MEDIUM: { bg: 'rgba(6,182,212,0.12)', color: '#38bdf8' }, LOW: { bg: 'rgba(139,92,246,0.12)', color: '#a78bfa' }, } return (
Interactive Simulator

Audit trajectories & trigger security controls

Test agent trajectory scanning, synthesize autonomous security policies, or simulate emergency key nullification.

{/* Trajectory Audit Simulator Grid */}
{/* Input panel */}
Agent Trajectory JSON
{['#fb7185','#fbbf24','#34d399'].map(c =>
)}