const { useState, useEffect, useRef, useMemo } = React; const BFF = window.BFF_URL || ""; // Locked fallback scores — never change const FALLBACK = { alice: { score: 0.2641, verdict: "rejected", mode: "Direct" }, bob: { score: 0.6703, verdict: "approved", mode: "Workflow" }, carol: { score: 0.0000, verdict: "blocked", mode: "Web3" }, }; const AGENTS_META = [ { id: "alice", name: "Agent Alice", role: "MEV Sandwich Bot", initials: "AL", address: "0xa11cea1a11cea1a11cea1a11cea1a11cea1a11ce" }, { id: "bob", name: "Agent Bob", role: "Honest Arb Agent", initials: "BO", address: "0xb0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0" }, { id: "carol", name: "Agent Carol", role: "Unverified New Agent", initials: "CA", address: "0xca401ca401ca401ca401ca401ca401ca401ca401" }, ]; function verdictFor(score) { if (score >= 0.5) return "approved"; if (score >= 0.1) return "rejected"; return "blocked"; } // ---------- Animated number ---------- function useAnimatedNumber(target, duration = 900) { const [v, setV] = useState(0); const raf = useRef(); const start = useRef(null); const from = useRef(0); useEffect(() => { cancelAnimationFrame(raf.current); from.current = v; start.current = null; const step = (t) => { if (start.current == null) start.current = t; const p = Math.min(1, (t - start.current) / duration); const eased = 1 - Math.pow(1 - p, 3); setV(from.current + (target - from.current) * eased); if (p < 1) raf.current = requestAnimationFrame(step); }; raf.current = requestAnimationFrame(step); return () => cancelAnimationFrame(raf.current); }, [target]); return v; } // ---------- Sparkline ---------- function Sparkline({ seed = 1, color = "#8b96a5", trend = 0 }) { const pts = useMemo(() => { const n = 32; let rng = seed * 9301 + 49297; const rand = () => { rng = (rng * 9301 + 49297) % 233280; return rng / 233280; }; const arr = []; let y = 0.5; for (let i = 0; i < n; i++) { y += (rand() - 0.5) * 0.25 + trend * 0.01; y = Math.max(0.05, Math.min(0.95, y)); arr.push(y); } return arr; }, [seed, trend]); const w = 280, h = 36; const path = pts.map((p, i) => { const x = (i / (pts.length - 1)) * w; const y = h - p * h; return `${i === 0 ? "M" : "L"}${x.toFixed(1)},${y.toFixed(1)}`; }).join(" "); const area = path + ` L${w},${h} L0,${h} Z`; return ( ); } // ---------- Agent Card ---------- function AgentCard({ meta, data, selected, onSelect }) { const score = data?.score ?? FALLBACK[meta.id].score; const verdict = data?.verdict ?? verdictFor(score); const mode = (data?.mode ?? FALLBACK[meta.id].mode).toLowerCase(); const isAdversarial = meta.id === "carol"; const val = useAnimatedNumber(score); const pct = Math.round(val * 100); const barCls = verdict === "approved" ? "green" : verdict === "rejected" ? "red" : "gray"; const sparkColor = verdict === "approved" ? "#00c851" : verdict === "rejected" ? "#ff4444" : "#5b6675"; const trend = verdict === "approved" ? 0.8 : verdict === "rejected" ? -0.6 : 0; return (
{isAdversarial && (
⚠️ ADVERSARIAL AGENT DETECTED
)}
{meta.name}
{meta.role}
{meta.initials}
Merit Score
{val.toFixed(4)} / 1.0000
{pct}% confidence {verdict === "blocked" ? "—" : `ppl ${(val * 1000 | 0)}`}
{verdict.toUpperCase()} {mode.charAt(0).toUpperCase() + mode.slice(1)}
); } // ---------- TEE Tab ---------- function TEETab({ attestation }) { const [copied, setCopied] = useState(null); const rows = [ { key: "compute", label: "Compute Hash", val: attestation?.compute_hash || "0x7f3a9b2c1e4d8f6a3c2b1e9d5f0a4c8e" }, { key: "storage", label: "Storage Root", val: attestation?.storage_root || "0x4e8c1a7b3f2d9e5c8a16fd0c2e7b94a1" }, { key: "oracle", label: "Oracle Commit", val: attestation?.oracle_commit || "0x09d34df4fd5c9c75b9970e4fbe0820c2" }, ]; const modeLabel = attestation?.mode || "Workflow"; const doCopy = (key, val) => { navigator.clipboard?.writeText(val).catch(() => {}); setCopied(key); setTimeout(() => setCopied(null), 1200); }; return (
{rows.map((r) => (
{r.label} ● Verified
0x{r.val.slice(2, 22)} …{r.val.slice(-6)}
))}
Verified by 0G Compute TeeML · Evidence anchored on 0G Galileo
{modeLabel.toUpperCase()}
{/* Transparency badges row */}
{/* Provider badge */} Provider: {(attestation?.provider || "unknown").length > 14 ? (attestation?.provider || "unknown").slice(0, 12) + "…" : attestation?.provider || "unknown"} {/* Compute badge */} Compute: {attestation?.compute_ok ? "✓" : "✗"} {/* Storage badge */} Storage: {attestation?.storage_ok ? "✓" : "✗"} {/* Fallback badge - only render if fallback_reason is non-null/non-empty */} {attestation?.fallback_reason && ( Fallback: {attestation.fallback_reason} )}
); } // ---------- Workflow Tab ---------- function WorkflowTab({ agentMeta }) { const [addr, setAddr] = useState(agentMeta?.address || ""); const [threshold, setThreshold] = useState(6500); const [running, setRunning] = useState(false); const [step, setStep] = useState(-1); const [result, setResult] = useState(null); const [log, setLog] = useState([]); useEffect(() => { setAddr(agentMeta?.address || ""); }, [agentMeta?.id]); const pushLog = (line, cls = "") => { const ts = new Date().toLocaleTimeString("en-GB", { hour12: false }); setLog((l) => [...l.slice(-40), { ts, line, cls }]); }; const run = async () => { if (running) return; setRunning(true); setResult(null); setStep(0); setLog([]); pushLog(`→ Dispatching workflow for ${addr.slice(0, 10)}…`, "info"); pushLog(` threshold = ${threshold} / 10000`, ""); try { setStep(0); const res = await fetch(`${BFF}/kh/workflow`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ address: addr, threshold }), }); const data = await res.json(); setTimeout(() => { pushLog(`${data.check ? "✓" : "✗"} CHECK — on-chain identity resolved`, data.check ? "ok" : "err"); setStep(1); }, 400); setTimeout(() => { pushLog(`${data.validate ? "✓" : "✗"} VALIDATE — TEE attestation ${data.validate ? "matched" : "failed"}`, data.validate ? "ok" : "err"); setStep(2); }, 1100); setTimeout(() => { const zk_verified = data.zk_verify?.verified || data.zk_verify?.skipped; pushLog(`${zk_verified ? "✓" : "✗"} ZK_VERIFY — Merkle proof ${data.zk_verify?.skipped ? "skipped (unknown agent)" : zk_verified ? "verified" : "failed"}`, zk_verified ? "ok" : "err"); if (data.zk_verify?.proof_hash) { pushLog(` proof: ${data.zk_verify.proof_hash} · merkle_root: ${data.zk_verify.merkle_root?.slice(0, 16)}…`, "info"); } setStep(3); }, 1550); setTimeout(() => { const approved = data.execute === "OK" || (data.check && data.validate); if (approved) { pushLog(`✓ EXECUTE — capital access granted`, "ok"); pushLog(` mode: ${data.mode || "Workflow"} · KeeperHub relay`, "info"); setResult("approved"); } else { pushLog(`⏳ EXECUTE — ${data.execute || "PENDING"} (below threshold or KH queued)`, "warn"); setResult(data.check && data.validate ? "approved" : "rejected"); } setStep(-2); setRunning(false); }, 2400); } catch (e) { pushLog(`✗ BFF unreachable: ${e.message}`, "err"); pushLog(` running in offline mode`, "warn"); setStep(-2); setResult("rejected"); setRunning(false); } }; const stepState = (i) => { if (step === -2) { if (i < 2) return "done"; return result === "approved" ? "done" : "fail"; } if (step === -1) return ""; if (step === i) return "active"; if (step > i) return "done"; return ""; }; const stepIcon = (i) => { const s = stepState(i); if (s === "done") return "✅"; if (s === "fail") return "❌"; if (s === "active") return ; return ; }; return (
setAddr(e.target.value)} spellCheck={false} />
setThreshold(parseInt(e.target.value, 10))} style={{ "--pct": `${(threshold/10000)*100}%` }} />
{threshold}
Powered by KeeperHub · CHECK → VALIDATE → ZK_VERIFY → EXECUTE
Pipeline {agentMeta?.name || "—"}
{["CHECK","VALIDATE","ZK_VERIFY","EXECUTE"].map((name, i) => ( {i > 0 &&
}
{name === "ZK_VERIFY" ? "🔐 ZK VERIFY" : name}
{stepIcon(i)}
))}
{log.length === 0 && (
[idle] awaiting dispatch…
)} {log.map((l, i) => (
[{l.ts}]{" "} {l.line}
))}
); } // ---------- Live Eval Tab (Sword #1 + #4) ---------- function LiveEvalTab() { const [addr, setAddr] = useState(""); const [running, setRunning] = useState(false); const [elapsed, setElapsed] = useState(0); const [result, setResult] = useState(null); const [phase, setPhase] = useState("idle"); // idle | running | reveal | done const timerRef = useRef(null); const startTimer = () => { const t0 = Date.now(); timerRef.current = setInterval(() => setElapsed(((Date.now() - t0) / 1000).toFixed(1)), 100); }; const stopTimer = () => { clearInterval(timerRef.current); timerRef.current = null; }; const evaluate = async () => { if (!addr.trim() || running) return; setRunning(true); setResult(null); setPhase("running"); setElapsed(0); startTimer(); try { const [meritData, analyzeData] = await Promise.all([ fetch(`${BFF}/merit/${addr.trim()}`).then(r => r.json()).catch(() => null), fetch(`${BFF}/analyze`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ address: addr.trim(), tx_history: [] }), }).then(r => r.json()).catch(() => null), ]); stopTimer(); setResult({ merit: meritData, analyze: analyzeData }); setPhase("reveal"); setTimeout(() => setPhase("done"), 1200); } catch { stopTimer(); setPhase("idle"); } finally { setRunning(false); } }; const score = result?.merit?.score ?? 0; const verdict = result?.merit?.exists === false && score === 0 ? "blocked" : verdictFor(score); const animScore = useAnimatedNumber(phase === "done" || phase === "reveal" ? score : 0, 1100); const gaming = result?.analyze?.gaming_detected; const reason = result?.analyze?.reason; const statusMsg = (s) => { const t = parseFloat(s); if (t < 1.5) return "Resolving on-chain identity…"; if (t < 3.5) return "Running AI sandwich analysis…"; if (t < 6) return "Verifying TEE attestation…"; return "Finalising merit score…"; }; return (
setAddr(e.target.value)} onKeyDown={e => e.key === "Enter" && evaluate()} disabled={running} spellCheck={false} />
{phase === "running" && (
⏱ {elapsed}s {statusMsg(elapsed)}
)} {(phase === "reveal" || phase === "done") && result && (
{verdict === "approved" ? "✅ APPROVED" : verdict === "rejected" ? "❌ REJECTED" : "⏸ BLOCKED"}
{animScore.toFixed(4)}
Merit Score
evaluated in {elapsed}s
AI Analysis SWORD #4 Gemma 4 26B · Ollama
{result.analyze ? ( <>
{gaming ? "⚠ Sandwich pattern detected" : "✓ No gaming pattern found"}
{reason &&
{reason}
}
merit_penalty: {result.analyze.merit_penalty ?? 0} · mode: {result.analyze.mode}
) : (
AI analysis unavailable
)}
)} {phase === "idle" && (
Enter any wallet address to run a live merit evaluation.
Try alice, bob, or{" "} carol for demo agents.
)}
); } // ---------- AI Sandwich Detection Tab (Sword #4) ---------- function AIAnalysisTab({ agentMeta }) { const [addr, setAddr] = useState(agentMeta?.address || agentMeta?.id || ""); const [running, setRunning] = useState(false); const [result, setResult] = useState(null); const [error, setError] = useState(null); useEffect(() => { setAddr(agentMeta?.id || agentMeta?.address || ""); }, [agentMeta?.id]); const analyze = async () => { if (!addr.trim() || running) return; setRunning(true); setResult(null); setError(null); try { const res = await fetch(`${BFF}/analyze`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ address: addr.trim(), tx_history: [] }), }); const data = await res.json(); setResult(data); } catch (e) { setError(e.message); } finally { setRunning(false); } }; const gaming = result?.gaming_detected; const adversarial = result?.adversarial_agent; return (
SWORD #4 — Gemma 4 26B via Ollama detects sandwich MEV attack patterns in agent transaction history. AI classification feeds directly into the merit oracle.
powered by Gemma 4 26B · Ollama · heuristic fallback
setAddr(e.target.value)} onKeyDown={e => e.key === "Enter" && analyze()} placeholder="alice / bob / carol — or 0x address" spellCheck={false} style={{ flex: 1, background: "#0b1218", border: "1px solid var(--border)", color: "#fff", padding: "8px 12px", borderRadius: 6, fontFamily: "inherit", fontSize: 13 }} />
{error &&
Error: {error}
} {result && (
{gaming ? "⚠️" : "✅"}
{gaming ? "SANDWICH ATTACK DETECTED" : "NO GAMING PATTERN"}
{adversarial && (
ADVERSARIAL AGENT — ground-truth confirmed
)}
{result.reason && (
{result.reason}
)}
merit_penalty: {result.merit_penalty ?? 0} mode: {result.mode} address: {result.address?.slice(0, 14)}…
How it works
1. Agent tx history fetched (or demo history used for named agents)
2. Gemma 4 26B prompt: detect frontrun/backrun sandwich pairs, same-block gas manipulation
3. If Ollama unavailable → heuristic fallback (keyword + block pattern detection)
4. Result feeds into merit_penalty applied to on-chain score
)} {!result && !running && !error && (
Try carol to see a detected sandwich attack, or bob for a clean agent.
)}
); } // ---------- MeritGuard Autonomous Agent Tab ---------- function MeritGuardTab({ agentLoopStatus }) { const status = agentLoopStatus; const running = status?.running; const lastScan = status?.last_scan ? new Date(status.last_scan + "Z").toLocaleTimeString("en-GB", { hour12: false }) : "—"; const actions = status?.actions || []; const flagged = status?.flagged || []; return (
{running ? "RUNNING" : "STOPPED"}
Scans every 60s · threshold{" "} 0.30 · last scan{" "} {lastScan}
powered by 0G Galileo · autonomous loop
{[ { label: "Agents Monitored", value: status?.agents_checked ?? 3, color: "#5ce8ff" }, { label: "Flagged (< 0.30)", value: flagged.length, color: flagged.length > 0 ? "#ff4444" : "#00c851" }, { label: "KH Actions Triggered", value: actions.length, color: "#d5deea" }, ].map(({ label, value, color }) => (
{label}
{value}
))}
{flagged.length > 0 && (
⚠ Flagged agents: {flagged.join(", ")} → KH_EXECUTE triggered
)}
Action Log — last {Math.min(actions.length, 20)} events
{actions.length === 0 ? (
No actions yet — waiting for next scan cycle…
) : ( [...actions].reverse().slice(0, 20).map((a, i) => (
{a.at ? new Date(a.at + "Z").toLocaleTimeString("en-GB", { hour12: false }) : "—"} {a.agent} score= {(a.score || 0).toFixed(4)} {a.action} {a.result?.status || (typeof a.result === "string" ? a.result : "PENDING")}
)) )}
MeritGuard autonomously monitors on-chain merit scores via{" "} MeritCore (0G Galileo) and triggers{" "} KeeperHub workflows for any agent below the risk threshold. This is fully autonomous — no human intervention required.
); } // ---------- ZK Proof Tab (Sword #5) ---------- function ZKProofTab({ agentMeta }) { const [threshold, setThreshold] = useState(5000); const [running, setRunning] = useState(false); const [result, setResult] = useState(null); const [error, setError] = useState(null); const agent = agentMeta?.id || "bob"; const generateProof = async () => { setRunning(true); setResult(null); setError(null); try { const res = await fetch(`${BFF}/zk-proof`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ agent, threshold }), }); const data = await res.json(); setResult(data); } catch (e) { setError(e.message); } finally { setRunning(false); } }; return (
SWORD #5 — Privacy-preserving merit proof: agents prove score ≥ threshold WITHOUT revealing the actual score. Cryptographic guarantee via Groth16 on BN254.
agent: {agent} threshold: setThreshold(parseInt(e.target.value) || 0)} style={{ width: 80, background: "#1a2633", border: "1px solid var(--border)", color: "#fff", padding: "4px 8px", borderRadius: 4, fontFamily: "inherit" }} />
{running && (
Building depth-8 Merkle tree → computing Groth16 witness → generating proof…
)} {error &&
Error: {error}
} {result && (
{result.success ? ( <>
✅ Proof verified on-chain ready
Public signals: merkleRoot + threshold (score stays private)
merkleRoot
{result.publicSignals?.[0]}
π_a (proof point)
{result.proof?.pi_a?.[0]?.slice(0, 40)}…
protocol
{result.proof?.protocol} · {result.proof?.curve} · gas ~{result.metadata?.verificationGas}
) : (
❌ Cannot prove: {result.reason}
)}
)}
); } // ---------- Uniswap Swap Tab (Sword #6) ---------- function UniswapSwapTab({ agentMeta }) { const [fromToken, setFromToken] = useState("WETH"); const [toToken, setToToken] = useState("USDC"); const [amount, setAmount] = useState("0.001"); const [slippage, setSlippage] = useState(2.0); const [loading, setLoading] = useState(false); const [quoteResult, setQuoteResult] = useState(null); const [executeResult, setExecuteResult] = useState(null); const [error, setError] = useState(null); const [rejectToast, setRejectToast] = useState(null); const triggerRejectToast = (merit, threshold) => { setRejectToast({ merit, threshold }); setTimeout(() => setRejectToast(null), 3500); }; const TOKENS = { WETH: "0x4200000000000000000000000000000000000006", USDC: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", }; const TOKEN_DECIMALS = { WETH: 18, USDC: 6, }; const toWei = (humanAmount, tokenSymbol) => { const decimals = TOKEN_DECIMALS[tokenSymbol] || 18; const factor = Math.pow(10, decimals); return String(Math.floor(parseFloat(humanAmount) * factor)); }; const fromWei = (weiAmount, tokenSymbol) => { const decimals = TOKEN_DECIMALS[tokenSymbol] || 18; const factor = Math.pow(10, decimals); return (parseFloat(weiAmount) / factor).toFixed(6); }; const getQuote = async () => { setLoading(true); setError(null); setQuoteResult(null); setExecuteResult(null); try { const amountInWei = toWei(amount, fromToken); const res = await fetch(`${BFF}/uniswap/swap`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ action: "quote", address: agentMeta?.id || "bob", from_token: TOKENS[fromToken], to_token: TOKENS[toToken], amount_in: amountInWei, slippage_pct: slippage, }), }); const data = await res.json(); if (!res.ok) { if (res.status === 403) { setError(`Merit ${data.merit?.toFixed(4)} below threshold ${data.threshold} — swap blocked`); triggerRejectToast(data.merit, data.threshold); } else if (res.status === 400) { setError(data.detail || "Validation error"); } else { setError(data.error || "Quote failed"); } setLoading(false); return; } setQuoteResult(data); } catch (e) { setError(e.message); } finally { setLoading(false); } }; const executeSwap = async () => { setLoading(true); setError(null); setExecuteResult(null); try { const amountInWei = toWei(amount, fromToken); const res = await fetch(`${BFF}/uniswap/swap`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ action: "execute", address: agentMeta?.id || "bob", from_token: TOKENS[fromToken], to_token: TOKENS[toToken], amount_in: amountInWei, slippage_pct: slippage, }), }); const data = await res.json(); if (!res.ok) { if (res.status === 403) { setError(`Merit ${data.merit?.toFixed(4)} below threshold ${data.threshold} — swap blocked`); triggerRejectToast(data.merit, data.threshold); } else if (res.status === 502) { setError(`Swap reverted on-chain: ${data.reason}`); } else if (res.status === 400) { setError(data.detail || "Validation error"); } else { setError(data.error || "Execution failed"); } setLoading(false); return; } setExecuteResult(data); } catch (e) { setError(e.message); } finally { setLoading(false); } }; return (
{rejectToast && (
403 REJECTED
merit {rejectToast.merit?.toFixed(4)} < {rejectToast.threshold} threshold
BELOW THRESHOLD · NO EXCEPTIONS
)}
SWORD #6 — Merit-gated Uniswap V3 swap on Base Sepolia. Agents with merit ≥ 0.5 can execute swaps with gas-free quote pricing and configurable slippage.
{error && (
⚠ {error}
)}
setAmount(e.target.value)} step="0.0001" min="0" style={{ width: "100%", background: "#0b1117", border: "1px solid var(--border)", color: "#fff", padding: "10px 12px", borderRadius: 6, fontFamily: "inherit", fontSize: 13, }} placeholder="0.001" />
setSlippage(Math.min(5, Math.max(0, parseFloat(e.target.value))))} step="0.1" min="0" max="5" style={{ width: "100%", background: "#0b1117", border: "1px solid var(--border)", color: "#fff", padding: "10px 12px", borderRadius: 6, fontFamily: "inherit", fontSize: 13, }} placeholder="2.0" />
{quoteResult && !executeResult && (
✓ Quote Retrieved
Amount Out
{fromWei(quoteResult.amount_out, toToken)} {toToken}
Price Impact
{quoteResult.price_impact_pct.toFixed(2)}%
Pool Fee
{(quoteResult.fee_tier / 10000 * 100).toFixed(2)}%
)} {executeResult && (
✅ Swap Confirmed
Block Number
{executeResult.block_number}
Amount Out
{fromWei(executeResult.amount_out, toToken)} {toToken}
)} {!quoteResult && !executeResult && !error && (
Enter swap parameters and click "Get Quote" to see the price impact and execute the swap.
)}
); } // ---------- App ---------- // ---------- Swarm Consensus Tab (0G Track 2) ---------- function SwarmTab({ agentMeta }) { const [loading, setLoading] = useState(false); const [result, setResult] = useState(null); const [error, setError] = useState(null); const [agentList, setAgentList] = useState([]); const [threshold, setThreshold] = useState(5000); useEffect(() => { fetch(`${BFF}/swarm/agents`) .then(r => r.json()) .then(d => setAgentList(d.agents || [])) .catch(e => setError(`Swarm agents unavailable: ${e.message}`)); }, []); const runSwarm = async () => { setLoading(true); setError(null); setResult(null); try { const res = await fetch(`${BFF}/swarm/evaluate`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ address: agentMeta?.id || "bob", threshold }), }); if (!res.ok) throw new Error(`HTTP ${res.status}`); setResult(await res.json()); } catch (e) { setError(e.message); } finally { setLoading(false); } }; const VERDICT_COLOR = { APPROVE: "#00c851", REJECT: "#ff4444", ABSTAIN: "#ffaa00" }; const VERDICT_ICON = { APPROVE: "✅", REJECT: "❌", ABSTAIN: "⚠️" }; return (
4 autonomous validator agents evaluate {agentMeta?.id || "bob"} in parallel and reach weighted consensus.
{agentList.length > 0 && (
{agentList.map(a => ( {a.healthy ? "●" : "○"} {a.agent_id} ))}
)}
{ setThreshold(Number(e.target.value)); setResult(null); }} style={{ flex: 1, accentColor: "var(--accent)" }} /> {(threshold / 10000).toFixed(2)}
{error && (
Error: {error}
)} {result && (
{/* Verdict banner */}
{VERDICT_ICON[result.final_verdict]}
{result.final_verdict}
consensus {(result.consensus_score * 100).toFixed(1)}%  ·  dissent {(result.dissent_score * 100).toFixed(1)}%  ·  {result.swarm_id}
{result.dissent_score > 0.25 && ( ⚠ DISSENT )}
{/* Agent votes */}
AGENT VOTES ({result.agent_votes.length})
{result.agent_votes.map((v, i) => (
{v.agent_id} {v.role}
{v.reasoning}
{VERDICT_ICON[v.verdict]} {v.verdict}
{(v.confidence * 100).toFixed(0)}% conf
))}
{result.timestamp}
)}
); } function App() { const [selectedId, setSelectedId] = useState("bob"); const [tab, setTab] = useState("live"); const [scores, setScores] = useState({}); const [attestation, setAttestation] = useState(null); const [chain, setChain] = useState({ galileo: null, base: null }); const [agentLoopStatus, setAgentLoopStatus] = useState(null); // Fetch health + scores + attestation + agent-loop status on mount + poll useEffect(() => { fetch(`${BFF}/health`) .then(r => r.json()) .then(d => setChain({ galileo: d.chain?.galileo, base: d.chain?.base })) .catch(() => {}); fetch(`${BFF}/attestation`) .then(r => r.json()) .then(d => setAttestation(d)) .catch(() => {}); Promise.all(AGENTS_META.map(a => fetch(`${BFF}/merit/${a.id}`) .then(r => r.json()) .then(d => [a.id, d]) .catch(() => [a.id, null]) )).then(results => { const s = {}; results.forEach(([id, d]) => { if (d) s[id] = { score: d.score, verdict: verdictFor(d.score), mode: d.mode }; }); setScores(s); }); // Fetch agent-loop status and poll every 10 seconds const fetchAgentLoopStatus = () => { fetch(`${BFF}/agent-loop/status`) .then(r => r.json()) .then(d => setAgentLoopStatus(d)) .catch(() => {}); }; fetchAgentLoopStatus(); const interval = setInterval(fetchAgentLoopStatus, 10000); return () => clearInterval(interval); }, []); const selected = AGENTS_META.find(a => a.id === selectedId); const pillCls = (ok) => ok === null ? "chain-pill" : ok ? "chain-pill" : "chain-pill offline"; const selectedScore = scores[selectedId]?.score; const selectedColor = selectedId === "bob" ? "#00d97e" : selectedId === "alice" ? "#ff4444" : "#8b96a5"; return (
{selected && (
{selected.initials}
Active Agent
{selected.name}
merit {selectedScore !== undefined ? selectedScore.toFixed(4) : "…"}
)}
{/* outer halo */} {/* outer reactor ring */} {/* mid ring */} {/* inner ring */} {/* 4 reactor slots: 12, 4, 6, 8 o'clock */} {/* dual pulsing core glow */} {/* prominent inverted triangle inscribed in inner ring (r=27) */} {/* inner triangle echo */} {/* vertex node caps */} {/* spark dot above W */} {/* W: center vertex at reactor core (32,32), outer strokes at ±60° */}

W.A.R.V.I.S

A Rather Very Intelligent System

MeritScore — Privacy-preserving credit scores for AI agents · ZK Proofs · 0G + Base

{agentLoopStatus?.running && ( ⚡ MeritGuard )} 0G Galileo Base Sepolia
// Agents under evaluation click a card to scope the tabs below
{AGENTS_META.map(a => ( setSelectedId(a.id)} /> ))}
{/* Force MeritGuard onto its own row so Sword #1–#6 stay together */}
{tab === "live" ? : tab === "tee" ? : tab === "wf" ? : tab === "ai" ? : tab === "zk" ? : tab === "uniswap" ? : tab === "swarm" ? : }
Mode: Direct Workflow Web3
Built at ETHGlobal OpenAgents · 0G Galileo + Base Sepolia
); } ReactDOM.createRoot(document.getElementById("root")).render();