Skip to main content
Glama

CodeGraph CLI MCP Server

by Jakedismo
agent-context-gathering-flow.html67.3 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CodeGraph Agent Context Gathering Flow</title> <style> :root { /* Color scheme based on spec */ --mcp-layer: #3B82F6; --react-color: #10B981; --lats-color: #8B5CF6; --graph-tools: #F59E0B; --data-layer: #6B7280; --llm-layer: #EC4899; /* Dark theme (default) */ --bg-primary: #0f172a; --bg-secondary: #1e293b; --bg-tertiary: #334155; --bg-glass: rgba(30, 41, 59, 0.7); --text-primary: #f1f5f9; --text-secondary: #94a3b8; --text-muted: #64748b; --border-color: rgba(148, 163, 184, 0.2); --border-glass: rgba(148, 163, 184, 0.1); --shadow-glass: 0 8px 32px rgba(0, 0, 0, 0.3); --backdrop-blur: blur(12px); } [data-theme="light"] { --bg-primary: #f8fafc; --bg-secondary: #ffffff; --bg-tertiary: #f1f5f9; --bg-glass: rgba(255, 255, 255, 0.7); --text-primary: #0f172a; --text-secondary: #475569; --text-muted: #64748b; --border-color: rgba(71, 85, 105, 0.2); --border-glass: rgba(71, 85, 105, 0.1); --shadow-glass: 0 8px 32px rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; background: var(--bg-primary); color: var(--text-primary); min-height: 100vh; line-height: 1.6; } /* Breadcrumb Navigation */ .breadcrumb { padding: 1rem 2rem; background: var(--bg-glass); backdrop-filter: var(--backdrop-blur); border-bottom: 1px solid var(--border-glass); font-size: 0.875rem; } .breadcrumb a { color: var(--text-secondary); text-decoration: none; transition: color 0.2s; } .breadcrumb a:hover { color: var(--mcp-layer); } .breadcrumb span { color: var(--text-muted); margin: 0 0.5rem; } .breadcrumb .current { color: var(--text-primary); font-weight: 500; } /* Header */ header { text-align: center; padding: 2rem; background: linear-gradient(135deg, rgba(59, 130, 246, 0.1), rgba(139, 92, 246, 0.1)); border-bottom: 1px solid var(--border-glass); } h1 { font-size: 2rem; font-weight: 700; background: linear-gradient(135deg, var(--mcp-layer), var(--lats-color)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; margin-bottom: 0.5rem; } .subtitle { color: var(--text-secondary); font-size: 1rem; } /* Controls */ .controls { display: flex; justify-content: center; gap: 0.75rem; padding: 1.5rem; flex-wrap: wrap; background: var(--bg-glass); backdrop-filter: var(--backdrop-blur); border-bottom: 1px solid var(--border-glass); position: sticky; top: 0; z-index: 100; } .btn { padding: 0.5rem 1rem; border: 1px solid var(--border-color); border-radius: 8px; background: var(--bg-glass); backdrop-filter: var(--backdrop-blur); color: var(--text-primary); cursor: pointer; font-size: 0.8rem; font-weight: 500; transition: all 0.2s ease; } .btn:hover { border-color: var(--mcp-layer); box-shadow: 0 0 12px rgba(59, 130, 246, 0.2); } .btn.active { background: var(--mcp-layer); border-color: var(--mcp-layer); color: white; box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4); } .btn-group { display: flex; gap: 0.25rem; padding: 0.25rem; background: var(--bg-tertiary); border-radius: 10px; } .btn-group .btn { border: none; border-radius: 6px; } /* Main Layout */ .main-container { display: flex; gap: 1.5rem; padding: 1.5rem; max-width: 1800px; margin: 0 auto; } .diagram-area { flex: 1; min-width: 0; } .sidebar { width: 320px; flex-shrink: 0; } /* Glassmorphism Panels */ .glass-panel { background: var(--bg-glass); backdrop-filter: var(--backdrop-blur); border: 1px solid var(--border-glass); border-radius: 16px; padding: 1.25rem; box-shadow: var(--shadow-glass); margin-bottom: 1rem; } .glass-panel h3 { font-size: 0.9rem; font-weight: 600; color: var(--text-primary); margin-bottom: 1rem; display: flex; align-items: center; gap: 0.5rem; } .glass-panel h3::before { content: ''; width: 3px; height: 16px; background: linear-gradient(to bottom, var(--mcp-layer), var(--lats-color)); border-radius: 2px; } /* Legend */ .legend-item { display: flex; align-items: center; gap: 0.75rem; padding: 0.5rem 0; font-size: 0.8rem; border-bottom: 1px solid var(--border-glass); cursor: pointer; transition: all 0.2s; } .legend-item:last-child { border-bottom: none; } .legend-item:hover { padding-left: 0.5rem; } .legend-color { width: 20px; height: 20px; border-radius: 6px; flex-shrink: 0; } .legend-item.mcp .legend-color { background: var(--mcp-layer); } .legend-item.react .legend-color { background: var(--react-color); } .legend-item.lats .legend-color { background: var(--lats-color); } .legend-item.tools .legend-color { background: var(--graph-tools); } .legend-item.data .legend-color { background: var(--data-layer); } .legend-item.llm .legend-color { background: var(--llm-layer); } /* Comparison Table */ .comparison-table { width: 100%; border-collapse: collapse; font-size: 0.75rem; } .comparison-table th, .comparison-table td { padding: 0.5rem; text-align: left; border-bottom: 1px solid var(--border-glass); } .comparison-table th { color: var(--text-muted); font-weight: 500; text-transform: uppercase; font-size: 0.65rem; letter-spacing: 0.05em; } .comparison-table .react-col { color: var(--react-color); } .comparison-table .lats-col { color: var(--lats-color); } /* Tool Details */ .tool-detail { padding: 0.75rem; background: var(--bg-tertiary); border-radius: 8px; margin-bottom: 0.5rem; } .tool-detail h4 { font-size: 0.8rem; font-weight: 600; color: var(--graph-tools); margin-bottom: 0.25rem; } .tool-detail p { font-size: 0.7rem; color: var(--text-secondary); } /* SVG Diagram */ .diagram-svg { width: 100%; height: auto; border-radius: 16px; background: var(--bg-secondary); border: 1px solid var(--border-glass); overflow: visible; } /* Layer styles */ .layer-group { transition: opacity 0.3s ease, transform 0.3s ease; } .layer-group.dimmed { opacity: 0.2; } .layer-group.highlighted { filter: brightness(1.1); } /* Node styles */ .node-box { rx: 12; ry: 12; transition: all 0.3s ease; } .node-box:hover { filter: brightness(1.15); cursor: pointer; } .node-box.selected { stroke-width: 3; filter: drop-shadow(0 0 12px currentColor); } .node-text { font-family: inherit; font-size: 11px; fill: var(--text-primary); font-weight: 600; pointer-events: none; } .node-subtext { font-family: inherit; font-size: 9px; fill: var(--text-secondary); pointer-events: none; } /* Animated arrows */ .flow-arrow { stroke-width: 2; fill: none; stroke-dasharray: 8, 4; animation: flowAnimation 1.5s linear infinite; } .flow-arrow.react { stroke: var(--react-color); } .flow-arrow.lats { stroke: var(--lats-color); } .flow-arrow.shared { stroke: var(--graph-tools); } @keyframes flowAnimation { to { stroke-dashoffset: -24; } } .flow-arrow.paused { animation-play-state: paused; } /* Tool tooltip */ .tool-tooltip { position: fixed; background: var(--bg-glass); backdrop-filter: var(--backdrop-blur); border: 1px solid var(--border-glass); border-radius: 12px; padding: 1rem; max-width: 280px; box-shadow: var(--shadow-glass); z-index: 1000; pointer-events: none; opacity: 0; transform: translateY(10px); transition: all 0.2s ease; } .tool-tooltip.visible { opacity: 1; transform: translateY(0); } .tool-tooltip h4 { font-size: 0.9rem; font-weight: 600; color: var(--graph-tools); margin-bottom: 0.5rem; } .tool-tooltip p { font-size: 0.75rem; color: var(--text-secondary); margin-bottom: 0.5rem; } .tool-tooltip .params { font-size: 0.7rem; color: var(--text-muted); font-family: monospace; background: var(--bg-tertiary); padding: 0.5rem; border-radius: 6px; } /* Theme toggle */ .theme-toggle { position: fixed; top: 1rem; right: 1rem; z-index: 200; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 1.25rem; box-shadow: var(--shadow-glass); } /* Print styles */ @media print { .controls, .theme-toggle, .breadcrumb { display: none; } .main-container { display: block; } .sidebar { width: 100%; display: flex; gap: 1rem; flex-wrap: wrap; } .glass-panel { page-break-inside: avoid; background: white; border: 1px solid #ddd; } body { background: white; color: black; } .diagram-svg { max-height: 60vh; } } /* Responsive */ @media (max-width: 1200px) { .main-container { flex-direction: column; } .sidebar { width: 100%; display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem; } .glass-panel { margin-bottom: 0; } } @media (max-width: 768px) { h1 { font-size: 1.5rem; } .controls { gap: 0.5rem; } .btn { font-size: 0.7rem; padding: 0.4rem 0.75rem; } } /* Agent Flow Sections */ .section-label { font-size: 13px; font-weight: 700; fill: var(--text-primary); text-anchor: middle; } .phase-label { font-size: 9px; font-weight: 500; fill: var(--text-muted); } /* Glassmorphism effect for SVG */ .glass-rect { fill: var(--bg-glass); stroke: var(--border-glass); stroke-width: 1; rx: 16; ry: 16; } </style> </head> <body> <button class="btn theme-toggle" onclick="toggleTheme()" title="Toggle theme"> <span id="themeIcon">&#9790;</span> </button> <nav class="breadcrumb"> <a href="./codegraph-architecture.html">Architecture</a> <span>/</span> <span class="current">Agent Context Gathering Flow</span> </nav> <header> <h1>Agent Context Gathering Flow</h1> <p class="subtitle">How CodeGraph ReAct and LATS agents use graph tools to answer queries</p> </header> <div class="controls"> <div class="btn-group"> <button class="btn active" data-filter="all" onclick="filterLayer('all')">All Layers</button> <button class="btn" data-filter="mcp" onclick="filterLayer('mcp')">MCP Entry</button> <button class="btn" data-filter="react" onclick="filterLayer('react')">ReAct Flow</button> <button class="btn" data-filter="lats" onclick="filterLayer('lats')">LATS Flow</button> <button class="btn" data-filter="tools" onclick="filterLayer('tools')">Graph Tools</button> <button class="btn" data-filter="data" onclick="filterLayer('data')">Data Layer</button> </div> <div class="btn-group"> <button class="btn active" data-view="flow" onclick="setView('flow')">Flow View</button> <button class="btn" data-view="comparison" onclick="setView('comparison')">Comparison</button> </div> <button class="btn" onclick="toggleAnimation()"> <span id="animToggle">Pause Animation</span> </button> </div> <div class="main-container"> <div class="diagram-area"> <svg class="diagram-svg" viewBox="0 0 1400 1100" xmlns="http://www.w3.org/2000/svg"> <defs> <!-- Gradients --> <linearGradient id="mcpGrad" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" style="stop-color:#3B82F6;stop-opacity:0.2"/> <stop offset="100%" style="stop-color:#3B82F6;stop-opacity:0.05"/> </linearGradient> <linearGradient id="reactGrad" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" style="stop-color:#10B981;stop-opacity:0.2"/> <stop offset="100%" style="stop-color:#10B981;stop-opacity:0.05"/> </linearGradient> <linearGradient id="latsGrad" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" style="stop-color:#8B5CF6;stop-opacity:0.2"/> <stop offset="100%" style="stop-color:#8B5CF6;stop-opacity:0.05"/> </linearGradient> <linearGradient id="toolsGrad" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" style="stop-color:#F59E0B;stop-opacity:0.2"/> <stop offset="100%" style="stop-color:#F59E0B;stop-opacity:0.05"/> </linearGradient> <linearGradient id="dataGrad" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" style="stop-color:#6B7280;stop-opacity:0.2"/> <stop offset="100%" style="stop-color:#6B7280;stop-opacity:0.05"/> </linearGradient> <linearGradient id="llmGrad" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" style="stop-color:#EC4899;stop-opacity:0.2"/> <stop offset="100%" style="stop-color:#EC4899;stop-opacity:0.05"/> </linearGradient> <!-- Arrow markers --> <marker id="arrowReact" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto"> <path d="M0,0 L0,6 L9,3 z" fill="#10B981"/> </marker> <marker id="arrowLats" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto"> <path d="M0,0 L0,6 L9,3 z" fill="#8B5CF6"/> </marker> <marker id="arrowShared" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto"> <path d="M0,0 L0,6 L9,3 z" fill="#F59E0B"/> </marker> <marker id="arrowMcp" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto"> <path d="M0,0 L0,6 L9,3 z" fill="#3B82F6"/> </marker> </defs> <!-- ============================================ --> <!-- LAYER 1: MCP Entry Layer --> <!-- ============================================ --> <g class="layer-group" data-layer="mcp"> <rect x="30" y="30" width="1340" height="140" fill="url(#mcpGrad)" stroke="#3B82F6" stroke-width="1" rx="16" ry="16"/> <text class="section-label" x="700" y="55" fill="#3B82F6">MCP Entry Layer</text> <!-- MCP Client --> <g class="node" data-node="mcp-client" onclick="selectNode('mcp-client')"> <rect class="node-box" x="50" y="75" width="120" height="70" fill="#1e293b" stroke="#3B82F6" stroke-width="2"/> <text class="node-text" x="110" y="105" text-anchor="middle">MCP Client</text> <text class="node-subtext" x="110" y="125" text-anchor="middle">Claude Desktop</text> <text class="node-subtext" x="110" y="137" text-anchor="middle">Cursor, etc.</text> </g> <!-- 7 Agentic MCP Tools --> <g class="node" data-node="agentic-tools" onclick="selectNode('agentic-tools')"> <rect class="node-box" x="220" y="65" width="700" height="85" fill="#1e293b" stroke="#3B82F6" stroke-width="2"/> <text class="node-text" x="570" y="90" text-anchor="middle">7 Agentic MCP Tools</text> <text class="node-subtext" x="280" y="115" text-anchor="start">agentic_code_search</text> <text class="node-subtext" x="420" y="115" text-anchor="start">agentic_dependency_analysis</text> <text class="node-subtext" x="600" y="115" text-anchor="start">agentic_call_chain_analysis</text> <text class="node-subtext" x="785" y="115" text-anchor="start">agentic_architecture_analysis</text> <text class="node-subtext" x="280" y="135" text-anchor="start">agentic_api_surface_analysis</text> <text class="node-subtext" x="470" y="135" text-anchor="start">agentic_context_builder</text> <text class="node-subtext" x="650" y="135" text-anchor="start">agentic_semantic_question</text> </g> <!-- CodeGraphExecutor --> <g class="node" data-node="executor" onclick="selectNode('executor')"> <rect class="node-box" x="970" y="75" width="180" height="70" fill="#1e293b" stroke="#3B82F6" stroke-width="2"/> <text class="node-text" x="1060" y="100" text-anchor="middle">CodeGraphExecutor</text> <text class="node-subtext" x="1060" y="118" text-anchor="middle">Detects architecture</text> <text class="node-subtext" x="1060" y="132" text-anchor="middle">Manages timeout</text> </g> <!-- Arrows --> <path class="flow-arrow shared" d="M170,110 L215,110" marker-end="url(#arrowMcp)"/> <path class="flow-arrow shared" d="M920,107 L965,107" marker-end="url(#arrowMcp)"/> </g> <!-- ============================================ --> <!-- LAYER 2: Architecture Selection --> <!-- ============================================ --> <g class="layer-group" data-layer="selection"> <rect x="400" y="185" width="600" height="75" fill="url(#mcpGrad)" stroke="#3B82F6" stroke-width="1" rx="12" ry="12"/> <g class="node" data-node="factory" onclick="selectNode('factory')"> <rect class="node-box" x="420" y="195" width="260" height="55" fill="#1e293b" stroke="#3B82F6" stroke-width="2"/> <text class="node-text" x="550" y="218" text-anchor="middle">AgentExecutorFactory</text> <text class="node-subtext" x="550" y="238" text-anchor="middle">CODEGRAPH_AGENT_ARCHITECTURE env var</text> </g> <!-- Branch arrows --> <g class="node" data-node="react-select" onclick="highlightPath('react')"> <rect class="node-box" x="720" y="195" width="120" height="55" fill="#1e293b" stroke="#10B981" stroke-width="2"/> <text class="node-text" x="780" y="218" text-anchor="middle" fill="#10B981">ReAct</text> <text class="node-subtext" x="780" y="236" text-anchor="middle">(default)</text> </g> <g class="node" data-node="lats-select" onclick="highlightPath('lats')"> <rect class="node-box" x="860" y="195" width="120" height="55" fill="#1e293b" stroke="#8B5CF6" stroke-width="2"/> <text class="node-text" x="920" y="218" text-anchor="middle" fill="#8B5CF6">LATS</text> <text class="node-subtext" x="920" y="236" text-anchor="middle">(experimental)</text> </g> <path class="flow-arrow shared" d="M1060,145 L700,185" marker-end="url(#arrowMcp)"/> <path class="flow-arrow react" d="M680,222 L715,222" marker-end="url(#arrowReact)"/> <path class="flow-arrow lats" d="M840,222 L855,222" marker-end="url(#arrowLats)"/> </g> <!-- ============================================ --> <!-- LAYER 3A: ReAct Agent Flow (Left) --> <!-- ============================================ --> <g class="layer-group" data-layer="react"> <rect x="30" y="280" width="640" height="400" fill="url(#reactGrad)" stroke="#10B981" stroke-width="1" rx="16" ry="16"/> <text class="section-label" x="350" y="305" fill="#10B981">ReAct Agent Flow (Linear Iterative)</text> <!-- CodeGraphAgentBuilder --> <g class="node" data-node="agent-builder" onclick="selectNode('agent-builder')"> <rect class="node-box" x="50" y="325" width="180" height="90" fill="#1e293b" stroke="#10B981" stroke-width="2"/> <text class="node-text" x="140" y="350" text-anchor="middle">CodeGraphAgentBuilder</text> <text class="node-subtext" x="140" y="370" text-anchor="middle">CodeGraphChatAdapter</text> <text class="node-subtext" x="140" y="385" text-anchor="middle">TierAwarePromptPlugin</text> <text class="node-subtext" x="140" y="400" text-anchor="middle">SlidingWindowMemory (40)</text> </g> <!-- TierAwareReActAgent --> <g class="node" data-node="tier-react" onclick="selectNode('tier-react')"> <rect class="node-box" x="270" y="325" width="180" height="90" fill="#1e293b" stroke="#10B981" stroke-width="2"/> <text class="node-text" x="360" y="350" text-anchor="middle">TierAwareReActAgent</text> <text class="node-subtext" x="360" y="370" text-anchor="middle">max_turns by tier:</text> <text class="node-subtext" x="360" y="385" text-anchor="middle">Small:5 Med:10</text> <text class="node-subtext" x="360" y="400" text-anchor="middle">Large:15 Massive:20</text> </g> <!-- AutoAgents Framework --> <g class="node" data-node="autoagents" onclick="selectNode('autoagents')"> <rect class="node-box" x="490" y="325" width="160" height="90" fill="#1e293b" stroke="#10B981" stroke-width="2"/> <text class="node-text" x="570" y="350" text-anchor="middle">AutoAgents</text> <text class="node-subtext" x="570" y="370" text-anchor="middle">ReActAgent</text> <text class="node-subtext" x="570" y="385" text-anchor="middle">Thought-Action-Obs</text> <text class="node-subtext" x="570" y="400" text-anchor="middle">ToolT trait</text> </g> <!-- React cycle visualization --> <g class="node" data-node="react-cycle" onclick="selectNode('react-cycle')"> <rect class="node-box" x="100" y="440" width="500" height="85" fill="#1e293b" stroke="#10B981" stroke-width="2"/> <text class="node-text" x="350" y="465" text-anchor="middle">Iterative Thought-Action-Observation Cycle</text> <!-- Cycle boxes --> <rect x="120" y="480" width="90" height="35" rx="6" fill="#10B981" opacity="0.2" stroke="#10B981"/> <text class="node-subtext" x="165" y="502" text-anchor="middle" fill="#10B981">1. Thought</text> <rect x="230" y="480" width="90" height="35" rx="6" fill="#10B981" opacity="0.3" stroke="#10B981"/> <text class="node-subtext" x="275" y="502" text-anchor="middle" fill="#10B981">2. Action</text> <rect x="340" y="480" width="100" height="35" rx="6" fill="#10B981" opacity="0.4" stroke="#10B981"/> <text class="node-subtext" x="390" y="502" text-anchor="middle" fill="#10B981">3. Observation</text> <rect x="460" y="480" width="120" height="35" rx="6" fill="#10B981" opacity="0.5" stroke="#10B981"/> <text class="node-subtext" x="520" y="502" text-anchor="middle" fill="#10B981">4. Repeat/End</text> </g> <!-- Tool Execution Path --> <g class="node" data-node="react-tool-path" onclick="selectNode('react-tool-path')"> <rect class="node-box" x="100" y="545" width="500" height="60" fill="#1e293b" stroke="#10B981" stroke-width="2"/> <text class="node-text" x="350" y="570" text-anchor="middle">Tool Execution: AutoAgents ToolT</text> <text class="node-subtext" x="350" y="590" text-anchor="middle">Serde deserializes params (APPLIES DEFAULTS) -> GraphToolExecutorAdapter -> GraphToolExecutor</text> </g> <!-- Arrows --> <path class="flow-arrow react" d="M780,250 L350,280" marker-end="url(#arrowReact)"/> <path class="flow-arrow react" d="M230,370 L265,370" marker-end="url(#arrowReact)"/> <path class="flow-arrow react" d="M450,370 L485,370" marker-end="url(#arrowReact)"/> <path class="flow-arrow react" d="M570,415 L570,435" marker-end="url(#arrowReact)"/> <path class="flow-arrow react" d="M350,525 L350,540" marker-end="url(#arrowReact)"/> </g> <!-- ============================================ --> <!-- LAYER 3B: LATS Agent Flow (Right) --> <!-- ============================================ --> <g class="layer-group" data-layer="lats"> <rect x="690" y="280" width="680" height="400" fill="url(#latsGrad)" stroke="#8B5CF6" stroke-width="1" rx="16" ry="16"/> <text class="section-label" x="1030" y="305" fill="#8B5CF6">LATS Agent Flow (Tree Search)</text> <!-- LATSExecutor --> <g class="node" data-node="lats-executor" onclick="selectNode('lats-executor')"> <rect class="node-box" x="710" y="325" width="180" height="90" fill="#1e293b" stroke="#8B5CF6" stroke-width="2"/> <text class="node-text" x="800" y="350" text-anchor="middle">LATSExecutor</text> <text class="node-subtext" x="800" y="370" text-anchor="middle">Manages search tree</text> <text class="node-subtext" x="800" y="385" text-anchor="middle">4-phase algorithm</text> <text class="node-subtext" x="800" y="400" text-anchor="middle">UCT exploration</text> </g> <!-- 4 Phases --> <g class="node" data-node="lats-phases" onclick="selectNode('lats-phases')"> <rect class="node-box" x="920" y="325" width="420" height="170" fill="#1e293b" stroke="#8B5CF6" stroke-width="2"/> <text class="node-text" x="1130" y="350" text-anchor="middle">4-Phase Algorithm</text> <!-- Phase 1: Selection --> <rect x="940" y="365" width="180" height="50" rx="8" fill="#8B5CF6" opacity="0.15" stroke="#8B5CF6"/> <text class="node-subtext" x="945" y="382" fill="#8B5CF6" font-weight="600">Phase 1: Selection</text> <text class="node-subtext" x="945" y="398">UCT algorithm selects leaves</text> <text class="node-subtext" x="945" y="410">exploration_weight = sqrt(2)</text> <!-- Phase 2: Expansion --> <rect x="1140" y="365" width="180" height="50" rx="8" fill="#8B5CF6" opacity="0.25" stroke="#8B5CF6"/> <text class="node-subtext" x="1145" y="382" fill="#8B5CF6" font-weight="600">Phase 2: Expansion</text> <text class="node-subtext" x="1145" y="398">LLM generates actions</text> <text class="node-subtext" x="1145" y="410">Direct executor call</text> <!-- Phase 3: Evaluation --> <rect x="940" y="425" width="180" height="50" rx="8" fill="#8B5CF6" opacity="0.35" stroke="#8B5CF6"/> <text class="node-subtext" x="945" y="442" fill="#8B5CF6" font-weight="600">Phase 3: Evaluation</text> <text class="node-subtext" x="945" y="458">LLM scores quality</text> <text class="node-subtext" x="945" y="470">is_solution detection</text> <!-- Phase 4: Backpropagation --> <rect x="1140" y="425" width="180" height="50" rx="8" fill="#8B5CF6" opacity="0.45" stroke="#8B5CF6"/> <text class="node-subtext" x="1145" y="442" fill="#8B5CF6" font-weight="600">Phase 4: Backprop</text> <text class="node-subtext" x="1145" y="458">Updates ancestor scores</text> <text class="node-subtext" x="1145" y="470">0.7*max + 0.3*avg</text> </g> <!-- Termination Conditions --> <g class="node" data-node="lats-termination" onclick="selectNode('lats-termination')"> <rect class="node-box" x="710" y="520" width="200" height="75" fill="#1e293b" stroke="#8B5CF6" stroke-width="2"/> <text class="node-text" x="810" y="545" text-anchor="middle">Termination</text> <text class="node-subtext" x="810" y="563" text-anchor="middle">Solution found</text> <text class="node-subtext" x="810" y="577" text-anchor="middle">High score (>0.9)</text> <text class="node-subtext" x="810" y="591" text-anchor="middle">Tree size / Timeout</text> </g> <!-- Synthesis --> <g class="node" data-node="lats-synthesis" onclick="selectNode('lats-synthesis')"> <rect class="node-box" x="940" y="520" width="200" height="75" fill="#1e293b" stroke="#8B5CF6" stroke-width="2"/> <text class="node-text" x="1040" y="545" text-anchor="middle">Synthesis</text> <text class="node-subtext" x="1040" y="563" text-anchor="middle">Extract best path</text> <text class="node-subtext" x="1040" y="577" text-anchor="middle">LLM synthesizes answer</text> </g> <!-- Tool Execution Path --> <g class="node" data-node="lats-tool-path" onclick="selectNode('lats-tool-path')"> <rect class="node-box" x="1160" y="520" width="190" height="75" fill="#1e293b" stroke="#8B5CF6" stroke-width="2"/> <text class="node-text" x="1255" y="545" text-anchor="middle">Tool Execution</text> <text class="node-subtext" x="1255" y="563" text-anchor="middle">Direct tool_executor</text> <text class="node-subtext" x="1255" y="577" text-anchor="middle">NO serde defaults</text> <text class="node-subtext" x="1255" y="591" text-anchor="middle">(manual defaults)</text> </g> <!-- Arrows --> <path class="flow-arrow lats" d="M920,250 L1030,280" marker-end="url(#arrowLats)"/> <path class="flow-arrow lats" d="M890,370 L915,370" marker-end="url(#arrowLats)"/> <path class="flow-arrow lats" d="M800,415 L800,515" marker-end="url(#arrowLats)"/> <path class="flow-arrow lats" d="M910,560 L935,560" marker-end="url(#arrowLats)"/> </g> <!-- ============================================ --> <!-- LAYER 4: Graph Tools (Shared) --> <!-- ============================================ --> <g class="layer-group" data-layer="tools"> <rect x="30" y="700" width="1340" height="170" fill="url(#toolsGrad)" stroke="#F59E0B" stroke-width="1" rx="16" ry="16"/> <text class="section-label" x="700" y="725" fill="#F59E0B">Graph Tools Layer (7 Tools - Shared by Both Agents)</text> <!-- semantic_code_search (Primary) --> <g class="node tool-node" data-node="semantic_code_search" data-tool="semantic_code_search" onclick="selectNode('semantic_code_search')"> <rect class="node-box" x="50" y="745" width="180" height="110" fill="#1e293b" stroke="#F59E0B" stroke-width="2"/> <text class="node-text" x="140" y="770" text-anchor="middle" fill="#F59E0B">semantic_code_search</text> <text class="node-subtext" x="140" y="790" text-anchor="middle">PRIMARY DISCOVERY</text> <text class="node-subtext" x="140" y="808" text-anchor="middle">query: String</text> <text class="node-subtext" x="140" y="823" text-anchor="middle">limit: 10 (default)</text> <text class="node-subtext" x="140" y="838" text-anchor="middle">threshold: 0.6</text> </g> <!-- get_transitive_dependencies --> <g class="node tool-node" data-node="get_transitive_dependencies" data-tool="get_transitive_dependencies" onclick="selectNode('get_transitive_dependencies')"> <rect class="node-box" x="250" y="745" width="170" height="110" fill="#1e293b" stroke="#F59E0B" stroke-width="2"/> <text class="node-text" x="335" y="770" text-anchor="middle">get_transitive_deps</text> <text class="node-subtext" x="335" y="790" text-anchor="middle">Forward dependencies</text> <text class="node-subtext" x="335" y="808" text-anchor="middle">node_id: String</text> <text class="node-subtext" x="335" y="823" text-anchor="middle">edge_type: Calls</text> <text class="node-subtext" x="335" y="838" text-anchor="middle">depth: 3 (default)</text> </g> <!-- get_reverse_dependencies --> <g class="node tool-node" data-node="get_reverse_dependencies" data-tool="get_reverse_dependencies" onclick="selectNode('get_reverse_dependencies')"> <rect class="node-box" x="440" y="745" width="170" height="110" fill="#1e293b" stroke="#F59E0B" stroke-width="2"/> <text class="node-text" x="525" y="770" text-anchor="middle">get_reverse_deps</text> <text class="node-subtext" x="525" y="790" text-anchor="middle">What depends on this</text> <text class="node-subtext" x="525" y="808" text-anchor="middle">node_id: String</text> <text class="node-subtext" x="525" y="823" text-anchor="middle">edge_type: Calls</text> <text class="node-subtext" x="525" y="838" text-anchor="middle">depth: 3 (default)</text> </g> <!-- trace_call_chain --> <g class="node tool-node" data-node="trace_call_chain" data-tool="trace_call_chain" onclick="selectNode('trace_call_chain')"> <rect class="node-box" x="630" y="745" width="160" height="110" fill="#1e293b" stroke="#F59E0B" stroke-width="2"/> <text class="node-text" x="710" y="770" text-anchor="middle">trace_call_chain</text> <text class="node-subtext" x="710" y="790" text-anchor="middle">Execution flow</text> <text class="node-subtext" x="710" y="808" text-anchor="middle">node_id: String</text> <text class="node-subtext" x="710" y="823" text-anchor="middle">max_depth: 5</text> </g> <!-- detect_cycles --> <g class="node tool-node" data-node="detect_cycles" data-tool="detect_cycles" onclick="selectNode('detect_cycles')"> <rect class="node-box" x="810" y="745" width="150" height="110" fill="#1e293b" stroke="#F59E0B" stroke-width="2"/> <text class="node-text" x="885" y="770" text-anchor="middle">detect_cycles</text> <text class="node-subtext" x="885" y="790" text-anchor="middle">Circular deps</text> <text class="node-subtext" x="885" y="808" text-anchor="middle">edge_type: Calls</text> </g> <!-- calculate_coupling --> <g class="node tool-node" data-node="calculate_coupling" data-tool="calculate_coupling" onclick="selectNode('calculate_coupling')"> <rect class="node-box" x="980" y="745" width="160" height="110" fill="#1e293b" stroke="#F59E0B" stroke-width="2"/> <text class="node-text" x="1060" y="770" text-anchor="middle">calculate_coupling</text> <text class="node-subtext" x="1060" y="790" text-anchor="middle">Coupling metrics</text> <text class="node-subtext" x="1060" y="808" text-anchor="middle">node_id: String</text> <text class="node-subtext" x="1060" y="823" text-anchor="middle">Ca, Ce, Instability</text> </g> <!-- get_hub_nodes --> <g class="node tool-node" data-node="get_hub_nodes" data-tool="get_hub_nodes" onclick="selectNode('get_hub_nodes')"> <rect class="node-box" x="1160" y="745" width="150" height="110" fill="#1e293b" stroke="#F59E0B" stroke-width="2"/> <text class="node-text" x="1235" y="770" text-anchor="middle">get_hub_nodes</text> <text class="node-subtext" x="1235" y="790" text-anchor="middle">Highly connected</text> <text class="node-subtext" x="1235" y="808" text-anchor="middle">min_degree: 5</text> </g> <!-- Arrows from both agents to tools --> <path class="flow-arrow react" d="M350,610 L350,695" marker-end="url(#arrowShared)"/> <path class="flow-arrow lats" d="M1255,595 L1255,695" marker-end="url(#arrowShared)"/> </g> <!-- ============================================ --> <!-- LAYER 5: Data Layer --> <!-- ============================================ --> <g class="layer-group" data-layer="data"> <rect x="300" y="890" width="800" height="90" fill="url(#dataGrad)" stroke="#6B7280" stroke-width="1" rx="16" ry="16"/> <text class="section-label" x="700" y="915" fill="#6B7280">Data Layer</text> <!-- GraphToolExecutor --> <g class="node" data-node="graph-executor" onclick="selectNode('graph-executor')"> <rect class="node-box" x="320" y="925" width="180" height="45" fill="#1e293b" stroke="#6B7280" stroke-width="2"/> <text class="node-text" x="410" y="952" text-anchor="middle">GraphToolExecutor</text> </g> <!-- SurrealDB --> <g class="node" data-node="surrealdb" onclick="selectNode('surrealdb')"> <rect class="node-box" x="550" y="925" width="250" height="45" fill="#1e293b" stroke="#EC4899" stroke-width="2"/> <text class="node-text" x="675" y="945" text-anchor="middle" fill="#EC4899">SurrealDB</text> <text class="node-subtext" x="675" y="962" text-anchor="middle">HNSW Vector Index + Graph Traversal</text> </g> <!-- LLM Providers --> <g class="node" data-node="llm-providers" onclick="selectNode('llm-providers')"> <rect class="node-box" x="850" y="925" width="230" height="45" fill="#1e293b" stroke="#EC4899" stroke-width="2"/> <text class="node-text" x="965" y="945" text-anchor="middle" fill="#EC4899">LLM Providers</text> <text class="node-subtext" x="965" y="962" text-anchor="middle">Anthropic | OpenAI | Ollama | xAI</text> </g> <!-- Arrows --> <path class="flow-arrow shared" d="M700,855 L700,885" marker-end="url(#arrowShared)"/> <path class="flow-arrow shared" d="M500,947 L545,947" marker-end="url(#arrowShared)"/> </g> <!-- ============================================ --> <!-- LLM Connection Lines --> <!-- ============================================ --> <g class="layer-group" data-layer="llm"> <!-- ReAct to LLM --> <path class="flow-arrow react" d="M570,325 C570,310 965,310 965,920" stroke-dasharray="4,4" opacity="0.5"/> <!-- LATS to LLM --> <path class="flow-arrow lats" d="M1130,495 C1200,600 1000,800 965,920" stroke-dasharray="4,4" opacity="0.5"/> </g> </svg> </div> <div class="sidebar"> <div class="glass-panel"> <h3>Layer Legend</h3> <div class="legend-item mcp" onclick="filterLayer('mcp')"> <div class="legend-color"></div> <span>MCP Entry Layer</span> </div> <div class="legend-item react" onclick="filterLayer('react')"> <div class="legend-color"></div> <span>ReAct Flow (Green)</span> </div> <div class="legend-item lats" onclick="filterLayer('lats')"> <div class="legend-color"></div> <span>LATS Flow (Purple)</span> </div> <div class="legend-item tools" onclick="filterLayer('tools')"> <div class="legend-color"></div> <span>Graph Tools (Orange)</span> </div> <div class="legend-item data" onclick="filterLayer('data')"> <div class="legend-color"></div> <span>Data Layer (Gray)</span> </div> <div class="legend-item llm" onclick="filterLayer('llm')"> <div class="legend-color"></div> <span>LLM Layer (Pink)</span> </div> </div> <div class="glass-panel" id="comparisonPanel"> <h3>Architecture Comparison</h3> <table class="comparison-table"> <thead> <tr> <th>Aspect</th> <th class="react-col">ReAct</th> <th class="lats-col">LATS</th> </tr> </thead> <tbody> <tr> <td>Architecture</td> <td class="react-col">Linear iterative</td> <td class="lats-col">Tree search</td> </tr> <tr> <td>Tool Execution</td> <td class="react-col">Via ToolT (serde)</td> <td class="lats-col">Direct executor</td> </tr> <tr> <td>Memory</td> <td class="react-col">Sliding (40 msg)</td> <td class="lats-col">Search tree</td> </tr> <tr> <td>Termination</td> <td class="react-col">max_turns</td> <td class="lats-col">Score/Solution</td> </tr> <tr> <td>Use Case</td> <td class="react-col">Fast, reliable</td> <td class="lats-col">Deep exploration</td> </tr> <tr> <td>Status</td> <td class="react-col">Production</td> <td class="lats-col">Experimental</td> </tr> </tbody> </table> </div> <div class="glass-panel" id="detailPanel"> <h3>Component Details</h3> <div id="detailContent"> <p style="color: var(--text-secondary); font-size: 0.85rem;"> Click on any component to see details about its role in the context gathering flow. </p> </div> </div> <div class="glass-panel"> <h3>Tier Configuration</h3> <table class="comparison-table"> <thead> <tr> <th>Tier</th> <th>Context</th> <th>Steps</th> <th>Tokens</th> </tr> </thead> <tbody> <tr> <td>Small</td> <td>&lt;50K</td> <td>5</td> <td>2,048</td> </tr> <tr> <td>Medium</td> <td>50K-150K</td> <td>10</td> <td>4,096</td> </tr> <tr> <td>Large</td> <td>150K-500K</td> <td>15</td> <td>8,192</td> </tr> <tr> <td>Massive</td> <td>&gt;500K</td> <td>20</td> <td>16,384</td> </tr> </tbody> </table> </div> </div> </div> <!-- Tooltip --> <div class="tool-tooltip" id="tooltip"></div> <script> // Component data const componentData = { 'mcp-client': { title: 'MCP Client', description: 'External MCP clients like Claude Desktop or Cursor that invoke agentic tools via the MCP protocol.', details: ['Sends tool requests', 'Receives structured responses', 'Handles progress notifications'] }, 'agentic-tools': { title: '7 Agentic MCP Tools', description: 'High-level tools exposed via MCP that trigger multi-step agent workflows.', details: [ 'agentic_code_search - Autonomous graph exploration', 'agentic_dependency_analysis - Dependency chain analysis', 'agentic_call_chain_analysis - Execution flow tracing', 'agentic_architecture_analysis - Architectural assessment', 'agentic_api_surface_analysis - Public interface analysis', 'agentic_context_builder - Comprehensive context gathering', 'agentic_semantic_question - Complex Q&A' ] }, 'executor': { title: 'CodeGraphExecutor', description: 'Main orchestrator that detects agent architecture and manages execution with timeout enforcement.', details: [ 'Detects architecture via CODEGRAPH_AGENT_ARCHITECTURE env', 'Creates executor via AgentExecutorFactory', 'Default timeout: 300 seconds', 'Handles context overflow errors' ] }, 'factory': { title: 'AgentExecutorFactory', description: 'Factory for creating architecture-specific executors based on configuration.', details: [ 'Creates ReActExecutor (default)', 'Creates LATSExecutor (if feature enabled)', 'Detects tier from LLM config' ] }, 'agent-builder': { title: 'CodeGraphAgentBuilder', description: 'Builder for tier-aware CodeGraph agents with graph analysis tools.', details: [ 'Creates CodeGraphChatAdapter for LLM bridging', 'Configures TierAwarePromptPlugin', 'Sets up SlidingWindowMemory (40 messages)', 'Registers 7 Arc-wrapped graph tools' ] }, 'tier-react': { title: 'TierAwareReActAgent', description: 'Wrapper that overrides max_turns based on context tier.', details: [ 'Small (<50K): 5 max turns', 'Medium (50K-150K): 10 max turns', 'Large (150K-500K): 15 max turns', 'Massive (>500K): 20 max turns' ] }, 'autoagents': { title: 'AutoAgents Framework', description: 'External ReActAgent implementation from AutoAgents crate.', details: [ 'Implements Thought-Action-Observation cycle', 'Calls tools via ToolT trait', 'Serde deserializes params (applies defaults!)', 'Manages agent memory and context' ] }, 'react-cycle': { title: 'ReAct Cycle', description: 'Iterative reasoning cycle: Thought -> Action -> Observation -> Repeat/End', details: [ '1. Thought: LLM reasons about next step', '2. Action: Select and call a graph tool', '3. Observation: Receive tool result', '4. Repeat until max_turns or answer found' ] }, 'react-tool-path': { title: 'ReAct Tool Execution Path', description: 'How ReAct executes graph tools through AutoAgents ToolT trait.', details: [ 'AutoAgents ToolT trait invoked', 'Serde deserializes params (applies #[serde(default)])', 'GraphToolExecutorAdapter (sync wrapper)', 'GraphToolExecutor.execute() async call', 'SurrealDB function execution' ] }, 'lats-executor': { title: 'LATSExecutor', description: 'Language Agent Tree Search executor implementing 4-phase algorithm.', details: [ 'Manages SearchTree data structure', 'UCT exploration with sqrt(2) weight', 'Beam width: 3, Max depth: 5', 'Per-iteration timeout: 60 seconds' ] }, 'lats-phases': { title: 'LATS 4-Phase Algorithm', description: 'Four phases executed iteratively to explore solution space.', details: [ 'Selection: UCT algorithm picks promising leaves', 'Expansion: LLM generates thought-action pairs', 'Evaluation: LLM scores node quality (0.0-1.0)', 'Backpropagation: Update ancestors (0.7*max + 0.3*avg)' ] }, 'lats-termination': { title: 'LATS Termination', description: 'Conditions that end the LATS search.', details: [ 'is_solution flag set by evaluation', 'High score threshold (>0.9)', 'Tree size limit (beam_width * max_depth * 2)', 'Per-iteration timeout' ] }, 'lats-synthesis': { title: 'LATS Synthesis', description: 'Final answer generation from best search path.', details: [ 'Extract best path from tree', 'Collect nodes along path', 'LLM synthesizes final answer', 'Returns CodeGraphAgentOutput' ] }, 'lats-tool-path': { title: 'LATS Tool Execution', description: 'How LATS executes graph tools directly without AutoAgents wrapper.', details: [ 'Direct tool_executor.execute() call', 'NO serde deserialization', 'Must handle defaults manually in executor', 'This is why defaults were added to GraphToolExecutor' ] }, 'semantic_code_search': { title: 'semantic_code_search', description: 'Primary code discovery tool using hybrid search with graph-traversal.', details: [ 'query: String - Natural language search query', 'limit: i32 - Max results (default: 10)', 'threshold: f64 - Similarity (default: 0.6)', 'Returns relevant code with node IDs for further analysis' ] }, 'get_transitive_dependencies': { title: 'get_transitive_dependencies', description: 'Get all transitive dependencies of a code node up to specified depth.', details: [ 'node_id: String - Node to analyze (e.g., "nodes:123")', 'edge_type: String - Calls, Imports, Uses, etc. (default: Calls)', 'depth: i32 - Max traversal depth (default: 3)', 'Follows dependency edges recursively' ] }, 'get_reverse_dependencies': { title: 'get_reverse_dependencies', description: 'Get all nodes that depend on the specified node.', details: [ 'node_id: String - Node to analyze', 'edge_type: String - Dependency type (default: Calls)', 'depth: i32 - Max depth (default: 3)', 'Useful for impact analysis' ] }, 'trace_call_chain': { title: 'trace_call_chain', description: 'Trace execution flow from a starting function through all called functions.', details: [ 'node_id: String - Starting node', 'max_depth: i32 - Max trace depth (default: 5)', 'Returns call sequence with file paths and line numbers' ] }, 'detect_cycles': { title: 'detect_cycles', description: 'Detect circular dependencies and cycles in the codebase graph.', details: [ 'edge_type: String - Type to check (default: Calls)', 'Returns all detected cycles', 'Important for architectural health' ] }, 'calculate_coupling': { title: 'calculate_coupling', description: 'Calculate afferent/efferent coupling and instability metrics.', details: [ 'node_id: String - Node to analyze', 'Returns Ca (afferent), Ce (efferent), Instability', 'Instability = Ce / (Ca + Ce)' ] }, 'get_hub_nodes': { title: 'get_hub_nodes', description: 'Find highly connected hub nodes in the dependency graph.', details: [ 'min_degree: i32 - Minimum connections (default: 5)', 'Returns nodes with high connectivity', 'Important for identifying central components' ] }, 'graph-executor': { title: 'GraphToolExecutor', description: 'Routes tool calls to SurrealDB graph functions.', details: [ 'Matches tool name to SurrealDB function', 'Handles parameter validation and defaults', 'Executes async queries', 'Formats and returns results' ] }, 'surrealdb': { title: 'SurrealDB', description: 'Graph database with HNSW vector index for semantic search.', details: [ 'HNSW index: 2-5ms query latency', 'Native graph traversal functions', 'Full-text search capabilities', 'Transactional operations' ] }, 'llm-providers': { title: 'LLM Providers', description: 'Multiple LLM providers for agent reasoning.', details: [ 'Anthropic Claude', 'OpenAI GPT', 'Ollama (local)', 'xAI Grok', 'LM Studio (local)' ] } }; let selectedNode = null; let animationPaused = false; let currentFilter = 'all'; // Filter layers function filterLayer(layer) { currentFilter = layer; const layers = document.querySelectorAll('.layer-group'); // Update buttons document.querySelectorAll('[data-filter]').forEach(btn => { btn.classList.toggle('active', btn.dataset.filter === layer); }); if (layer === 'all') { layers.forEach(l => l.classList.remove('dimmed')); } else { layers.forEach(l => { const layerName = l.dataset.layer; const shouldShow = layerName === layer || (layer === 'react' && (layerName === 'selection' || layerName === 'tools' || layerName === 'data')) || (layer === 'lats' && (layerName === 'selection' || layerName === 'tools' || layerName === 'data')); l.classList.toggle('dimmed', !shouldShow); }); } } // Highlight path function highlightPath(agent) { filterLayer(agent); } // Select node function selectNode(nodeId) { // Remove previous selection document.querySelectorAll('.node-box.selected').forEach(n => n.classList.remove('selected')); // Add selection const node = document.querySelector(`[data-node="${nodeId}"] .node-box`); if (node) { node.classList.add('selected'); } selectedNode = nodeId; updateDetailPanel(nodeId); } // Update detail panel function updateDetailPanel(nodeId) { const data = componentData[nodeId]; if (!data) return; const detailContent = document.getElementById('detailContent'); detailContent.innerHTML = ` <h4 style="color: var(--graph-tools); margin-bottom: 0.5rem;">${data.title}</h4> <p style="color: var(--text-secondary); font-size: 0.85rem; margin-bottom: 0.75rem;">${data.description}</p> <ul style="list-style: none; padding: 0;"> ${data.details.map(d => ` <li style="font-size: 0.75rem; color: var(--text-muted); padding: 0.25rem 0; border-bottom: 1px solid var(--border-glass);"> ${d} </li> `).join('')} </ul> `; } // Toggle animation function toggleAnimation() { animationPaused = !animationPaused; document.querySelectorAll('.flow-arrow').forEach(arrow => { arrow.classList.toggle('paused', animationPaused); }); document.getElementById('animToggle').textContent = animationPaused ? 'Resume Animation' : 'Pause Animation'; } // Set view function setView(view) { document.querySelectorAll('[data-view]').forEach(btn => { btn.classList.toggle('active', btn.dataset.view === view); }); // For comparison view, we could show a side-by-side layout // For now, just toggle visibility const comparison = document.getElementById('comparisonPanel'); if (view === 'comparison') { comparison.style.display = 'block'; filterLayer('all'); } } // Theme toggle function toggleTheme() { const body = document.body; const currentTheme = body.getAttribute('data-theme'); const newTheme = currentTheme === 'light' ? '' : 'light'; body.setAttribute('data-theme', newTheme); document.getElementById('themeIcon').textContent = newTheme === 'light' ? '&#9728;' : '&#9790;'; } // Initialize theme from system preference if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) { document.body.setAttribute('data-theme', 'light'); document.getElementById('themeIcon').textContent = '&#9728;'; } // Tool tooltips const toolNodes = document.querySelectorAll('.tool-node'); const tooltip = document.getElementById('tooltip'); toolNodes.forEach(node => { node.addEventListener('mouseenter', (e) => { const toolName = node.dataset.tool; const data = componentData[toolName]; if (!data) return; tooltip.innerHTML = ` <h4>${data.title}</h4> <p>${data.description}</p> <div class="params">${data.details.slice(0, 3).join('<br>')}</div> `; const rect = node.getBoundingClientRect(); tooltip.style.left = `${rect.right + 10}px`; tooltip.style.top = `${rect.top}px`; tooltip.classList.add('visible'); }); node.addEventListener('mouseleave', () => { tooltip.classList.remove('visible'); }); }); </script> </body> </html>

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jakedismo/codegraph-rust'

If you have feedback or need assistance with the MCP directory API, please join our Discord server