| | |
| | 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'); |
| | |
| | |
| | document.querySelectorAll('.toolbox-item').forEach(item => { |
| | item.addEventListener('dragstart', (e) => { |
| | e.dataTransfer.setData('text/plain', e.target.closest('.toolbox-item').dataset.type); |
| | }); |
| | }); |
| |
|
| | |
| | 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.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); |
| | |
| | |
| | element.addEventListener('dblclick', () => this.showProperties(component)); |
| | |
| | this.addConnectionPoints(element, id); |
| | } |
| |
|
| | getComponentHTML(type, id) { |
| | const templates = { |
| | 'react-agent': ` |
| | <div class="component-handle flex items-center justify-between"> |
| | <i data-feather="cpu" class="w-4 h-4"></i> |
| | <span class="text-sm font-semibold">React Agent</span> |
| | </div> |
| | <div class="text-xs text-gray-300">Reasoning engine</div> |
| | `, |
| | 'tool': ` |
| | <div class="component-handle flex items-center justify-between"> |
| | <i data-feather="tool" class="w-4 h-4"></i> |
| | <span class="text-sm font-semibold">Tool</span> |
| | </div> |
| | <div class="text-xs text-gray-300">Function tool</div> |
| | `, |
| | 'prompt': ` |
| | <div class="component-handle flex items-center justify-between"> |
| | <i data-feather="message-square" class="w-4 h-4"></i> |
| | <span class="text-sm font-semibold">Prompt Template</span> |
| | </div> |
| | <div class="text-xs text-gray-300">Chat setup</div> |
| | `, |
| | 'memory': ` |
| | <div class="component-handle flex items-center justify-between"> |
| | <i data-feather="database" class="w-4 h-4"></i> |
| | <span class="text-sm font-semibold">Memory</span> |
| | </div> |
| | <div class="text-xs text-gray-300">State storage</div> |
| | ` |
| | }; |
| | |
| | return templates[type] || '<div>Unknown Component</div>'; |
| | } |
| |
|
| | 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); |
| | |
| | |
| | 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 = `<h3 class="text-lg font-semibold mb-4 capitalize">${component.type.replace('-', ' ')} Properties</h3>`; |
| | |
| | Object.keys(properties).forEach(key => { |
| | const value = properties[key]; |
| | const isTextarea = typeof value === 'string' && value.includes('\n'); |
| | |
| | html += ` |
| | <div class="property-group"> |
| | <label class="property-label capitalize">${key.replace('_', ' ')}</label> |
| | ${isTextarea ? |
| | `<textarea name="${key}" class="property-input h-24">${value}</textarea>` : |
| | `<input type="text" name="${key}" value="${value}" class="property-input">` |
| | } |
| | </div> |
| | `; |
| | }); |
| | |
| | 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`; |
| | |
| | |
| | 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; |
| | } |
| | }); |
| | |
| | |
| | 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; |
| | } |
| | } |
| | |
| | function startNewProject() { |
| | const builder = new AgentBuilder(); |
| | window.agentBuilder = builder; |
| | document.getElementById('canvas').innerHTML = ''; |
| | document.getElementById('properties-panel').classList.add('hidden'); |
| | } |
| |
|
| | function loadSample() { |
| | startNewProject(); |
| | |
| | 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': |
| | |
| | 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); |
| | |
| | |
| | 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': |
| | |
| | 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': |
| | |
| | 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': |
| | |
| | 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': |
| | |
| | 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': |
| | |
| | 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; |
| | } |
| | |
| | |
| | document.getElementById('properties-panel').classList.add('hidden'); |
| | |
| | |
| | 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 = ` |
| | <div class="modal-content"> |
| | <div class="flex justify-between items-center mb-4"> |
| | <h3 class="text-xl font-semibold">Generated Python Code</h3> |
| | <button onclick="this.closest('.modal-overlay').remove()" class="text-gray-400 hover:text-white"> |
| | <i data-feather="x"></i> |
| | </button> |
| | </div> |
| | <pre class="bg-gray-900 p-4 rounded-lg overflow-auto max-h-96"><code class="language-python">${code}</code></pre> |
| | <div class="flex gap-2 mt-4"> |
| | <button onclick="copyCode()" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded-lg flex-1"> |
| | <i data-feather="copy" class="mr-2"></i>Copy to Clipboard |
| | </button> |
| | <button onclick="downloadCode()" class="bg-green-600 hover:bg-green-700 px-4 py-2 rounded-lg flex-1"> |
| | <i data-feather="download" class="mr-2"></i>Download .py |
| | </button> |
| | </div> |
| | </div> |
| | `; |
| | |
| | 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); |
| | }; |
| | } |
| | |
| | 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 = ` |
| | <div class="flex items-center gap-2"> |
| | <i data-feather="${type === 'success' ? 'check-circle' : type === 'error' ? 'alert-circle' : 'info'}"></i> |
| | <span>${message}</span> |
| | </div> |
| | `; |
| | |
| | document.body.appendChild(notification); |
| | |
| | |
| | setTimeout(() => { |
| | notification.style.transform = 'translateX(0)'; |
| | }, 100); |
| | |
| | |
| | setTimeout(() => { |
| | notification.style.transform = 'translateX(full)'; |
| | setTimeout(() => { |
| | if (notification.parentNode) { |
| | notification.parentNode.removeChild(notification); |
| | } |
| | }, 300); |
| | }, 3000); |
| | |
| | feather.replace(); |
| | } |
| |
|
| | |
| | document.addEventListener('DOMContentLoaded', () => { |
| | window.agentBuilder = new AgentBuilder(); |
| | feather.replace(); |
| | |
| | |
| | const urlParams = new URLSearchParams(window.location.search); |
| | const example = urlParams.get('example'); |
| | if (example && ['research', 'ecommerce', 'code', 'support', 'analyst', 'translator'].includes(example)) { |
| | |
| | setTimeout(() => { |
| | loadExample(example); |
| | }, 500); |
| | } |
| | }); |
| | console.log('AgentFlow Studio loaded'); |