6989a98d75
- Arkitektur: docs/auth/passwordless-architecture.md - Backend: iom/quixzoom-auth-service/ (FastAPI + Redis) - Webb: quixzoom-market-pages/se/login/ (QR-kod + polling) - App: iom/quixzoom-app/src/features/auth/ (push + deep links) Flöde: QR-kod → app-godkännande → webb-inloggad
210 lines
8.0 KiB
HTML
210 lines
8.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>LIFE Agent Swarm — Live Operations</title>
|
|
<link rel="stylesheet" href="/assets/css/landvex-complete.css">
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Inter', sans-serif; background: #000; color: #fff; line-height: 1.6; }
|
|
.header { background: #0a0a0a; border-bottom: 1px solid #333; padding: 24px; display: flex; justify-content: space-between; align-items: center; }
|
|
.header h1 { font-size: 1.5rem; color: #00d4ff; }
|
|
.status { display: flex; gap: 16px; }
|
|
.status-item { background: #1a3a1a; color: #4ade80; padding: 24px; border-radius: var(--radius-sm); font-size: 0.8rem; }
|
|
.main { padding: 40px; max-width: 1400px; margin: 0 auto; }
|
|
.metrics { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 16px; margin-bottom: 32px; }
|
|
.metric { background: #111; border: 1px solid #333; border-radius: var(--radius-md); padding: 20px; text-align: center; }
|
|
.metric-value { font-size: 2rem; font-weight: 700; color: #00d4ff; }
|
|
.metric-label { font-size: 0.8rem; color: #888; margin-top: 4px; }
|
|
.agents { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; margin-bottom: 32px; }
|
|
.agent { background: #111; border: 1px solid #333; border-radius: var(--radius-md); padding: 20px; }
|
|
.agent-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
|
|
.agent-name { font-weight: 600; color: #fff; }
|
|
.agent-status { font-size: 0.75rem; padding: 24px; border-radius: var(--radius-sm); }
|
|
.status-active { background: #1a3a1a; color: #4ade80; }
|
|
.agent-stats { font-size: 0.85rem; color: #888; }
|
|
.agent-stats div { margin: 4px 0; }
|
|
.log { background: #111; border: 1px solid #333; border-radius: var(--radius-md); padding: 20px; height: 400px; overflow-y: auto; }
|
|
.log h2 { font-size: 1.1rem; margin-bottom: 12px; color: #00d4ff; }
|
|
.log-entry { font-family: monospace; font-size: 0.8rem; padding: 4px 0; border-bottom: 1px solid #222; }
|
|
.log-time { color: #666; }
|
|
.log-agent { color: #7c3aed; }
|
|
.log-msg { color: #aaa; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="header">
|
|
<div>
|
|
<h1>LIFE Agent Swarm</h1>
|
|
</div>
|
|
<div class="status">
|
|
<div class="status-item"> 6 Agents Active</div>
|
|
<div class="status-item"> 281 Nodes</div>
|
|
<div class="status-item"> 924 Edges</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="main">
|
|
|
|
<div class="metrics">
|
|
<div class="metric">
|
|
<div class="metric-value" id="objects-discovered">0</div>
|
|
<div class="metric-label">Objects Discovered</div>
|
|
</div>
|
|
<div class="metric">
|
|
<div class="metric-value" id="observations-added">0</div>
|
|
<div class="metric-label">Observations Added</div>
|
|
</div>
|
|
<div class="metric">
|
|
<div class="metric-value" id="evidence-validated">0</div>
|
|
<div class="metric-label">Evidence Validated</div>
|
|
</div>
|
|
<div class="metric">
|
|
<div class="metric-value" id="confidence-improved">0</div>
|
|
<div class="metric-label">Confidence Improved</div>
|
|
</div>
|
|
<div class="metric">
|
|
<div class="metric-value" id="missions-generated">0</div>
|
|
<div class="metric-label">Missions Generated</div>
|
|
</div>
|
|
<div class="metric">
|
|
<div class="metric-value" id="cycles">0</div>
|
|
<div class="metric-label">Cycles Completed</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="agents">
|
|
<div class="agent">
|
|
<div class="agent-header">
|
|
<div class="agent-name"> Crawler Agent</div>
|
|
<div class="agent-status status-active">ACTIVE</div>
|
|
</div>
|
|
<div class="agent-stats">
|
|
<div>Discovers new roads and infrastructure</div>
|
|
<div>Last run: <span id="crawler-last">—</span></div>
|
|
<div>Roads found: <span id="crawler-count">—</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="agent">
|
|
<div class="agent-header">
|
|
<div class="agent-name"> Observation Agent</div>
|
|
<div class="agent-status status-active">ACTIVE</div>
|
|
</div>
|
|
<div class="agent-stats">
|
|
<div>Generates observations from multiple sources</div>
|
|
<div>Last run: <span id="obs-last">—</span></div>
|
|
<div>Observations: <span id="obs-count">—</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="agent">
|
|
<div class="agent-header">
|
|
<div class="agent-name"><svg width="20" height="20" viewBox="0 0 20 20" fill="none"><circle cx="10" cy="10" r="9" stroke="#22c55e" stroke-width="2"/><path d="M6 10L9 13L14 7" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> Validation Agent</div>
|
|
<div class="agent-status status-active">ACTIVE</div>
|
|
</div>
|
|
<div class="agent-stats">
|
|
<div>Validates evidence quality</div>
|
|
<div>Last run: <span id="val-last">—</span></div>
|
|
<div>Validated: <span id="val-count">—</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="agent">
|
|
<div class="agent-header">
|
|
<div class="agent-name"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M2 12L6 8L9 11L14 5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M10 5H14V9" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> Confidence Agent</div>
|
|
<div class="agent-status status-active">ACTIVE</div>
|
|
</div>
|
|
<div class="agent-stats">
|
|
<div>Improves confidence scoring</div>
|
|
<div>Last run: <span id="conf-last">—</span></div>
|
|
<div>Improved: <span id="conf-count">—</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="agent">
|
|
<div class="agent-header">
|
|
<div class="agent-name"> Mission Agent</div>
|
|
<div class="agent-status status-active">ACTIVE</div>
|
|
</div>
|
|
<div class="agent-stats">
|
|
<div>Generates QUIXZOOM missions</div>
|
|
<div>Last run: <span id="mission-last">—</span></div>
|
|
<div>Missions: <span id="mission-count">—</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="agent">
|
|
<div class="agent-header">
|
|
<div class="agent-name"> Learning Agent</div>
|
|
<div class="agent-status status-active">ACTIVE</div>
|
|
</div>
|
|
<div class="agent-stats">
|
|
<div>Analyzes patterns and improves models</div>
|
|
<div>Last run: <span id="learn-last">—</span></div>
|
|
<div>Patterns: <span id="learn-count">—</span></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="log">
|
|
<h2>Agent Activity Log</h2>
|
|
<div id="log-content">
|
|
<div class="log-entry"><span class="log-time">--:--:--</span> <span class="log-agent">SYSTEM</span> <span class="log-msg">Agent swarm initialized...</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
let cycle = 0;
|
|
|
|
function updateStats() {
|
|
// Simulera ökande värden (i verkligheten: hämta från API)
|
|
cycle++;
|
|
document.getElementById('cycles').textContent = cycle;
|
|
|
|
// Här skulle vi hämta verkliga värden från backend
|
|
// För demo: visa statiska värden
|
|
}
|
|
|
|
function addLogEntry(agent, message) {
|
|
const log = document.getElementById('log-content');
|
|
const time = new Date().toLocaleTimeString();
|
|
const entry = document.createElement('div');
|
|
entry.className = 'log-entry';
|
|
entry.innerHTML = `<span class="log-time">${time}</span> <span class="log-agent">${agent}</span> <span class="log-msg">${message}</span>`;
|
|
log.insertBefore(entry, log.firstChild);
|
|
|
|
// Begränsa till 50 entries
|
|
while (log.children.length > 50) {
|
|
log.removeChild(log.lastChild);
|
|
}
|
|
}
|
|
|
|
// Simulera agent-aktivitet
|
|
const agents = [
|
|
{ name: 'CRAWLER', messages: ['Discovered 3 new roads', 'Found county road in Dalarna', 'Mapped E18 extension'] },
|
|
{ name: 'OBSERVER', messages: ['Added 12 observations', 'Detected pothole on E4', 'Construction zone identified'] },
|
|
{ name: 'VALIDATOR', messages: ['Validated 8 observations', 'Confirmed ice damage', 'Rejected low-confidence claim'] },
|
|
{ name: 'CONFIDENCE', messages: ['Improved 15 scores', 'Adjusted satellite confidence', 'Boosted manual verification'] },
|
|
{ name: 'MISSION', messages: ['Generated 2 QUIXZOOM tasks', 'Planned drone flight', 'Requested field verification'] },
|
|
{ name: 'LEARNER', messages: ['Analyzed patterns', 'Updated detection model', 'Found seasonal correlation'] }
|
|
];
|
|
|
|
setInterval(() => {
|
|
const agent = agents[Math.floor(Math.random() * agents.length)];
|
|
const msg = agent.messages[Math.floor(Math.random() * agent.messages.length)];
|
|
addLogEntry(agent.name, msg);
|
|
updateStats();
|
|
}, 3000);
|
|
|
|
// Uppdatera var 5:e sekund
|
|
setInterval(updateStats, 5000);
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|