// Shared JavaScript across all pages class AgentBuilder { constructor() { this.components = []; this.connections = []; this.selectedComponent = null; this.dragging = false; this.dragOffset = { x: 0, y: 0 }; this.initializeEventListeners(); } initializeEventListeners() { const canvas = document.getElementById('canvas'); // Drag start from toolbox document.querySelectorAll('.toolbox-item').forEach(item => { item.addEventListener('dragstart', (e) => { e.dataTransfer.setData('text/plain', e.target.closest('.toolbox-item').dataset.type); }); }); // Drop on canvas canvas.addEventListener('dragover', (e) => { e.preventDefault(); canvas.classList.add('border-blue-500'); }); canvas.addEventListener('dragleave', () => { canvas.classList.remove('border-blue-500'); }); canvas.addEventListener('drop', (e) => { e.preventDefault(); canvas.classList.remove('border-blue-500'); const type = e.dataTransfer.getData('text/plain'); const rect = canvas.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; this.addComponent(type, x, y); }); // Canvas interactions canvas.addEventListener('mousedown', (e) => { const component = e.target.closest('.canvas-component'); if (component) { this.selectComponent(component); if (e.target.classList.contains('component-handle')) { this.startDragging(component, e); } } else { this.deselectComponent(); } }); document.addEventListener('mousemove', (e) => { if (this.dragging) { this.dragComponent(e); } }); document.addEventListener('mouseup', () => { this.dragging = false; }); } addComponent(type, x, y) { const id = `comp-${Date.now()}`; const component = { id, type, x, y, properties: this.getDefaultProperties(type) }; const element = document.createElement('div'); element.className = 'canvas-component'; element.id = id; element.style.left = `${x}px`; element.style.top = `${y}px`; element.innerHTML = this.getComponentHTML(type, id); document.getElementById('canvas').appendChild(element); this.components.push(component); // Add event listeners to the new component element.addEventListener('dblclick', () => this.showProperties(component)); this.addConnectionPoints(element, id); } getComponentHTML(type, id) { const templates = { 'react-agent': `
React Agent
Reasoning engine
`, 'tool': `
Tool
Function tool
`, 'prompt': `
Prompt Template
Chat setup
`, 'memory': `
Memory
State storage
` }; return templates[type] || '
Unknown Component
'; } addConnectionPoints(element, id) { const inputPoint = document.createElement('div'); inputPoint.className = 'connection-point input'; inputPoint.dataset.component = id; inputPoint.dataset.type = 'input'; const outputPoint = document.createElement('div'); outputPoint.className = 'connection-point output'; outputPoint.dataset.component = id; outputPoint.dataset.type = 'output'; element.appendChild(inputPoint); element.appendChild(outputPoint); } getDefaultProperties(type) { const defaults = { 'react-agent': { name: 'react_agent', model: 'gpt-4', temperature: 0.7 }, 'tool': { name: 'custom_tool', description: 'A custom function tool', function: 'def tool_function(input):\n return "processed: " + input' }, 'prompt': { template: 'You are a helpful assistant. Answer the following question: {question}', variables: ['question'] }, 'memory': { type: 'MemorySaver', checkpoint_ttl: 3600 } }; return defaults[type] || {}; } selectComponent(componentElement) { this.deselectComponent(); componentElement.classList.add('selected'); this.selectedComponent = this.components.find(c => c.id === componentElement.id); this.showProperties(this.selectedComponent); } deselectComponent() { document.querySelectorAll('.canvas-component.selected').forEach(el => { el.classList.remove('selected'); }); this.selectedComponent = null; this.hideProperties(); } startDragging(componentElement, e) { this.dragging = true; const rect = componentElement.getBoundingClientRect(); const canvasRect = document.getElementById('canvas').getBoundingClientRect(); this.dragOffset = { x: e.clientX - rect.left + canvasRect.left, y: e.clientY - rect.top + canvasRect.top }; } dragComponent(e) { if (!this.selectedComponent) return; const canvasRect = document.getElementById('canvas').getBoundingClientRect(); const x = e.clientX - this.dragOffset.x; const y = e.clientY - this.dragOffset.y; const componentElement = document.getElementById(this.selectedComponent.id); componentElement.style.left = `${x}px`; componentElement.style.top = `${y}px`; this.selectedComponent.x = x; this.selectedComponent.y = y; } showProperties(component) { const panel = document.getElementById('properties-panel'); const content = document.getElementById('properties-content'); panel.classList.remove('hidden'); content.innerHTML = this.generatePropertiesForm(component); // Update properties on input change content.querySelectorAll('input, textarea').forEach(input => { input.addEventListener('change', (e) => { component.properties[e.target.name] = e.target.value; }); }); } hideProperties() { document.getElementById('properties-panel').classList.add('hidden'); } generatePropertiesForm(component) { const properties = component.properties; let html = `

${component.type.replace('-', ' ')} Properties

`; Object.keys(properties).forEach(key => { const value = properties[key]; const isTextarea = typeof value === 'string' && value.includes('\n'); html += `
${isTextarea ? `` : `` }
`; }); return html; } exportToPython() { let code = `# Generated by AgentFlow Studio\n`; code += `from langchain_core.messages import HumanMessage, ToolMessage\n`; code += `from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n`; code += `from langgraph.graph import StateGraph, END\n`; code += `from langgraph.checkpoint.memory import MemorySaver\n`; code += `from pydantic import BaseModel, Field\n`; code += `from langchain.agents import create_react_agent\n\n`; // Add component definitions this.components.forEach(comp => { code += `# ${comp.type} component\n`; switch(comp.type) { case 'react-agent': code += `agent = create_react_agent(\n`; code += ` model="${comp.properties.model}",\n`; code += ` temperature=${comp.properties.temperature}\n`; code += `)\n\n`; break; case 'tool': code += `class ${comp.properties.name.replace('_', ' ').title().replace(' ', '')}Tool(BaseModel):\n`; code += ` \"\"\"${comp.properties.description}\"\"\"\n\n`; code += ` def execute(self, input: str) -> str:\n`; code += ` ${comp.properties.function.replace('\n', '\n ')}\n\n`; break; case 'prompt': code += `prompt_template = ChatPromptTemplate.from_template(\n`; code += ` \"\"\"${comp.properties.template}\"\"\"\n`; code += `)\n\n`; break; case 'memory': code += `memory = MemorySaver()\n\n`; break; } }); // Add graph construction code += `# Build the agent graph\n`; code += `graph_builder = StateGraph()\n\n`; code += `# Export the final agent\n`; code += `def get_agent():\n`; code += ` return graph_builder.compile()\n`; return code; } } // Global functions for UI interactions function startNewProject() { const builder = new AgentBuilder(); window.agentBuilder = builder; document.getElementById('canvas').innerHTML = ''; document.getElementById('properties-panel').classList.add('hidden'); } function loadSample() { startNewProject(); // Add sample components window.agentBuilder.addComponent('react-agent', 100, 100); window.agentBuilder.addComponent('tool', 300, 100); window.agentBuilder.addComponent('prompt', 100, 200); window.agentBuilder.addComponent('memory', 300, 200); } function loadExample(exampleType) { startNewProject(); switch(exampleType) { case 'research': // Research Assistant Example const researchAgent = window.agentBuilder.addComponent('react-agent', 100, 100); const webSearchTool = window.agentBuilder.addComponent('tool', 300, 100); const researchPrompt = window.agentBuilder.addComponent('prompt', 100, 200); const researchMemory = window.agentBuilder.addComponent('memory', 300, 200); // Configure components const researchComponents = window.agentBuilder.components; researchComponents.find(c => c.id === researchAgent).properties = { name: 'research_assistant', model: 'gpt-4', temperature: 0.3, max_tokens: 2000 }; researchComponents.find(c => c.id === webSearchTool).properties = { name: 'web_search', description: 'Search the web for current information', function: 'def web_search(query):\n # Implementation for web search\n return f"Searched for: {query}"' }; researchComponents.find(c => c.id === researchPrompt).properties = { template: 'You are a research assistant. Search for information about: {topic}. Provide detailed, well-sourced answers.', variables: ['topic'] }; researchComponents.find(c => c.id === researchMemory).properties = { type: 'MemorySaver', checkpoint_ttl: 7200 }; break; case 'ecommerce': // E-commerce Assistant Example const ecomAgent = window.agentBuilder.addComponent('react-agent', 100, 100); const productSearch = window.agentBuilder.addComponent('tool', 300, 100); const priceCompare = window.agentBuilder.addComponent('tool', 500, 100); const ecomPrompt = window.agentBuilder.addComponent('prompt', 100, 200); const ecomMemory = window.agentBuilder.addComponent('memory', 300, 200); const ecomComponents = window.agentBuilder.components; ecomComponents.find(c => c.id === ecomAgent).properties = { name: 'ecommerce_assistant', model: 'gpt-4', temperature: 0.2, max_tokens: 1500 }; ecomComponents.find(c => c.id === productSearch).properties = { name: 'product_search', description: 'Search for products in the catalog', function: 'def product_search(category, keywords):\n # Search product database\n return f"Products in {category} matching {keywords}"' }; ecomComponents.find(c => c.id === priceCompare).properties = { name: 'price_comparison', description: 'Compare prices across different vendors', function: 'def price_comparison(product_id):\n # Get price comparisons\n return f"Price comparison for product {product_id}"' }; ecomComponents.find(c => c.id === ecomPrompt).properties = { template: 'You are an e-commerce assistant. Help customers find products and compare prices. Be helpful and concise.', variables: ['user_query'] }; ecomComponents.find(c => c.id === ecomMemory).properties = { type: 'MemorySaver', checkpoint_ttl: 3600 }; break; case 'code': // Code Assistant Example const codeAgent = window.agentBuilder.addComponent('react-agent', 100, 100); const codeGenerator = window.agentBuilder.addComponent('tool', 300, 100); const debuggerTool = window.agentBuilder.addComponent('tool', 500, 100); const codePrompt = window.agentBuilder.addComponent('prompt', 100, 200); const codeMemory = window.agentBuilder.addComponent('memory', 300, 200); const codeComponents = window.agentBuilder.components; codeComponents.find(c => c.id === codeAgent).properties = { name: 'code_assistant', model: 'gpt-4', temperature: 0.1, max_tokens: 3000 }; codeComponents.find(c => c.id === codeGenerator).properties = { name: 'code_generation', description: 'Generate code based on requirements', function: 'def generate_code(language, requirements):\n # Generate code implementation\n return f"Generated {language} code for: {requirements}"' }; codeComponents.find(c => c.id === debuggerTool).properties = { name: 'debug_code', description: 'Help debug and fix code issues', function: 'def debug_code(code, error):\n # Debug code implementation\n return f"Debugged code with error: {error}"' }; codeComponents.find(c => c.id === codePrompt).properties = { template: 'You are a programming assistant. Help with code generation, debugging, and explanations. Provide clear, working code examples.', variables: ['programming_task'] }; codeComponents.find(c => c.id === codeMemory).properties = { type: 'MemorySaver', checkpoint_ttl: 4800 }; break; case 'support': // Customer Support Example const supportAgent = window.agentBuilder.addComponent('react-agent', 100, 100); const faqSearch = window.agentBuilder.addComponent('tool', 300, 100); const ticketCreator = window.agentBuilder.addComponent('tool', 500, 100); const supportPrompt = window.agentBuilder.addComponent('prompt', 100, 200); const supportMemory = window.agentBuilder.addComponent('memory', 300, 200); const supportComponents = window.agentBuilder.components; supportComponents.find(c => c.id === supportAgent).properties = { name: 'support_agent', model: 'gpt-4', temperature: 0.4, max_tokens: 1200 }; supportComponents.find(c => c.id === faqSearch).properties = { name: 'faq_search', description: 'Search the FAQ database for answers', function: 'def search_faq(question):\n # Search FAQ database\n return f"FAQ results for: {question}"' }; supportComponents.find(c => c.id === ticketCreator).properties = { name: 'create_ticket', description: 'Create a support ticket for escalation', function: 'def create_ticket(issue, priority):\n # Create support ticket\n return f"Created {priority} ticket for: {issue}"' }; supportComponents.find(c => c.id === supportPrompt).properties = { template: 'You are a customer support agent. Be empathetic and helpful. Use FAQs when possible, escalate when needed.', variables: ['customer_issue'] }; supportComponents.find(c => c.id === supportMemory).properties = { type: 'MemorySaver', checkpoint_ttl: 2400 }; break; case 'analyst': // Data Analyst Example const analystAgent = window.agentBuilder.addComponent('react-agent', 100, 100); const dataProcessor = window.agentBuilder.addComponent('tool', 300, 100); const statsAnalyzer = window.agentBuilder.addComponent('tool', 500, 100); const analystPrompt = window.agentBuilder.addComponent('prompt', 100, 200); const analystMemory = window.agentBuilder.addComponent('memory', 300, 200); const analystComponents = window.agentBuilder.components; analystComponents.find(c => c.id === analystAgent).properties = { name: 'data_analyst', model: 'gpt-4', temperature: 0.2, max_tokens: 2500 }; analystComponents.find(c => c.id === dataProcessor).properties = { name: 'process_data', description: 'Process and clean datasets', function: 'def process_data(dataset, operations):\n # Process data implementation\n return f"Processed dataset with: {operations}"' }; analystComponents.find(c => c.id === statsAnalyzer).properties = { name: 'analyze_statistics', description: 'Perform statistical analysis on data', function: 'def analyze_stats(data, metrics):\n # Statistical analysis\n return f"Analysis results for metrics: {metrics}"' }; analystComponents.find(c => c.id === analystPrompt).properties = { template: 'You are a data analyst. Help analyze datasets, generate insights, and create visualizations. Be precise and data-driven.', variables: ['analysis_request'] }; analystComponents.find(c => c.id === analystMemory).properties = { type: 'MemorySaver', checkpoint_ttl: 6000 }; break; case 'translator': // Multi-language Translator Example const translatorAgent = window.agentBuilder.addComponent('react-agent', 100, 100); const translateTool = window.agentBuilder.addComponent('tool', 300, 100); const contextTool = window.agentBuilder.addComponent('tool', 500, 100); const translatorPrompt = window.agentBuilder.addComponent('prompt', 100, 200); const translatorMemory = window.agentBuilder.addComponent('memory', 300, 200); const translatorComponents = window.agentBuilder.components; translatorComponents.find(c => c.id === translatorAgent).properties = { name: 'translator', model: 'gpt-4', temperature: 0.3, max_tokens: 1800 }; translatorComponents.find(c => c.id === translateTool).properties = { name: 'translate_text', description: 'Translate text between languages', function: 'def translate(text, source_lang, target_lang):\n # Translation implementation\n return f"Translated from {source_lang} to {target_lang}: {text}"' }; translatorComponents.find(c => c.id === contextTool).properties = { name: 'preserve_context', description: 'Maintain context and cultural nuances', function: 'def preserve_context(translation, context):\n # Context preservation\n return f"Context-preserved translation: {translation}"' }; translatorComponents.find(c => c.id === translatorPrompt).properties = { template: 'You are a multilingual translator. Translate text while preserving meaning, context, and cultural nuances. Support multiple languages.', variables: ['text_to_translate', 'target_language'] }; translatorComponents.find(c => c.id === translatorMemory).properties = { type: 'MemorySaver', checkpoint_ttl: 5400 }; break; } // Update the UI to show the loaded example document.getElementById('properties-panel').classList.add('hidden'); // Show success message showNotification(`Loaded ${exampleType.replace(/_/g, ' ')} example successfully!`, 'success'); } function exportAgent() { if (!window.agentBuilder || window.agentBuilder.components.length === 0) { showNotification('Please add some components to the canvas first!', 'error'); return; } const code = window.agentBuilder.exportToPython(); showCodeModal(code); } function clearCanvas() { if (confirm('Are you sure you want to clear the canvas?')) { document.getElementById('canvas').innerHTML = ''; document.getElementById('properties-panel').classList.add('hidden'); if (window.agentBuilder) { window.agentBuilder.components = []; window.agentBuilder.connections = []; } showNotification('Canvas cleared successfully!', 'success'); } } function showCodeModal(code) { const modal = document.createElement('div'); modal.className = 'modal-overlay'; modal.innerHTML = ` `; document.body.appendChild(modal); feather.replace(); window.copyCode = function() { navigator.clipboard.writeText(code).then(() => { alert('Code copied to clipboard!'); }); }; window.downloadCode = function() { const blob = new Blob([code], { type: 'text/python' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'langchain_agent.py'; a.click(); URL.revokeObjectURL(url); }; } // Notification system function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `fixed top-4 right-4 z-50 p-4 rounded-lg shadow-lg transition-all duration-300 transform translate-x-full ${ type === 'success' ? 'bg-green-600' : type === 'error' ? 'bg-red-600' : 'bg-blue-600' } text-white`; notification.innerHTML = `
${message}
`; document.body.appendChild(notification); // Animate in setTimeout(() => { notification.style.transform = 'translateX(0)'; }, 100); // Animate out and remove setTimeout(() => { notification.style.transform = 'translateX(full)'; setTimeout(() => { if (notification.parentNode) { notification.parentNode.removeChild(notification); } }, 300); }, 3000); feather.replace(); } // Initialize the app when page loads document.addEventListener('DOMContentLoaded', () => { window.agentBuilder = new AgentBuilder(); feather.replace(); // Check for example parameter in URL const urlParams = new URLSearchParams(window.location.search); const example = urlParams.get('example'); if (example && ['research', 'ecommerce', 'code', 'support', 'analyst', 'translator'].includes(example)) { // Small delay to ensure everything is loaded setTimeout(() => { loadExample(example); }, 500); } }); console.log('AgentFlow Studio loaded');