- Complete fact-based memory API with mem0-inspired approach - Individual fact extraction and deduplication - ADD/UPDATE/DELETE memory actions - Precision search with 0.86+ similarity scores - MCP server for Claude Code integration - Neo4j graph relationships and PostgreSQL vector storage - Comprehensive documentation with architecture and API docs - Matrix communication integration - Production-ready Docker setup with Ollama and Supabase 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
353 lines
10 KiB
JavaScript
353 lines
10 KiB
JavaScript
// LangMem Documentation JavaScript
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Initialize all components
|
|
initializeNavigation();
|
|
initializeAnimations();
|
|
initializeDiagrams();
|
|
initializeCodeBlocks();
|
|
initializeSmoothScroll();
|
|
initializeProgressTracking();
|
|
});
|
|
|
|
// Navigation functionality
|
|
function initializeNavigation() {
|
|
const currentPath = window.location.pathname;
|
|
const navLinks = document.querySelectorAll('.nav-links a');
|
|
|
|
navLinks.forEach(link => {
|
|
if (link.getAttribute('href') === currentPath) {
|
|
link.classList.add('active');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Fade-in animations for cards
|
|
function initializeAnimations() {
|
|
const observerOptions = {
|
|
threshold: 0.1,
|
|
rootMargin: '0px 0px -100px 0px'
|
|
};
|
|
|
|
const observer = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('fade-in');
|
|
}
|
|
});
|
|
}, observerOptions);
|
|
|
|
document.querySelectorAll('.card, .phase-card, .diagram-container').forEach(el => {
|
|
observer.observe(el);
|
|
});
|
|
}
|
|
|
|
// Initialize Mermaid diagrams
|
|
function initializeDiagrams() {
|
|
if (typeof mermaid !== 'undefined') {
|
|
mermaid.initialize({
|
|
startOnLoad: true,
|
|
theme: 'default',
|
|
flowchart: {
|
|
useMaxWidth: true,
|
|
htmlLabels: true
|
|
},
|
|
securityLevel: 'loose'
|
|
});
|
|
}
|
|
}
|
|
|
|
// Code block enhancements
|
|
function initializeCodeBlocks() {
|
|
const codeBlocks = document.querySelectorAll('.code-block');
|
|
|
|
codeBlocks.forEach(block => {
|
|
// Add copy button
|
|
const copyBtn = document.createElement('button');
|
|
copyBtn.className = 'copy-btn';
|
|
copyBtn.innerHTML = '📋 Copy';
|
|
copyBtn.onclick = () => copyToClipboard(block.textContent, copyBtn);
|
|
|
|
const container = document.createElement('div');
|
|
container.className = 'code-container';
|
|
container.appendChild(copyBtn);
|
|
|
|
block.parentNode.insertBefore(container, block);
|
|
container.appendChild(block);
|
|
});
|
|
}
|
|
|
|
// Copy to clipboard functionality
|
|
function copyToClipboard(text, button) {
|
|
navigator.clipboard.writeText(text).then(() => {
|
|
const originalText = button.innerHTML;
|
|
button.innerHTML = '✅ Copied!';
|
|
setTimeout(() => {
|
|
button.innerHTML = originalText;
|
|
}, 2000);
|
|
});
|
|
}
|
|
|
|
// Smooth scrolling for anchor links
|
|
function initializeSmoothScroll() {
|
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
anchor.addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
const target = document.querySelector(this.getAttribute('href'));
|
|
if (target) {
|
|
target.scrollIntoView({
|
|
behavior: 'smooth',
|
|
block: 'start'
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Progress tracking for implementation phases
|
|
function initializeProgressTracking() {
|
|
const phaseCards = document.querySelectorAll('.phase-card');
|
|
const progressBar = document.querySelector('.progress-bar');
|
|
|
|
if (progressBar && phaseCards.length > 0) {
|
|
updateProgressBar();
|
|
}
|
|
}
|
|
|
|
function updateProgressBar() {
|
|
const totalPhases = document.querySelectorAll('.phase-card').length;
|
|
const completedPhases = document.querySelectorAll('.status-completed').length;
|
|
const progress = (completedPhases / totalPhases) * 100;
|
|
|
|
const progressBar = document.querySelector('.progress-fill');
|
|
if (progressBar) {
|
|
progressBar.style.width = `${progress}%`;
|
|
}
|
|
}
|
|
|
|
// Architecture diagram interactions
|
|
function showDiagramDetails(diagramId) {
|
|
const modal = document.getElementById('diagram-modal');
|
|
const content = document.getElementById('diagram-details');
|
|
|
|
const diagramDetails = {
|
|
'system-overview': {
|
|
title: 'System Architecture Overview',
|
|
description: 'This diagram shows the high-level architecture of the LangMem system, including the main components and their relationships.',
|
|
components: [
|
|
'LangMem SDK - Core memory management layer',
|
|
'Supabase - Vector storage with pgvector',
|
|
'Neo4j - Graph database for relationships',
|
|
'Ollama - Local LLM and embedding models',
|
|
'Docker Network - Container orchestration'
|
|
]
|
|
},
|
|
'data-flow': {
|
|
title: 'Data Flow Architecture',
|
|
description: 'Shows how data flows through the system during ingestion and retrieval operations.',
|
|
components: [
|
|
'Input Processing - Text chunking and preprocessing',
|
|
'Embedding Generation - Vector creation via Ollama',
|
|
'Storage Layer - Dual storage in Supabase and Neo4j',
|
|
'Retrieval Engine - Hybrid search capabilities',
|
|
'Context Assembly - Final context preparation'
|
|
]
|
|
}
|
|
};
|
|
|
|
const details = diagramDetails[diagramId];
|
|
if (details && modal && content) {
|
|
content.innerHTML = `
|
|
<h3>${details.title}</h3>
|
|
<p>${details.description}</p>
|
|
<ul>
|
|
${details.components.map(comp => `<li>${comp}</li>`).join('')}
|
|
</ul>
|
|
`;
|
|
modal.style.display = 'block';
|
|
}
|
|
}
|
|
|
|
function closeDiagramModal() {
|
|
const modal = document.getElementById('diagram-modal');
|
|
if (modal) {
|
|
modal.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
// Search functionality
|
|
function initializeSearch() {
|
|
const searchInput = document.querySelector('.search-input');
|
|
const searchResults = document.querySelector('.search-results');
|
|
|
|
if (searchInput && searchResults) {
|
|
searchInput.addEventListener('input', debounce(performSearch, 300));
|
|
}
|
|
}
|
|
|
|
function performSearch(event) {
|
|
const query = event.target.value.toLowerCase();
|
|
const searchResults = document.querySelector('.search-results');
|
|
|
|
if (query.length < 2) {
|
|
searchResults.style.display = 'none';
|
|
return;
|
|
}
|
|
|
|
// Simple search implementation
|
|
const searchableElements = document.querySelectorAll('h1, h2, h3, p, li');
|
|
const results = [];
|
|
|
|
searchableElements.forEach(element => {
|
|
if (element.textContent.toLowerCase().includes(query)) {
|
|
results.push({
|
|
title: element.textContent,
|
|
url: `#${element.id || ''}`,
|
|
type: element.tagName.toLowerCase()
|
|
});
|
|
}
|
|
});
|
|
|
|
displaySearchResults(results);
|
|
}
|
|
|
|
function displaySearchResults(results) {
|
|
const searchResults = document.querySelector('.search-results');
|
|
|
|
if (results.length === 0) {
|
|
searchResults.innerHTML = '<p>No results found</p>';
|
|
} else {
|
|
searchResults.innerHTML = results.map(result => `
|
|
<div class="search-result">
|
|
<a href="${result.url}">${result.title}</a>
|
|
<span class="result-type">${result.type}</span>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
searchResults.style.display = 'block';
|
|
}
|
|
|
|
// Utility functions
|
|
function debounce(func, wait) {
|
|
let timeout;
|
|
return function executedFunction(...args) {
|
|
const later = () => {
|
|
clearTimeout(timeout);
|
|
func(...args);
|
|
};
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(later, wait);
|
|
};
|
|
}
|
|
|
|
// Mobile menu toggle
|
|
function toggleMobileMenu() {
|
|
const navLinks = document.querySelector('.nav-links');
|
|
navLinks.classList.toggle('mobile-open');
|
|
}
|
|
|
|
// Theme toggle functionality
|
|
function toggleTheme() {
|
|
const body = document.body;
|
|
const currentTheme = body.getAttribute('data-theme');
|
|
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
|
|
|
body.setAttribute('data-theme', newTheme);
|
|
localStorage.setItem('theme', newTheme);
|
|
}
|
|
|
|
// Initialize theme from localStorage
|
|
function initializeTheme() {
|
|
const savedTheme = localStorage.getItem('theme') || 'light';
|
|
document.body.setAttribute('data-theme', savedTheme);
|
|
}
|
|
|
|
// Component status updates
|
|
function updateComponentStatus(componentId, status) {
|
|
const statusElement = document.querySelector(`[data-component="${componentId}"] .status`);
|
|
if (statusElement) {
|
|
statusElement.className = `status status-${status}`;
|
|
statusElement.textContent = status.replace('-', ' ').toUpperCase();
|
|
}
|
|
}
|
|
|
|
// Progress tracking for implementation
|
|
function trackImplementationProgress() {
|
|
const phases = {
|
|
'phase-1': 'in-progress',
|
|
'phase-2': 'planning',
|
|
'phase-3': 'planning',
|
|
'phase-4': 'planning'
|
|
};
|
|
|
|
Object.entries(phases).forEach(([phaseId, status]) => {
|
|
updateComponentStatus(phaseId, status);
|
|
});
|
|
}
|
|
|
|
// Add CSS for additional interactive elements
|
|
const additionalStyles = `
|
|
.copy-btn {
|
|
position: absolute;
|
|
top: 0.5rem;
|
|
right: 0.5rem;
|
|
background: var(--primary-color);
|
|
color: white;
|
|
border: none;
|
|
padding: 0.25rem 0.5rem;
|
|
border-radius: 0.25rem;
|
|
cursor: pointer;
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
.code-container {
|
|
position: relative;
|
|
}
|
|
|
|
.search-results {
|
|
position: absolute;
|
|
top: 100%;
|
|
left: 0;
|
|
right: 0;
|
|
background: white;
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 0.5rem;
|
|
box-shadow: var(--shadow-md);
|
|
display: none;
|
|
max-height: 300px;
|
|
overflow-y: auto;
|
|
z-index: 1000;
|
|
}
|
|
|
|
.search-result {
|
|
padding: 1rem;
|
|
border-bottom: 1px solid var(--border-color);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.search-result:hover {
|
|
background: var(--code-bg);
|
|
}
|
|
|
|
.mobile-open {
|
|
display: flex !important;
|
|
flex-direction: column;
|
|
position: absolute;
|
|
top: 100%;
|
|
left: 0;
|
|
right: 0;
|
|
background: var(--primary-color);
|
|
padding: 1rem;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.nav-links {
|
|
display: none;
|
|
}
|
|
}
|
|
`;
|
|
|
|
// Inject additional styles
|
|
const styleSheet = document.createElement('style');
|
|
styleSheet.textContent = additionalStyles;
|
|
document.head.appendChild(styleSheet); |