Vapora/assets/vapora_architecture.svg

577 lines
42 KiB
XML
Raw Permalink Normal View History

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 1020" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
<defs>
<style>
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700;800&amp;family=Inter:wght@400;500;600&amp;display=swap');
</style>
<!-- Brand gradients -->
<linearGradient id="grad-main" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#22d3ee"/>
<stop offset="50%" stop-color="#a855f7"/>
<stop offset="100%" stop-color="#ec4899"/>
</linearGradient>
<linearGradient id="grad-cyan-purple" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#22d3ee"/>
<stop offset="100%" stop-color="#a855f7"/>
</linearGradient>
<linearGradient id="grad-purple-pink" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#a855f7"/>
<stop offset="100%" stop-color="#ec4899"/>
</linearGradient>
<linearGradient id="grad-vertical" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#22d3ee" stop-opacity="0.8"/>
<stop offset="50%" stop-color="#a855f7" stop-opacity="0.5"/>
<stop offset="100%" stop-color="#ec4899" stop-opacity="0.3"/>
</linearGradient>
<linearGradient id="grad-card-cyan" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#22d3ee" stop-opacity="0.15"/>
<stop offset="100%" stop-color="#22d3ee" stop-opacity="0.05"/>
</linearGradient>
<linearGradient id="grad-card-purple" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#a855f7" stop-opacity="0.15"/>
<stop offset="100%" stop-color="#a855f7" stop-opacity="0.05"/>
</linearGradient>
<linearGradient id="grad-card-pink" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#ec4899" stop-opacity="0.15"/>
<stop offset="100%" stop-color="#ec4899" stop-opacity="0.05"/>
</linearGradient>
<!-- Glow filters -->
<filter id="glow-sm">
<feGaussianBlur stdDeviation="2" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glow-md">
<feGaussianBlur stdDeviation="4" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glow-lg">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glass-card">
<feGaussianBlur in="SourceAlpha" stdDeviation="1" result="blur"/>
<feOffset dx="0" dy="1" result="shadow"/>
<feFlood flood-color="#000" flood-opacity="0.3" result="color"/>
<feComposite in="color" in2="shadow" operator="in" result="shadow"/>
<feMerge><feMergeNode in="shadow"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<!-- Animated particle marker -->
<circle id="particle-cyan" r="3" fill="#22d3ee" filter="url(#glow-md)"/>
<circle id="particle-purple" r="3" fill="#a855f7" filter="url(#glow-md)"/>
<circle id="particle-pink" r="3" fill="#ec4899" filter="url(#glow-md)"/>
<circle id="particle-sm-cyan" r="2" fill="#22d3ee" filter="url(#glow-sm)"/>
<circle id="particle-sm-purple" r="2" fill="#a855f7" filter="url(#glow-sm)"/>
<circle id="particle-sm-pink" r="2" fill="#ec4899" filter="url(#glow-sm)"/>
</defs>
<!-- ═══════════════════════════════════════ -->
<!-- BACKGROUND -->
<!-- ═══════════════════════════════════════ -->
<rect width="1400" height="1020" fill="#0a0a0a"/>
<!-- Subtle tech grid -->
<g opacity="0.04" stroke="#22d3ee" stroke-width="0.5">
<line x1="0" y1="0" x2="1400" y2="0"><animate attributeName="y1" values="0;1020" dur="60s" repeatCount="indefinite"/><animate attributeName="y2" values="0;1020" dur="60s" repeatCount="indefinite"/></line>
<line x1="100" y1="0" x2="100" y2="1020"/>
<line x1="250" y1="0" x2="250" y2="1020"/>
<line x1="400" y1="0" x2="400" y2="1020"/>
<line x1="550" y1="0" x2="550" y2="1020"/>
<line x1="700" y1="0" x2="700" y2="1020"/>
<line x1="850" y1="0" x2="850" y2="1020"/>
<line x1="1000" y1="0" x2="1000" y2="1020"/>
<line x1="1150" y1="0" x2="1150" y2="1020"/>
<line x1="1300" y1="0" x2="1300" y2="1020"/>
<line x1="0" y1="130" x2="1400" y2="130"/>
<line x1="0" y1="260" x2="1400" y2="260"/>
<line x1="0" y1="420" x2="1400" y2="420"/>
<line x1="0" y1="580" x2="1400" y2="580"/>
<line x1="0" y1="720" x2="1400" y2="720"/>
<line x1="0" y1="860" x2="1400" y2="860"/>
</g>
<!-- Ambient glow orbs -->
<circle cx="240" cy="350" r="180" fill="#22d3ee" opacity="0.07">
<animate attributeName="r" values="160;200;160" dur="8s" repeatCount="indefinite"/>
</circle>
<circle cx="690" cy="360" r="175" fill="#a855f7" opacity="0.05">
<animate attributeName="r" values="175;195;175" dur="10s" repeatCount="indefinite"/>
</circle>
<circle cx="1130" cy="350" r="200" fill="#ec4899" opacity="0.07">
<animate attributeName="r" values="180;220;180" dur="9s" repeatCount="indefinite"/>
</circle>
<!-- ═══════════════════════════════════════ -->
<!-- TITLE -->
<!-- ═══════════════════════════════════════ -->
<text x="700" y="42" font-family="'JetBrains Mono', monospace" font-size="22" font-weight="800" fill="url(#grad-main)" letter-spacing="6" text-anchor="middle" filter="url(#glow-sm)">VAPORA ARCHITECTURE</text>
<text x="700" y="62" font-family="'Inter', sans-serif" font-size="11" fill="#a855f7" opacity="0.6" letter-spacing="3" text-anchor="middle">18 CRATES · 354 TESTS · 100% RUST</text>
<!-- Layer labels (left side) -->
<text x="30" y="115" font-family="'JetBrains Mono', monospace" font-size="10" fill="#22d3ee" opacity="0.7" letter-spacing="2" transform="rotate(-90 30 115)">PRESENTATION</text>
<text x="30" y="290" font-family="'JetBrains Mono', monospace" font-size="10" fill="#a855f7" opacity="0.7" letter-spacing="2" transform="rotate(-90 30 290)">SERVICES</text>
<text x="30" y="485" font-family="'JetBrains Mono', monospace" font-size="10" fill="#ec4899" opacity="0.7" letter-spacing="2" transform="rotate(-90 30 485)">INTELLIGENCE</text>
<text x="30" y="640" font-family="'JetBrains Mono', monospace" font-size="10" fill="#22d3ee" opacity="0.7" letter-spacing="2" transform="rotate(-90 30 640)">DATA</text>
<text x="30" y="850" font-family="'JetBrains Mono', monospace" font-size="10" fill="#a855f7" opacity="0.7" letter-spacing="2" transform="rotate(-90 30 850)">PROVIDERS</text>
<!-- ═══════════════════════════════════════ -->
<!-- ROW 1: FRONTEND (y=80) -->
<!-- ═══════════════════════════════════════ -->
<!-- Frontend card -->
<g filter="url(#glass-card)">
<rect x="490" y="80" width="420" height="65" rx="8" fill="url(#grad-card-cyan)" stroke="#22d3ee" stroke-opacity="0.4" stroke-width="2"/>
<rect x="494" y="80" width="412" height="1.5" rx="1" fill="url(#grad-main)" opacity="0.8"/>
<text x="700" y="106" font-family="'JetBrains Mono', monospace" font-size="14" font-weight="700" fill="#22d3ee" text-anchor="middle" filter="url(#glow-sm)">Leptos WASM Frontend</text>
<text x="700" y="124" font-family="'Inter', sans-serif" font-size="10" fill="#ffffff" opacity="0.5" text-anchor="middle">Kanban Board · Glassmorphism UI · UnoCSS · Reactive Components</text>
<!-- Pulse ring -->
<rect x="490" y="80" width="420" height="65" rx="8" fill="none" stroke="#22d3ee" stroke-opacity="0.15">
<animate attributeName="stroke-opacity" values="0.15;0.3;0.15" dur="3s" repeatCount="indefinite"/>
</rect>
</g>
<!-- ═══════════════════════════════════════ -->
<!-- CONNECTION: Frontend → Services -->
<!-- ═══════════════════════════════════════ -->
<!-- Frontend to Backend -->
<path id="path-fe-be" d="M 580 145 L 580 160 Q 580 175 480 175 L 280 175 Q 260 175 260 195 L 260 210" fill="none" stroke="#22d3ee" stroke-width="2" stroke-opacity="0.25"/>
<use href="#particle-sm-cyan" opacity="0.8"><animateMotion dur="2.5s" repeatCount="indefinite"><mpath href="#path-fe-be"/></animateMotion></use>
<!-- Frontend to Agents -->
<line x1="700" y1="145" x2="700" y2="210" stroke="#a855f7" stroke-width="2" stroke-opacity="0.25"/>
<use href="#particle-sm-purple" opacity="0.8"><animateMotion dur="2s" repeatCount="indefinite" path="M 700 145 L 700 210"/></use>
<!-- Frontend to MCP -->
<path id="path-fe-mcp" d="M 820 145 L 820 160 Q 820 175 920 175 L 1100 175 Q 1140 175 1140 195 L 1140 210" fill="none" stroke="#ec4899" stroke-width="2" stroke-opacity="0.25"/>
<use href="#particle-sm-pink" opacity="0.8"><animateMotion dur="2.5s" repeatCount="indefinite"><mpath href="#path-fe-mcp"/></animateMotion></use>
<!-- ═══════════════════════════════════════ -->
<!-- ROW 2: SERVICES (y=210) -->
<!-- ═══════════════════════════════════════ -->
<!-- Backend / Axum API -->
<g filter="url(#glass-card)">
<rect x="100" y="210" width="310" height="100" rx="8" fill="url(#grad-card-cyan)" stroke="#22d3ee" stroke-opacity="0.35" stroke-width="2"/>
<rect x="104" y="210" width="302" height="1.5" rx="1" fill="#22d3ee" opacity="0.6"/>
<text x="255" y="237" font-family="'JetBrains Mono', monospace" font-size="13" font-weight="700" fill="#22d3ee" text-anchor="middle">Axum Backend API</text>
<text x="255" y="256" font-family="'Inter', sans-serif" font-size="9" fill="#ffffff" opacity="0.45" text-anchor="middle">40+ REST Endpoints · 161 Tests</text>
<!-- Sub-items -->
<g font-family="'Inter', sans-serif" font-size="8" fill="#ffffff" opacity="0.35">
<text x="120" y="278">Projects</text>
<text x="180" y="278">Tasks</text>
<text x="225" y="278">Agents</text>
<text x="280" y="278">Workflows</text>
<text x="350" y="278">Proposals</text>
<text x="120" y="294">Swarm</text>
<text x="175" y="294">Metrics</text>
<text x="235" y="294">RLM API</text>
<text x="300" y="294">WebSocket</text>
</g>
</g>
<!-- Agent Runtime -->
<g filter="url(#glass-card)">
<rect x="540" y="210" width="310" height="100" rx="8" fill="url(#grad-card-purple)" stroke="#a855f7" stroke-opacity="0.35" stroke-width="2"/>
<rect x="544" y="210" width="302" height="1.5" rx="1" fill="#a855f7" opacity="0.6"/>
<text x="695" y="237" font-family="'JetBrains Mono', monospace" font-size="13" font-weight="700" fill="#a855f7" text-anchor="middle">Agent Runtime</text>
<text x="695" y="256" font-family="'Inter', sans-serif" font-size="9" fill="#ffffff" opacity="0.45" text-anchor="middle">Orchestration · Learning Profiles · 71 Tests</text>
<g font-family="'Inter', sans-serif" font-size="8" fill="#ffffff" opacity="0.35">
<text x="560" y="278">Registry</text>
<text x="625" y="278">Coordinator</text>
<text x="720" y="278">Scoring</text>
<text x="785" y="278">Profiles</text>
<text x="560" y="294">12 Roles</text>
<text x="630" y="294">Health Checks</text>
<text x="735" y="294">Recency Bias</text>
</g>
<!-- Heartbeat animation -->
<circle cx="835" cy="225" r="4" fill="#a855f7" opacity="0.07">
<animate attributeName="r" values="3;5;3" dur="1.5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.3;0.6;0.3" dur="1.5s" repeatCount="indefinite"/>
</circle>
</g>
<!-- MCP Gateway -->
<g filter="url(#glass-card)">
<rect x="980" y="210" width="310" height="100" rx="8" fill="url(#grad-card-pink)" stroke="#ec4899" stroke-opacity="0.35" stroke-width="2"/>
<rect x="984" y="210" width="302" height="1.5" rx="1" fill="#ec4899" opacity="0.6"/>
<text x="1135" y="237" font-family="'JetBrains Mono', monospace" font-size="13" font-weight="700" fill="#ec4899" text-anchor="middle">MCP Gateway</text>
<text x="1135" y="256" font-family="'Inter', sans-serif" font-size="9" fill="#ffffff" opacity="0.45" text-anchor="middle">Model Context Protocol · Plugin System</text>
<g font-family="'Inter', sans-serif" font-size="8" fill="#ffffff" opacity="0.35">
<text x="1000" y="278">Stdio Transport</text>
<text x="1105" y="278">SSE Transport</text>
<text x="1210" y="278">JSON-RPC</text>
<text x="1000" y="294">6 Tools</text>
<text x="1060" y="294">Tool Registry</text>
<text x="1160" y="294">Schema Validation</text>
</g>
</g>
<!-- A2A Protocol (small card overlapping) -->
<g filter="url(#glass-card)">
<rect x="445" y="280" width="86" height="35" rx="6" fill="rgba(168,85,247,0.1)" stroke="#a855f7" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="488" y="300" font-family="'JetBrains Mono', monospace" font-size="9" font-weight="700" fill="#a855f7" opacity="0.6" text-anchor="middle">A2A Protocol</text>
</g>
<!-- ═══════════════════════════════════════ -->
<!-- CONNECTIONS: Services → Intelligence -->
<!-- ═══════════════════════════════════════ -->
<!-- Backend → RLM -->
<path id="path-be-rlm" d="M 200 310 L 200 380" fill="none" stroke="#22d3ee" stroke-width="2" stroke-opacity="0.2"/>
<use href="#particle-sm-cyan" opacity="0.7"><animateMotion dur="1.8s" repeatCount="indefinite" path="M 200 310 L 200 380"/></use>
<!-- Backend → SurrealDB (arco por la derecha para evitar KG) -->
<path id="path-be-sdb" d="M 320 310 L 320 340 Q 320 360 360 360 L 420 360 Q 435 360 435 380 Q 435 580 420 580 L 420 585" fill="none" stroke="#22d3ee" stroke-width="2" stroke-opacity="0.35" stroke-dasharray="4 4"/>
<!-- Agents → LLM Router -->
<line x1="695" y1="310" x2="695" y2="380" stroke="#a855f7" stroke-width="2.4" stroke-opacity="0.3"/>
<use href="#particle-purple" opacity="0.8"><animateMotion dur="1.5s" repeatCount="indefinite" path="M 695 310 L 695 380"/></use>
<use href="#particle-sm-purple" opacity="0.5"><animateMotion dur="1.5s" begin="0.75s" repeatCount="indefinite" path="M 695 310 L 695 380"/></use>
<!-- Agents → Swarm -->
<path id="path-ag-sw" d="M 800 310 L 800 340 Q 800 355 900 355 L 1050 355 Q 1070 355 1070 375 L 1070 380" fill="none" stroke="#a855f7" stroke-width="2" stroke-opacity="0.2"/>
<use href="#particle-sm-purple" opacity="0.6"><animateMotion dur="2.2s" repeatCount="indefinite"><mpath href="#path-ag-sw"/></animateMotion></use>
<!-- MCP → Agents -->
<path id="path-mcp-ag" d="M 1020 310 L 1020 320 Q 1020 332 920 332 L 810 332 Q 800 332 800 320 L 800 310" fill="none" stroke="#ec4899" stroke-width="1.6" stroke-opacity="0.35" stroke-dasharray="3 3"/>
<!-- ═══════════════════════════════════════ -->
<!-- ROW 3: INTELLIGENCE (y=380) -->
<!-- ═══════════════════════════════════════ -->
<!-- RLM Engine -->
<g filter="url(#glass-card)">
<rect x="60" y="380" width="340" height="130" rx="8" fill="url(#grad-card-cyan)" stroke="#22d3ee" stroke-opacity="0.4" stroke-width="1.2"/>
<rect x="64" y="380" width="332" height="2" rx="1" fill="url(#grad-main)" opacity="0.7"/>
<text x="230" y="405" font-family="'JetBrains Mono', monospace" font-size="14" font-weight="700" fill="url(#grad-main)" text-anchor="middle" filter="url(#glow-sm)">RLM Engine</text>
<text x="230" y="422" font-family="'Inter', sans-serif" font-size="9" fill="#ffffff" opacity="0.45" text-anchor="middle">Recursive Language Models · 38 Tests · 17k+ LOC</text>
<!-- RLM sub-components as mini pills -->
<g transform="translate(75, 435)">
<!-- Chunking -->
<rect x="0" y="0" width="80" height="22" rx="4" fill="rgba(34,211,238,0.12)" stroke="#22d3ee" stroke-opacity="0.3" stroke-width="0.5"/>
<text x="40" y="11" font-family="'JetBrains Mono', monospace" font-size="7" fill="#22d3ee" opacity="0.8" text-anchor="middle" dominant-baseline="central">Chunking</text>
<!-- Hybrid Search -->
<rect x="90" y="0" width="95" height="22" rx="4" fill="rgba(168,85,247,0.12)" stroke="#a855f7" stroke-opacity="0.3" stroke-width="0.5"/>
<text x="137" y="11" font-family="'JetBrains Mono', monospace" font-size="7" fill="#a855f7" opacity="0.8" text-anchor="middle" dominant-baseline="central">Hybrid Search</text>
<!-- Dispatcher -->
<rect x="195" y="0" width="80" height="22" rx="4" fill="rgba(236,72,153,0.12)" stroke="#ec4899" stroke-opacity="0.3" stroke-width="0.5"/>
<text x="235" y="11" font-family="'JetBrains Mono', monospace" font-size="7" fill="#ec4899" opacity="0.8" text-anchor="middle" dominant-baseline="central">Dispatcher</text>
</g>
<g transform="translate(75, 465)">
<!-- BM25 -->
<rect x="0" y="0" width="65" height="20" rx="3" fill="rgba(34,211,238,0.08)" stroke="#22d3ee" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="32" y="10" font-family="'Inter', sans-serif" font-size="7" fill="#22d3ee" opacity="0.6" text-anchor="middle" dominant-baseline="central">BM25</text>
<!-- Semantic -->
<rect x="75" y="0" width="70" height="20" rx="3" fill="rgba(168,85,247,0.08)" stroke="#a855f7" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="110" y="10" font-family="'Inter', sans-serif" font-size="7" fill="#a855f7" opacity="0.6" text-anchor="middle" dominant-baseline="central">Semantic</text>
<!-- RRF -->
<rect x="155" y="0" width="50" height="20" rx="3" fill="rgba(236,72,153,0.08)" stroke="#ec4899" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="180" y="10" font-family="'Inter', sans-serif" font-size="7" fill="#ec4899" opacity="0.6" text-anchor="middle" dominant-baseline="central">RRF</text>
<!-- Sandbox -->
<rect x="215" y="0" width="60" height="20" rx="3" fill="rgba(34,211,238,0.08)" stroke="#22d3ee" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="245" y="10" font-family="'Inter', sans-serif" font-size="7" fill="#22d3ee" opacity="0.6" text-anchor="middle" dominant-baseline="central">Sandbox</text>
</g>
<!-- Animated search indicator -->
<g transform="translate(370, 400)">
<circle r="6" fill="none" stroke="#22d3ee" stroke-width="0.8" opacity="0.07">
<animate attributeName="r" values="4;8;4" dur="3s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.4;0.1;0.4" dur="3s" repeatCount="indefinite"/>
</circle>
<circle r="3" fill="#22d3ee" opacity="0.07">
<animate attributeName="opacity" values="0.2;0.5;0.2" dur="3s" repeatCount="indefinite"/>
</circle>
</g>
</g>
<!-- LLM Router -->
<g filter="url(#glass-card)">
<rect x="500" y="380" width="380" height="130" rx="8" fill="url(#grad-card-purple)" stroke="#a855f7" stroke-opacity="0.4" stroke-width="1.2"/>
<rect x="504" y="380" width="372" height="2" rx="1" fill="#a855f7" opacity="0.7"/>
<text x="690" y="405" font-family="'JetBrains Mono', monospace" font-size="14" font-weight="700" fill="#a855f7" text-anchor="middle" filter="url(#glow-sm)">Multi-IA LLM Router</text>
<text x="690" y="422" font-family="'Inter', sans-serif" font-size="9" fill="#ffffff" opacity="0.45" text-anchor="middle">Budget Enforcement · Cost Tracking · 53 Tests</text>
<!-- Router sub-components -->
<g transform="translate(515, 435)">
<rect x="0" y="0" width="95" height="22" rx="4" fill="rgba(168,85,247,0.12)" stroke="#a855f7" stroke-opacity="0.3" stroke-width="0.5"/>
<text x="47" y="11" font-family="'JetBrains Mono', monospace" font-size="7" fill="#a855f7" opacity="0.8" text-anchor="middle" dominant-baseline="central">Rule Router</text>
<rect x="105" y="0" width="115" height="22" rx="4" fill="rgba(236,72,153,0.12)" stroke="#ec4899" stroke-opacity="0.3" stroke-width="0.5"/>
<text x="162" y="11" font-family="'JetBrains Mono', monospace" font-size="7" fill="#ec4899" opacity="0.8" text-anchor="middle" dominant-baseline="central">Budget Manager</text>
<rect x="230" y="0" width="110" height="22" rx="4" fill="rgba(34,211,238,0.12)" stroke="#22d3ee" stroke-opacity="0.3" stroke-width="0.5"/>
<text x="285" y="11" font-family="'JetBrains Mono', monospace" font-size="7" fill="#22d3ee" opacity="0.8" text-anchor="middle" dominant-baseline="central">Cost Tracker</text>
</g>
<g transform="translate(515, 465)">
<rect x="0" y="0" width="95" height="20" rx="3" fill="rgba(168,85,247,0.08)" stroke="#a855f7" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="47" y="10" font-family="'Inter', sans-serif" font-size="7" fill="#a855f7" opacity="0.6" text-anchor="middle" dominant-baseline="central">Fallback Chain</text>
<rect x="105" y="0" width="90" height="20" rx="3" fill="rgba(236,72,153,0.08)" stroke="#ec4899" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="150" y="10" font-family="'Inter', sans-serif" font-size="7" fill="#ec4899" opacity="0.6" text-anchor="middle" dominant-baseline="central">Cost Ranker</text>
<rect x="205" y="0" width="80" height="20" rx="3" fill="rgba(34,211,238,0.08)" stroke="#22d3ee" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="245" y="10" font-family="'Inter', sans-serif" font-size="7" fill="#22d3ee" opacity="0.6" text-anchor="middle" dominant-baseline="central">Providers</text>
</g>
<!-- Routing indicator animation -->
<g transform="translate(855, 400)">
<line x1="-6" y1="0" x2="6" y2="0" stroke="#a855f7" stroke-width="1.5" opacity="0.5">
<animateTransform attributeName="transform" type="rotate" values="0;360" dur="4s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="-6" x2="0" y2="6" stroke="#ec4899" stroke-width="1.5" opacity="0.5">
<animateTransform attributeName="transform" type="rotate" values="0;360" dur="4s" repeatCount="indefinite"/>
</line>
</g>
</g>
<!-- Swarm Coordinator -->
<g filter="url(#glass-card)">
<rect x="980" y="380" width="310" height="130" rx="8" fill="url(#grad-card-pink)" stroke="#ec4899" stroke-opacity="0.35" stroke-width="2"/>
<rect x="984" y="380" width="302" height="1.5" rx="1" fill="#ec4899" opacity="0.6"/>
<text x="1135" y="405" font-family="'JetBrains Mono', monospace" font-size="14" font-weight="700" fill="#ec4899" text-anchor="middle" filter="url(#glow-sm)">Swarm Coordinator</text>
<text x="1135" y="422" font-family="'Inter', sans-serif" font-size="9" fill="#ffffff" opacity="0.45" text-anchor="middle">Load Balancing · Prometheus · 6 Tests</text>
<g transform="translate(995, 435)">
<rect x="0" y="0" width="90" height="22" rx="4" fill="rgba(236,72,153,0.12)" stroke="#ec4899" stroke-opacity="0.3" stroke-width="0.5"/>
<text x="45" y="11" font-family="'JetBrains Mono', monospace" font-size="7" fill="#ec4899" opacity="0.8" text-anchor="middle" dominant-baseline="central">Assignment</text>
<rect x="100" y="0" width="90" height="22" rx="4" fill="rgba(34,211,238,0.12)" stroke="#22d3ee" stroke-opacity="0.3" stroke-width="0.5"/>
<text x="145" y="11" font-family="'JetBrains Mono', monospace" font-size="7" fill="#22d3ee" opacity="0.8" text-anchor="middle" dominant-baseline="central">Filtering</text>
<rect x="200" y="0" width="80" height="22" rx="4" fill="rgba(168,85,247,0.12)" stroke="#a855f7" stroke-opacity="0.3" stroke-width="0.5"/>
<text x="240" y="11" font-family="'JetBrains Mono', monospace" font-size="7" fill="#a855f7" opacity="0.8" text-anchor="middle" dominant-baseline="central">Metrics</text>
</g>
<g transform="translate(995, 465)">
<rect x="0" y="0" width="130" height="20" rx="3" fill="rgba(236,72,153,0.08)" stroke="#ec4899" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="65" y="10" font-family="'Inter', sans-serif" font-size="7" fill="#ec4899" opacity="0.6" text-anchor="middle" dominant-baseline="central">success_rate / (1+load)</text>
<rect x="140" y="0" width="80" height="20" rx="3" fill="rgba(34,211,238,0.08)" stroke="#22d3ee" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="180" y="10" font-family="'Inter', sans-serif" font-size="7" fill="#22d3ee" opacity="0.6" text-anchor="middle" dominant-baseline="central">Capabilities</text>
</g>
<!-- Swarm pulse -->
<circle cx="1270" cy="395" r="3" fill="#ec4899" opacity="0.07">
<animate attributeName="r" values="2;5;2" dur="2s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.2;0.5;0.2" dur="2s" repeatCount="indefinite"/>
</circle>
</g>
<!-- RLM → LLM Router connection -->
<path id="path-rlm-llm" d="M 400 445 L 500 445" fill="none" stroke="url(#grad-cyan-purple)" stroke-width="3" stroke-opacity="0.3"/>
<use href="#particle-cyan" opacity="0.7"><animateMotion dur="1.5s" repeatCount="indefinite" path="M 400 445 L 500 445"/></use>
<!-- LLM Router → Swarm connection -->
<path d="M 880 445 L 980 445" fill="none" stroke="url(#grad-purple-pink)" stroke-width="2" stroke-opacity="0.2"/>
<use href="#particle-sm-pink" opacity="0.6"><animateMotion dur="1.8s" repeatCount="indefinite" path="M 880 445 L 980 445"/></use>
<!-- ═══════════════════════════════════════ -->
<!-- CONNECTIONS: Intelligence → Data -->
<!-- ═══════════════════════════════════════ -->
<!-- RLM → KG -->
<path id="path-rlm-kg" d="M 160 510 L 160 575" fill="none" stroke="#22d3ee" stroke-width="2" stroke-opacity="0.25"/>
<use href="#particle-sm-cyan" opacity="0.7"><animateMotion dur="1.8s" repeatCount="indefinite" path="M 160 510 L 160 575"/></use>
<!-- RLM → SurrealDB -->
<path id="path-rlm-sdb" d="M 300 510 L 300 540 Q 300 555 400 555 L 530 555 Q 545 555 545 575" fill="none" stroke="#22d3ee" stroke-width="2.4" stroke-opacity="0.25"/>
<use href="#particle-cyan" opacity="0.7"><animateMotion dur="2.5s" repeatCount="indefinite"><mpath href="#path-rlm-sdb"/></animateMotion></use>
<!-- LLM Router → Providers (goes down below data) -->
<path id="path-llm-providers" d="M 790 510 L 790 725" fill="none" stroke="#a855f7" stroke-width="3" stroke-opacity="0.2"/>
<use href="#particle-purple" opacity="0.8"><animateMotion dur="3s" repeatCount="indefinite" path="M 790 510 L 790 725"/></use>
<use href="#particle-sm-purple" opacity="0.5"><animateMotion dur="3s" begin="1.5s" repeatCount="indefinite" path="M 790 510 L 790 725"/></use>
<!-- Swarm → NATS -->
<path id="path-sw-nats" d="M 1135 510 L 1135 575" fill="none" stroke="#ec4899" stroke-width="2" stroke-opacity="0.25"/>
<use href="#particle-sm-pink" opacity="0.7"><animateMotion dur="1.8s" repeatCount="indefinite" path="M 1135 510 L 1135 575"/></use>
<!-- ═══════════════════════════════════════ -->
<!-- ROW 4: DATA LAYER (y=575) -->
<!-- ═══════════════════════════════════════ -->
<!-- Knowledge Graph -->
<g filter="url(#glass-card)">
<rect x="60" y="575" width="260" height="100" rx="8" fill="url(#grad-card-cyan)" stroke="#22d3ee" stroke-opacity="0.3" stroke-width="2"/>
<rect x="60" y="575" width="260" height="1.5" rx="1" fill="#22d3ee" opacity="0.5"/>
<text x="190" y="600" font-family="'JetBrains Mono', monospace" font-size="12" font-weight="700" fill="#22d3ee" text-anchor="middle">Knowledge Graph</text>
<text x="190" y="617" font-family="'Inter', sans-serif" font-size="9" fill="#ffffff" opacity="0.4" text-anchor="middle">Temporal History · Learning Curves · 20 Tests</text>
<g transform="translate(75, 630)">
<rect x="0" y="0" width="80" height="18" rx="3" fill="rgba(34,211,238,0.1)" stroke="#22d3ee" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="40" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#22d3ee" opacity="0.6" text-anchor="middle" dominant-baseline="central">Executions</text>
<rect x="90" y="0" width="70" height="18" rx="3" fill="rgba(168,85,247,0.1)" stroke="#a855f7" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="125" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#a855f7" opacity="0.6" text-anchor="middle" dominant-baseline="central">Similarity</text>
<rect x="170" y="0" width="60" height="18" rx="3" fill="rgba(236,72,153,0.1)" stroke="#ec4899" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="200" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#ec4899" opacity="0.6" text-anchor="middle" dominant-baseline="central">Causal</text>
</g>
</g>
<!-- SurrealDB -->
<g filter="url(#glass-card)">
<rect x="420" y="575" width="340" height="100" rx="8" fill="url(#grad-card-purple)" stroke="#a855f7" stroke-opacity="0.4" stroke-width="1.2"/>
<rect x="420" y="575" width="340" height="2" rx="1" fill="url(#grad-main)" opacity="0.6"/>
<text x="590" y="600" font-family="'JetBrains Mono', monospace" font-size="14" font-weight="700" fill="url(#grad-main)" text-anchor="middle" filter="url(#glow-sm)">SurrealDB</text>
<text x="590" y="617" font-family="'Inter', sans-serif" font-size="9" fill="#ffffff" opacity="0.45" text-anchor="middle">Multi-Model Database · Multi-Tenant Scopes</text>
<g transform="translate(435, 630)">
<rect x="0" y="0" width="65" height="18" rx="3" fill="rgba(34,211,238,0.1)" stroke="#22d3ee" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="32" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#22d3ee" opacity="0.6" text-anchor="middle" dominant-baseline="central">Projects</text>
<rect x="75" y="0" width="50" height="18" rx="3" fill="rgba(168,85,247,0.1)" stroke="#a855f7" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="100" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#a855f7" opacity="0.6" text-anchor="middle" dominant-baseline="central">Tasks</text>
<rect x="135" y="0" width="55" height="18" rx="3" fill="rgba(236,72,153,0.1)" stroke="#ec4899" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="162" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#ec4899" opacity="0.6" text-anchor="middle" dominant-baseline="central">Agents</text>
<rect x="200" y="0" width="55" height="18" rx="3" fill="rgba(34,211,238,0.1)" stroke="#22d3ee" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="227" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#22d3ee" opacity="0.6" text-anchor="middle" dominant-baseline="central">Chunks</text>
<rect x="265" y="0" width="45" height="18" rx="3" fill="rgba(168,85,247,0.1)" stroke="#a855f7" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="287" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#a855f7" opacity="0.6" text-anchor="middle" dominant-baseline="central">A2A</text>
</g>
<!-- DB activity indicator -->
<g transform="translate(735, 590)">
<rect x="0" y="0" width="2" height="10" fill="#22d3ee" opacity="0.4">
<animate attributeName="height" values="6;12;6" dur="1.2s" repeatCount="indefinite"/>
</rect>
<rect x="5" y="0" width="2" height="8" fill="#a855f7" opacity="0.4">
<animate attributeName="height" values="8;14;8" dur="1.5s" repeatCount="indefinite"/>
</rect>
<rect x="10" y="0" width="2" height="12" fill="#ec4899" opacity="0.4">
<animate attributeName="height" values="10;16;10" dur="1s" repeatCount="indefinite"/>
</rect>
</g>
</g>
<!-- KG → SurrealDB -->
<line x1="320" y1="630" x2="420" y2="630" stroke="#22d3ee" stroke-width="2" stroke-opacity="0.2"/>
<use href="#particle-sm-cyan" opacity="0.6"><animateMotion dur="1.5s" repeatCount="indefinite" path="M 320 630 L 420 630"/></use>
<!-- NATS JetStream -->
<g filter="url(#glass-card)">
<rect x="860" y="575" width="340" height="100" rx="8" fill="url(#grad-card-pink)" stroke="#ec4899" stroke-opacity="0.35" stroke-width="2"/>
<rect x="860" y="575" width="340" height="1.5" rx="1" fill="#ec4899" opacity="0.5"/>
<text x="1030" y="600" font-family="'JetBrains Mono', monospace" font-size="14" font-weight="700" fill="#ec4899" text-anchor="middle" filter="url(#glow-sm)">NATS JetStream</text>
<text x="1030" y="617" font-family="'Inter', sans-serif" font-size="9" fill="#ffffff" opacity="0.45" text-anchor="middle">Message Queue · Async Coordination · Pub/Sub</text>
<g transform="translate(875, 630)">
<rect x="0" y="0" width="75" height="18" rx="3" fill="rgba(236,72,153,0.1)" stroke="#ec4899" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="37" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#ec4899" opacity="0.6" text-anchor="middle" dominant-baseline="central">Agent Jobs</text>
<rect x="85" y="0" width="75" height="18" rx="3" fill="rgba(34,211,238,0.1)" stroke="#22d3ee" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="122" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#22d3ee" opacity="0.6" text-anchor="middle" dominant-baseline="central">Workflows</text>
<rect x="170" y="0" width="70" height="18" rx="3" fill="rgba(168,85,247,0.1)" stroke="#a855f7" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="205" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#a855f7" opacity="0.6" text-anchor="middle" dominant-baseline="central">Proposals</text>
<rect x="250" y="0" width="60" height="18" rx="3" fill="rgba(236,72,153,0.1)" stroke="#ec4899" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="280" y="9" font-family="'Inter', sans-serif" font-size="7" fill="#ec4899" opacity="0.6" text-anchor="middle" dominant-baseline="central">A2A</text>
</g>
<!-- Message pulse animation -->
<g transform="translate(1125, 590)">
<circle r="4" fill="none" stroke="#ffffff" stroke-width="2" opacity="0.07">
<animate attributeName="r" values="3;8;3" dur="2s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="1;0.5;1" dur="2s" repeatCount="indefinite"/>
</circle>
<circle r="3" fill="#ffffff" opacity="0.07">
<animate attributeName="opacity" values="0.8;1;0.8" dur="2s" repeatCount="indefinite"/>
</circle>
</g>
</g>
<!-- SurrealDB ↔ NATS bridge line -->
<line x1="760" y1="625" x2="860" y2="625" stroke="url(#grad-purple-pink)" stroke-width="0.8" stroke-opacity="0.4" stroke-dasharray="4 3"/>
<!-- ═══════════════════════════════════════ -->
<!-- CONNECTIONS: Data → Providers -->
<!-- ═══════════════════════════════════════ -->
<!-- Central provider trunk (from LLM Router, already drawn) -->
<!-- Branch to each provider -->
<path id="path-to-claude" d="M 790 725 Q 790 750 500 750 L 245 750 Q 225 750 225 785" fill="none" stroke="#22d3ee" stroke-width="2" stroke-opacity="0.2"/>
<use href="#particle-sm-cyan" opacity="0.6"><animateMotion dur="2.5s" repeatCount="indefinite"><mpath href="#path-to-claude"/></animateMotion></use>
<path id="path-to-openai" d="M 790 725 Q 790 760 600 760 L 555 760 Q 545 760 545 785" fill="none" stroke="#a855f7" stroke-width="2" stroke-opacity="0.2"/>
<use href="#particle-sm-purple" opacity="0.6"><animateMotion dur="2s" repeatCount="indefinite"><mpath href="#path-to-openai"/></animateMotion></use>
<path id="path-to-gemini" d="M 790 725 Q 790 770 810 770 L 855 770 Q 865 770 865 785" fill="none" stroke="#ec4899" stroke-width="2" stroke-opacity="0.2"/>
<use href="#particle-sm-pink" opacity="0.6"><animateMotion dur="2.2s" repeatCount="indefinite"><mpath href="#path-to-gemini"/></animateMotion></use>
<path id="path-to-ollama" d="M 790 725 Q 790 750 900 750 L 1155 750 Q 1175 750 1175 785" fill="none" stroke="#22d3ee" stroke-width="2" stroke-opacity="0.2"/>
<use href="#particle-sm-cyan" opacity="0.6"><animateMotion dur="2.8s" repeatCount="indefinite"><mpath href="#path-to-ollama"/></animateMotion></use>
<!-- ═══════════════════════════════════════ -->
<!-- ROW 5: LLM PROVIDERS (y=810) -->
<!-- ═══════════════════════════════════════ -->
<!-- Claude -->
<g filter="url(#glass-card)">
<rect x="100" y="785" width="250" height="55" rx="6" fill="url(#grad-card-cyan)" stroke="#22d3ee" stroke-opacity="0.3" stroke-width="0.8"/>
<text x="225" y="810" font-family="'JetBrains Mono', monospace" font-size="12" font-weight="700" fill="#22d3ee" text-anchor="middle">Anthropic Claude</text>
<text x="225" y="827" font-family="'Inter', sans-serif" font-size="8" fill="#ffffff" opacity="0.4" text-anchor="middle">Opus · Sonnet · Haiku</text>
</g>
<!-- OpenAI -->
<g filter="url(#glass-card)">
<rect x="420" y="785" width="250" height="55" rx="6" fill="url(#grad-card-purple)" stroke="#a855f7" stroke-opacity="0.3" stroke-width="0.8"/>
<text x="545" y="810" font-family="'JetBrains Mono', monospace" font-size="12" font-weight="700" fill="#a855f7" text-anchor="middle">OpenAI</text>
<text x="545" y="827" font-family="'Inter', sans-serif" font-size="8" fill="#ffffff" opacity="0.4" text-anchor="middle">GPT-4 · GPT-4o · GPT-3.5</text>
</g>
<!-- Gemini -->
<g filter="url(#glass-card)">
<rect x="740" y="785" width="250" height="55" rx="6" fill="url(#grad-card-pink)" stroke="#ec4899" stroke-opacity="0.3" stroke-width="0.8"/>
<text x="865" y="810" font-family="'JetBrains Mono', monospace" font-size="12" font-weight="700" fill="#ec4899" text-anchor="middle">Google Gemini</text>
<text x="865" y="827" font-family="'Inter', sans-serif" font-size="8" fill="#ffffff" opacity="0.4" text-anchor="middle">2.0 Pro · Flash · 1.5 Pro</text>
</g>
<!-- Ollama -->
<g filter="url(#glass-card)">
<rect x="1060" y="785" width="250" height="55" rx="6" fill="url(#grad-card-cyan)" stroke="#22d3ee" stroke-opacity="0.3" stroke-width="0.8"/>
<text x="1185" y="810" font-family="'JetBrains Mono', monospace" font-size="12" font-weight="700" fill="#22d3ee" text-anchor="middle">Ollama (Local)</text>
<text x="1185" y="827" font-family="'Inter', sans-serif" font-size="8" fill="#ffffff" opacity="0.4" text-anchor="middle">Llama · Mistral · CodeLlama</text>
</g>
<!-- ═══════════════════════════════════════ -->
<!-- SUPPORTING CRATES (bottom strip) -->
<!-- ═══════════════════════════════════════ -->
<g transform="translate(0, 882)">
<rect x="60" y="0" width="1280" height="50" rx="6" fill="rgba(168,85,247,0.1)" stroke="#a855f7" stroke-opacity="0.2" stroke-width="0.5"/>
<text x="700" y="16" font-family="'JetBrains Mono', monospace" font-size="9" fill="#a855f7" opacity="0.7" text-anchor="middle" letter-spacing="2">SUPPORTING CRATES</text>
<g font-family="'Inter', sans-serif" font-size="10" opacity="0.6" text-anchor="middle">
<text x="130" y="36" fill="#22d3ee">vapora-shared</text>
<text x="260" y="36" fill="#a855f7">vapora-tracking</text>
<text x="400" y="36" fill="#ec4899">vapora-telemetry</text>
<text x="540" y="36" fill="#22d3ee">vapora-analytics</text>
<text x="680" y="36" fill="#a855f7">vapora-worktree</text>
<text x="820" y="36" fill="#ec4899">vapora-doc-lifecycle</text>
<text x="975" y="36" fill="#22d3ee">vapora-workflow-engine</text>
<text x="1140" y="36" fill="#a855f7">vapora-cli</text>
<text x="1250" y="36" fill="#ec4899">vapora-leptos-ui</text>
</g>
</g>
<!-- ═══════════════════════════════════════ -->
<!-- OBSERVABILITY STRIP (right edge) -->
<!-- ═══════════════════════════════════════ -->
<g transform="translate(1340, 80)">
<rect x="0" y="0" width="4" height="790" rx="2" fill="url(#grad-vertical)" opacity="0.3">
<animate attributeName="opacity" values="0.2;0.4;0.2" dur="5s" repeatCount="indefinite"/>
</rect>
<text x="15" y="400" font-family="'JetBrains Mono', monospace" font-size="9" fill="#a855f7" opacity="0.6" letter-spacing="2" text-anchor="middle" transform="rotate(90 15 400)">PROMETHEUS · GRAFANA · OPENTELEMETRY</text>
</g>
<!-- ═══════════════════════════════════════ -->
<!-- FOOTER -->
<!-- ═══════════════════════════════════════ -->
<text x="700" y="970" font-family="'JetBrains Mono', monospace" font-size="11" font-weight="700" fill="url(#grad-main)" text-anchor="middle" opacity="0.7" letter-spacing="3">VAPORA v1.2.0</text>
<text x="700" y="993" font-family="'Inter', sans-serif" font-size="9" fill="#a855f7" opacity="0.6" text-anchor="middle" letter-spacing="1">Evaporate complexity · Full-Stack Rust · Production Ready</text>
<!-- Bottom gradient bar -->
<rect x="400" y="1005" width="600" height="2" rx="1" fill="url(#grad-main)" opacity="0.3"/>
</svg>