Browser JavaScript (ESM)
This guide shows how to use the Athena Intelligence SDK directly in the browser using ESM imports from CDN. Perfect for rapid prototyping, demos, and simple web applications without build tools.
Key features:
- No build process required - works directly in the browser
- Full SDK functionality available via ESM imports
- Type safety with JSDoc comments
- Real-time interaction examples
- Production-ready patterns for browser applications
Basic ESM Import Setup
Use the SDK directly in your browser with ESM imports:
1 // Import the SDK from ESM CDN 2 import { AthenaIntelligenceClient, AthenaIntelligenceError } from 'https://esm.run/athena-intelligence'; 3 4 // Basic client initialization (uses default production API) 5 const client = new AthenaIntelligenceClient({ 6 apiKey: API_KEY, // Assumes API_KEY is defined globally 7 }); 8 9 // Override baseUrl for custom API endpoints 10 const customClient = new AthenaIntelligenceClient({ 11 apiKey: API_KEY, 12 baseUrl: 'https://your-custom-api.example.com', // Custom API endpoint 13 }); 14 15 // Use development/localhost environment 16 const devClient = new AthenaIntelligenceClient({ 17 apiKey: API_KEY, 18 baseUrl: 'http://localhost:8000', // Local development server 19 }); 20 21 console.log('Athena Intelligence client initialized');
Simple Agent Interaction
Execute basic agent requests with full error handling:
1 async function runSimpleAgent() { 2 try { 3 console.log('๐ค Running General Agent...'); 4 5 const response = await client.agents.general.invoke({ 6 config: { 7 model: 'gpt-4-turbo-preview', 8 enabled_tools: ['search'], 9 }, 10 messages: [ 11 { 12 content: 'Search for the latest news about artificial intelligence', 13 role: 'user', 14 type: 'user', 15 }, 16 ], 17 }); 18 19 console.log('โ Response received'); 20 21 // Extract the response content safely 22 const messages = response.messages || []; 23 const lastMessage = messages[messages.length - 1]; 24 25 if (lastMessage?.kwargs?.content) { 26 console.log('Agent Response:', lastMessage.kwargs.content); 27 return lastMessage.kwargs.content; 28 } else { 29 console.warn('No content in response'); 30 return null; 31 } 32 } catch (error) { 33 if (error instanceof AthenaIntelligenceError) { 34 console.error(`API Error: ${error.statusCode} - ${error.message}`); 35 } else { 36 console.error('Unexpected error:', error); 37 } 38 return null; 39 } 40 } 41 42 // Execute the function 43 runSimpleAgent().then(result => { 44 if (result) { 45 console.log('Success:', result); 46 } 47 });
Multi-Tool Workflow
Combine multiple tools for complex tasks:
1 async function runMultiToolWorkflow() { 2 try { 3 const request = { 4 config: { 5 enabled_tools: ['search', 'browse'], 6 system_prompt: 'You are a research assistant. Use search and browse tools to gather comprehensive information.', 7 model: 'gpt-4-turbo-preview', 8 }, 9 messages: [ 10 { 11 content: 'Research the latest developments in quantum computing and provide a detailed summary with sources.', 12 role: 'user', 13 type: 'user', 14 }, 15 ], 16 }; 17 18 console.log('๐ Starting multi-tool research...'); 19 const response = await client.agents.general.invoke(request); 20 21 // Process the response 22 const messages = response.messages || []; 23 24 messages.forEach((message, index) => { 25 console.log(`Message ${index + 1}:`); 26 console.log(` Type: ${message.type}`); 27 console.log(` Role: ${message.role || 'unknown'}`); 28 29 // Handle different content types 30 const content = message.kwargs?.content || message.content; 31 if (typeof content === 'string') { 32 console.log(` Content: ${content.substring(0, 200)}...`); 33 } else if (Array.isArray(content)) { 34 console.log(` Content: ${content.length} content parts`); 35 } 36 37 // Check for tool calls 38 if (message.kwargs?.tool_calls && message.kwargs.tool_calls.length > 0) { 39 console.log(` Tool Calls: ${message.kwargs.tool_calls.length}`); 40 } 41 }); 42 43 return response; 44 } catch (error) { 45 console.error('Multi-tool workflow failed:', error); 46 return null; 47 } 48 }
Conversational Interaction
Build interactive conversations with context preservation:
1 class ConversationManager { 2 constructor(client) { 3 this.client = client; 4 this.messages = []; 5 this.threadId = null; 6 } 7 8 // Add a system message 9 addSystemMessage(content) { 10 this.messages.push({ 11 content, 12 role: 'system', 13 type: 'system', 14 }); 15 } 16 17 // Add a user message 18 addUserMessage(content) { 19 this.messages.push({ 20 content, 21 role: 'user', 22 type: 'user', 23 }); 24 } 25 26 // Send messages and get response 27 async sendMessage(userInput, config = {}) { 28 try { 29 // Add user input to conversation 30 this.addUserMessage(userInput); 31 32 const defaultConfig = { 33 model: 'gpt-4-turbo-preview', 34 enabled_tools: ['search'], 35 }; 36 37 const request = { 38 config: { ...defaultConfig, ...config }, 39 messages: [...this.messages], 40 thread_id: this.threadId, 41 }; 42 43 console.log(`๐ฌ Sending message: "${userInput}"`); 44 const response = await this.client.agents.general.invoke(request); 45 46 // Extract assistant response and add to conversation 47 const responseMessages = response.messages || []; 48 const lastMessage = responseMessages[responseMessages.length - 1]; 49 50 if (lastMessage?.kwargs?.content) { 51 const assistantContent = lastMessage.kwargs.content; 52 53 // Add assistant response to conversation history 54 this.messages.push({ 55 content: assistantContent, 56 role: 'assistant', 57 type: 'assistant', 58 }); 59 60 console.log('๐ค Assistant response received'); 61 return { 62 content: assistantContent, 63 fullResponse: response, 64 conversationLength: this.messages.length, 65 }; 66 } else { 67 console.warn('No assistant content in response'); 68 return null; 69 } 70 } catch (error) { 71 console.error('Conversation error:', error); 72 return null; 73 } 74 } 75 76 // Get conversation history 77 getHistory() { 78 return [...this.messages]; 79 } 80 81 // Clear conversation 82 clear() { 83 this.messages = []; 84 this.threadId = null; 85 } 86 } 87 88 // Usage example 89 async function runConversation() { 90 const conversation = new ConversationManager(client); 91 92 // Set up conversation context 93 conversation.addSystemMessage('You are a helpful AI assistant specializing in technology and business analysis.'); 94 95 // First message 96 const response1 = await conversation.sendMessage( 97 'What are the key trends in AI for 2024?', 98 { enabled_tools: ['search'] } 99 ); 100 101 if (response1) { 102 console.log('Response 1:', response1.content); 103 } 104 105 // Follow-up message with context 106 const response2 = await conversation.sendMessage( 107 'Can you provide specific examples of companies implementing these trends?' 108 ); 109 110 if (response2) { 111 console.log('Response 2:', response2.content); 112 console.log(`Total conversation length: ${response2.conversationLength} messages`); 113 } 114 115 // Show full conversation history 116 console.log('Full conversation:', conversation.getHistory()); 117 }
Understanding AOP Execution
Important: Agent Operating Procedures (AOPs) can take minutes to complete. Always use asynchronous execution to prevent timeouts and enable real-time progress tracking.
How it works:
executeAsyncstarts execution and returns immediately with athread_id- The AOP runs in the background on the server
- You poll
threads.getStatusto monitor progress - When status is
completed, extract the final result
Basic Async AOP Execution
Execute AOPs asynchronously with proper monitoring:
1 // Async AOP execution (recommended for production) 2 async function executeAOP(assetId, userInputs = {}) { 3 try { 4 console.log(`๐ Starting async AOP execution: ${assetId}`); 5 console.log('User inputs:', userInputs); 6 7 // Step 1: Start async execution (returns immediately with thread_id) 8 const asyncResponse = await client.aop.executeAsync({ 9 asset_id: assetId, 10 user_inputs: userInputs, 11 }); 12 13 // executeAsync only STARTS the execution - it does NOT complete it 14 console.log('โ AOP execution initiated (running in background)'); 15 console.log('Thread ID:', asyncResponse.thread_id); 16 console.log('Status:', asyncResponse.status); // Will be "started" or similar 17 console.log('AOP Title:', asyncResponse.aop_title); 18 19 // Step 2: Monitor execution until it actually completes 20 const result = await monitorExecution(asyncResponse.thread_id); 21 22 return result; 23 } catch (error) { 24 console.error('AOP execution failed:', error); 25 26 if (error instanceof AthenaIntelligenceError) { 27 return { 28 success: false, 29 error: `API Error: ${error.statusCode} - ${error.message}`, 30 statusCode: error.statusCode, 31 }; 32 } else { 33 return { 34 success: false, 35 error: error.message || 'Unknown error', 36 }; 37 } 38 } 39 } 40 41 // Progress monitoring function 42 async function monitorExecution(threadId) { 43 const maxAttempts = 60; // 5 minutes with 5-second intervals 44 const pollInterval = 5000; 45 let consecutiveErrors = 0; 46 const maxConsecutiveErrors = 3; 47 48 console.log(`๐ Starting progress monitoring for thread: ${threadId}`); 49 50 for (let attempt = 1; attempt <= maxAttempts; attempt++) { 51 try { 52 // Poll thread status 53 const status = await client.threads.getStatus(threadId); 54 55 // Reset error counter on successful response 56 consecutiveErrors = 0; 57 58 console.log(`[${attempt}/${maxAttempts}] Status: ${status.status} (Updated: ${status.updated_at})`); 59 60 // Check if execution completed 61 if (status.status === 'completed') { 62 console.log('๐ AOP execution completed successfully!'); 63 64 // Extract final result safely 65 const conversationAsset = status.conversation_asset; 66 if (conversationAsset?.last_message?.content) { 67 const finalContent = conversationAsset.last_message.content; 68 69 // Handle string content 70 if (typeof finalContent === 'string') { 71 return { 72 success: true, 73 status: 'completed', 74 result: finalContent, 75 threadId, 76 conversationAssetId: conversationAsset.conversation_asset_id, 77 messageCount: conversationAsset.num_messages, 78 }; 79 } 80 81 // Handle multimodal content (array) 82 if (Array.isArray(finalContent)) { 83 const textParts = finalContent 84 .filter(part => part.type === 'text' && part.text) 85 .map(part => part.text) 86 .join('\n'); 87 88 return { 89 success: true, 90 status: 'completed', 91 result: textParts, 92 threadId, 93 conversationAssetId: conversationAsset.conversation_asset_id, 94 messageCount: conversationAsset.num_messages, 95 isMultimodal: true, 96 }; 97 } 98 } 99 100 // Completed but no content 101 return { 102 success: true, 103 status: 'completed', 104 result: 'AOP completed but no final message available', 105 threadId, 106 }; 107 } else if (status.status === 'failed') { 108 console.error('โ AOP execution failed'); 109 return { 110 success: false, 111 status: 'failed', 112 error: 'AOP execution failed', 113 threadId, 114 }; 115 } 116 117 // Still running - wait before next poll 118 console.log(`โณ Still running... (${status.status})`); 119 await new Promise(resolve => setTimeout(resolve, pollInterval)); 120 } catch (error) { 121 consecutiveErrors++; 122 console.error(`Status check failed (${consecutiveErrors}/${maxConsecutiveErrors}):`, error.message); 123 124 // Fail fast if too many consecutive errors 125 if (consecutiveErrors >= maxConsecutiveErrors) { 126 return { 127 success: false, 128 status: 'error', 129 error: `Too many consecutive status check failures: ${error.message}`, 130 threadId, 131 }; 132 } 133 134 // Wait before retrying 135 await new Promise(resolve => setTimeout(resolve, pollInterval)); 136 } 137 } 138 139 // Timeout reached 140 console.warn('โฐ Polling timeout reached'); 141 return { 142 success: false, 143 status: 'timeout', 144 error: 'Monitoring timeout reached - execution may still be running', 145 threadId, 146 }; 147 } 148 149 // Example usage 150 const marketAnalysisResult = await executeAOP( 151 'asset_market_research_aop', 152 { 153 company: 'Tesla', 154 quarter: 'Q3 2024', 155 analysis_type: 'comprehensive', 156 } 157 ); 158 159 if (marketAnalysisResult.success) { 160 console.log('โ Market analysis result:', marketAnalysisResult.result); 161 } else { 162 console.error('โ Market analysis failed:', marketAnalysisResult.error); 163 }
Advanced: Custom Progress Callbacks
Add custom progress callbacks for UI updates and analytics:
1 // Execute AOP with custom progress tracking 2 async function executeAOPWithProgress(assetId, userInputs = {}, onProgress = null) { 3 try { 4 console.log(`๐ Starting async AOP: ${assetId}`); 5 6 // Step 1: Start async execution (returns immediately) 7 const asyncResponse = await client.aop.executeAsync({ 8 asset_id: assetId, 9 user_inputs: userInputs, 10 }); 11 12 console.log('โ AOP execution initiated'); 13 console.log('Thread ID:', asyncResponse.thread_id); 14 console.log('AOP Title:', asyncResponse.aop_title); 15 16 // Step 2: Monitor progress with callbacks 17 const result = await monitorWithCallback(asyncResponse.thread_id, onProgress); 18 19 return { 20 success: result.success, 21 startResponse: asyncResponse, 22 finalResult: result, 23 }; 24 } catch (error) { 25 console.error('Async AOP execution failed:', error); 26 return { 27 success: false, 28 error: error.message || 'Unknown error', 29 }; 30 } 31 } 32 33 // Progress monitoring with callback support 34 async function monitorWithCallback(threadId, onProgress = null) { 35 const maxAttempts = 120; // 10 minutes for longer workflows 36 const pollInterval = 5000; 37 let consecutiveErrors = 0; 38 const maxConsecutiveErrors = 3; 39 40 for (let attempt = 1; attempt <= maxAttempts; attempt++) { 41 try { 42 const status = await client.threads.getStatus(threadId); 43 44 // Reset error counter 45 consecutiveErrors = 0; 46 47 // Call progress callback if provided 48 if (onProgress) { 49 onProgress({ 50 attempt, 51 maxAttempts, 52 status: status.status, 53 updatedAt: status.updated_at, 54 threadId: status.thread_id, 55 }); 56 } 57 58 console.log(`[${attempt}/${maxAttempts}] Status: ${status.status} (${status.updated_at})`); 59 60 if (status.status === 'completed') { 61 console.log('๐ AOP execution completed!'); 62 63 // Extract final result 64 const conversationAsset = status.conversation_asset; 65 if (conversationAsset?.last_message?.content) { 66 const finalContent = conversationAsset.last_message.content; 67 68 // Handle string or array content 69 let resultText; 70 if (typeof finalContent === 'string') { 71 resultText = finalContent; 72 } else if (Array.isArray(finalContent)) { 73 resultText = finalContent 74 .filter(part => part.type === 'text' && part.text) 75 .map(part => part.text) 76 .join('\n'); 77 } else { 78 resultText = JSON.stringify(finalContent); 79 } 80 81 return { 82 success: true, 83 status: 'completed', 84 result: resultText, 85 conversationAssetId: conversationAsset.conversation_asset_id, 86 messageCount: conversationAsset.num_messages, 87 threadStatus: status, 88 }; 89 } else { 90 return { 91 success: true, 92 status: 'completed', 93 result: 'AOP completed but no final message available', 94 threadStatus: status, 95 }; 96 } 97 } else if (status.status === 'failed') { 98 console.error('โ AOP execution failed'); 99 return { 100 success: false, 101 status: 'failed', 102 error: 'AOP execution failed', 103 threadStatus: status, 104 }; 105 } 106 107 // Continue polling 108 await new Promise(resolve => setTimeout(resolve, pollInterval)); 109 } catch (error) { 110 consecutiveErrors++; 111 console.error(`Status check failed (${consecutiveErrors}/${maxConsecutiveErrors}):`, error.message); 112 113 // Fail fast if too many consecutive errors 114 if (consecutiveErrors >= maxConsecutiveErrors) { 115 return { 116 success: false, 117 status: 'error', 118 error: `Too many consecutive failures: ${error.message}`, 119 }; 120 } 121 122 // Wait before retrying 123 await new Promise(resolve => setTimeout(resolve, pollInterval)); 124 } 125 } 126 127 console.warn('โฐ Polling timeout reached'); 128 return { 129 success: false, 130 status: 'timeout', 131 error: 'Monitoring timeout reached - execution may still be running', 132 }; 133 } 134 135 // Example usage with progress tracking 136 const progressCallback = (info) => { 137 console.log(`๐ Progress: ${info.attempt}/${info.maxAttempts} - ${info.status}`); 138 139 // Update UI or send to analytics 140 if (typeof window !== 'undefined' && window.updateProgressUI) { 141 window.updateProgressUI({ 142 percent: (info.attempt / info.maxAttempts) * 100, 143 status: info.status, 144 updatedAt: info.updatedAt, 145 }); 146 } 147 }; 148 149 const comprehensiveAnalysis = await executeAOPWithProgress( 150 'asset_comprehensive_research_aop', 151 { 152 company: 'OpenAI', 153 research_depth: 'comprehensive', 154 include_financials: 'true', 155 time_horizon: '2024-2025', 156 }, 157 progressCallback 158 ); 159 160 if (comprehensiveAnalysis.success) { 161 console.log('โ Comprehensive analysis result:', comprehensiveAnalysis.finalResult.result); 162 } else { 163 console.error('โ Analysis failed:', comprehensiveAnalysis.error); 164 }
Batch Processing with Async Execution
Process multiple AOPs concurrently using async execution:
1 // Batch AOP execution with async pattern 2 async function executeBatchAOPs(aopConfigs) { 3 console.log(`๐ Starting ${aopConfigs.length} AOPs concurrently...`); 4 5 // Step 1: Start all AOPs asynchronously (all return immediately with thread_ids) 6 const startPromises = aopConfigs.map(async (config, index) => { 7 try { 8 console.log(`Starting AOP ${index + 1}: ${config.name || config.assetId}`); 9 10 const response = await client.aop.executeAsync({ 11 asset_id: config.assetId, 12 user_inputs: config.userInputs || {}, 13 }); 14 15 console.log(`โ ${config.name || 'AOP'} started with thread: ${response.thread_id}`); 16 17 return { 18 index, 19 name: config.name || `AOP ${index + 1}`, 20 threadId: response.thread_id, 21 aopTitle: response.aop_title, 22 success: true, 23 }; 24 } catch (error) { 25 console.error(`โ Failed to start AOP ${index + 1}:`, error.message); 26 return { 27 index, 28 name: config.name || `AOP ${index + 1}`, 29 success: false, 30 error: error.message || 'Unknown error', 31 }; 32 } 33 }); 34 35 const startResults = await Promise.all(startPromises); 36 37 // Step 2: Monitor all successful starts until completion 38 console.log(`๐ Monitoring ${startResults.filter(r => r.success).length} running AOPs...`); 39 40 const monitorPromises = startResults 41 .filter(result => result.success && result.threadId) 42 .map(async (result) => { 43 try { 44 const finalResult = await monitorExecution(result.threadId); 45 return { 46 ...result, 47 ...finalResult, 48 }; 49 } catch (error) { 50 return { 51 ...result, 52 success: false, 53 status: 'error', 54 error: error.message || 'Monitoring failed', 55 }; 56 } 57 }); 58 59 const finalResults = await Promise.all(monitorPromises); 60 61 // Combine failed starts with monitoring results 62 const allResults = [ 63 ...finalResults, 64 ...startResults.filter(r => !r.success), 65 ]; 66 67 // Calculate summary 68 const successful = allResults.filter(r => r.success && r.status === 'completed'); 69 const failed = allResults.filter(r => !r.success || r.status !== 'completed'); 70 71 console.log(`\nโ Batch complete: ${successful.length} successful, ${failed.length} failed`); 72 73 return { 74 successful, 75 failed, 76 summary: { 77 total: aopConfigs.length, 78 successful: successful.length, 79 failed: failed.length, 80 }, 81 }; 82 } 83 84 // Example batch configuration 85 const batchConfigs = [ 86 { 87 name: 'Market Research', 88 assetId: 'asset_market_research_aop', 89 userInputs: { company: 'Apple', quarter: 'Q3 2024' }, 90 }, 91 { 92 name: 'Competitor Analysis', 93 assetId: 'asset_competitor_analysis_aop', 94 userInputs: { company: 'Apple', competitors: 'Samsung,Google,Microsoft' }, 95 }, 96 { 97 name: 'Financial Summary', 98 assetId: 'asset_financial_analysis_aop', 99 userInputs: { company: 'Apple', period: 'annual', year: '2024' }, 100 }, 101 ]; 102 103 const batchResults = await executeBatchAOPs(batchConfigs); 104 105 console.log('\n=== Batch Results ==='); 106 batchResults.successful.forEach(result => { 107 console.log(`โ ${result.name}: ${result.result?.substring(0, 100)}...`); 108 }); 109 batchResults.failed.forEach(result => { 110 console.log(`โ ${result.name}: ${result.error}`); 111 }); 112 console.log(`\nSummary: ${batchResults.summary.successful}/${batchResults.summary.total} completed`);
File Upload and Processing
Upload files and process them with AOPs using async execution:
1 // File upload and processing workflow with async execution 2 async function uploadAndProcessFile(file, processingAOPId, processingInputs = {}) { 3 try { 4 console.log(`๐ Uploading file: ${file.name}`); 5 6 // Step 1: Upload the file 7 const uploadResponse = await client.tools.saveAsset({ file }); 8 9 if (!uploadResponse.asset_id) { 10 throw new Error('File upload failed - no asset ID returned'); 11 } 12 13 console.log('โ File uploaded:', uploadResponse.asset_id); 14 15 // Step 2: Start async processing with AOP 16 console.log('๐ Starting AOP processing...'); 17 18 const asyncResponse = await client.aop.executeAsync({ 19 asset_id: processingAOPId, 20 user_inputs: { 21 ...processingInputs, 22 file_asset_id: uploadResponse.asset_id, 23 }, 24 }); 25 26 console.log('โ Processing started with thread:', asyncResponse.thread_id); 27 28 // Step 3: Monitor processing until completion 29 const processingResult = await monitorExecution(asyncResponse.thread_id); 30 31 if (processingResult.success) { 32 return { 33 success: true, 34 uploadedAssetId: uploadResponse.asset_id, 35 processingResult: processingResult.result, 36 threadId: asyncResponse.thread_id, 37 conversationAssetId: processingResult.conversationAssetId, 38 }; 39 } else { 40 return { 41 success: false, 42 uploadedAssetId: uploadResponse.asset_id, 43 error: processingResult.error || 'Processing failed', 44 threadId: asyncResponse.thread_id, 45 }; 46 } 47 } catch (error) { 48 console.error('File processing failed:', error); 49 return { 50 success: false, 51 error: error.message || 'Unknown error', 52 }; 53 } 54 } 55 56 // File input handler 57 function handleFileUpload(inputElement, processingAOPId) { 58 inputElement.addEventListener('change', async (event) => { 59 const file = event.target.files?.[0]; 60 61 if (!file) { 62 console.log('No file selected'); 63 return; 64 } 65 66 console.log(`Selected file: ${file.name} (${file.size} bytes)`); 67 68 const result = await uploadAndProcessFile( 69 file, 70 processingAOPId, 71 { 72 analysis_type: 'comprehensive', 73 extract_insights: 'true', 74 } 75 ); 76 77 if (result.success) { 78 console.log('File processing completed:', result.processingResult); 79 } else { 80 console.error('File processing failed:', result.error); 81 } 82 }); 83 }
Real-time Data Processing
Process data streams and handle updates:
1 // Real-time data processor 2 class RealTimeAOPProcessor { 3 constructor(client, aopAssetId) { 4 this.client = client; 5 this.aopAssetId = aopAssetId; 6 this.processing = false; 7 this.queue = []; 8 this.results = []; 9 } 10 11 // Add data to processing queue 12 addData(data, metadata = {}) { 13 this.queue.push({ 14 data, 15 metadata, 16 timestamp: new Date().toISOString(), 17 }); 18 19 console.log(`๐ Added data to queue. Queue length: ${this.queue.length}`); 20 21 // Auto-process if not currently processing 22 if (!this.processing) { 23 this.processQueue(); 24 } 25 } 26 27 // Process queued data 28 async processQueue() { 29 if (this.processing || this.queue.length === 0) { 30 return; 31 } 32 33 this.processing = true; 34 console.log(`๐ Processing ${this.queue.length} items...`); 35 36 while (this.queue.length > 0) { 37 const item = this.queue.shift(); 38 39 try { 40 const result = await this.processItem(item); 41 this.results.push(result); 42 console.log(`โ Processed item: ${result.success ? 'success' : 'failed'}`); 43 } catch (error) { 44 console.error('Item processing error:', error); 45 this.results.push({ 46 success: false, 47 error: error.message, 48 originalData: item, 49 }); 50 } 51 } 52 53 this.processing = false; 54 console.log('๐ Queue processing complete'); 55 } 56 57 // Process individual item with async execution 58 async processItem(item) { 59 try { 60 // Start async execution 61 const asyncResponse = await this.client.aop.executeAsync({ 62 asset_id: this.aopAssetId, 63 user_inputs: { 64 input_data: JSON.stringify(item.data), 65 metadata: JSON.stringify(item.metadata), 66 timestamp: item.timestamp, 67 }, 68 }); 69 70 console.log(`Processing item with thread: ${asyncResponse.thread_id}`); 71 72 // Monitor execution (simplified for real-time processing) 73 const result = await this.monitorItemExecution(asyncResponse.thread_id); 74 75 return { 76 success: result.success, 77 result: result.result || 'No result content', 78 threadId: asyncResponse.thread_id, 79 originalData: item, 80 processedAt: new Date().toISOString(), 81 }; 82 } catch (error) { 83 return { 84 success: false, 85 error: error.message || 'Processing failed', 86 originalData: item, 87 processedAt: new Date().toISOString(), 88 }; 89 } 90 } 91 92 // Simplified monitoring for real-time items (shorter timeout) 93 async monitorItemExecution(threadId) { 94 const maxAttempts = 30; // 2.5 minutes for individual items 95 const pollInterval = 5000; 96 97 for (let attempt = 1; attempt <= maxAttempts; attempt++) { 98 try { 99 const status = await this.client.threads.getStatus(threadId); 100 101 if (status.status === 'completed') { 102 const conversationAsset = status.conversation_asset; 103 if (conversationAsset?.last_message?.content) { 104 const content = conversationAsset.last_message.content; 105 const result = typeof content === 'string' 106 ? content 107 : Array.isArray(content) 108 ? content.filter(p => p.type === 'text').map(p => p.text).join('\n') 109 : JSON.stringify(content); 110 111 return { success: true, result }; 112 } 113 return { success: true, result: 'Completed with no content' }; 114 } else if (status.status === 'failed') { 115 return { success: false, error: 'Execution failed' }; 116 } 117 118 await new Promise(resolve => setTimeout(resolve, pollInterval)); 119 } catch (error) { 120 if (attempt === maxAttempts) { 121 return { success: false, error: error.message }; 122 } 123 } 124 } 125 126 return { success: false, error: 'Timeout' }; 127 } 128 129 // Get processing results 130 getResults() { 131 return [...this.results]; 132 } 133 134 // Clear results 135 clearResults() { 136 this.results = []; 137 } 138 } 139 140 // Usage example 141 const dataProcessor = new RealTimeAOPProcessor(client, 'asset_data_analysis_aop'); 142 143 // Simulate data stream 144 const sampleData = [ 145 { temperature: 23.5, humidity: 45, location: 'NYC' }, 146 { temperature: 21.2, humidity: 52, location: 'LA' }, 147 { temperature: 18.7, humidity: 38, location: 'Chicago' }, 148 ]; 149 150 // Add data items with metadata 151 sampleData.forEach((data, index) => { 152 dataProcessor.addData(data, { 153 source: 'sensor_network', 154 batch_id: 'batch_001', 155 sequence: index + 1, 156 }); 157 }); 158 159 // Wait for processing to complete 160 setTimeout(() => { 161 const results = dataProcessor.getResults(); 162 console.log(`๐ Processing complete: ${results.length} results`); 163 results.forEach((result, index) => { 164 console.log(`Result ${index + 1}:`, result.success ? result.result : result.error); 165 }); 166 }, 10000);
Error Handling and Debugging
Comprehensive error handling patterns for browser environments:
1 // Global error handler for SDK operations 2 class AthenaErrorHandler { 3 static handleError(error, context = '') { 4 console.error(`โ Error in ${context}:`, error); 5 6 if (error instanceof AthenaIntelligenceError) { 7 const errorInfo = { 8 type: 'AthenaIntelligenceError', 9 statusCode: error.statusCode, 10 message: error.message, 11 context, 12 timestamp: new Date().toISOString(), 13 }; 14 15 // Log for debugging 16 console.error('Athena API Error Details:', errorInfo); 17 18 // Handle specific error codes 19 switch (error.statusCode) { 20 case 401: 21 console.error('๐ Authentication failed - check your API key'); 22 break; 23 case 404: 24 console.error('๐ Resource not found - check asset IDs'); 25 break; 26 case 400: 27 console.error('๐ Bad request - check your input parameters'); 28 break; 29 case 429: 30 console.error('๐ฆ Rate limit exceeded - slow down requests'); 31 break; 32 case 500: 33 console.error('๐ฅ Server error - try again later'); 34 break; 35 default: 36 console.error(`๐คท Unknown API error: ${error.statusCode}`); 37 } 38 39 return errorInfo; 40 } else { 41 const errorInfo = { 42 type: 'UnknownError', 43 message: error.message || 'Unknown error occurred', 44 context, 45 timestamp: new Date().toISOString(), 46 }; 47 48 console.error('Unknown Error Details:', errorInfo); 49 return errorInfo; 50 } 51 } 52 53 // Retry wrapper with exponential backoff 54 static async withRetry(asyncFn, maxRetries = 3, context = '') { 55 let lastError; 56 57 for (let attempt = 1; attempt <= maxRetries; attempt++) { 58 try { 59 console.log(`๐ Attempt ${attempt}/${maxRetries} for ${context}`); 60 const result = await asyncFn(); 61 console.log(`โ Success on attempt ${attempt} for ${context}`); 62 return result; 63 } catch (error) { 64 lastError = error; 65 66 // Don't retry on client errors (4xx) 67 if (error instanceof AthenaIntelligenceError && 68 error.statusCode >= 400 && error.statusCode < 500) { 69 console.error('โ Client error - not retrying'); 70 break; 71 } 72 73 if (attempt < maxRetries) { 74 const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000); 75 console.log(`โณ Waiting ${delay}ms before retry...`); 76 await new Promise(resolve => setTimeout(resolve, delay)); 77 } 78 } 79 } 80 81 throw this.handleError(lastError, context); 82 } 83 } 84 85 // Safe execution wrapper with async execution 86 async function safeExecuteAOP(assetId, userInputs = {}) { 87 return await AthenaErrorHandler.withRetry( 88 async () => { 89 // Start async execution 90 const asyncResponse = await client.aop.executeAsync({ 91 asset_id: assetId, 92 user_inputs: userInputs, 93 }); 94 95 // Monitor until completion 96 const result = await monitorExecution(asyncResponse.thread_id); 97 98 if (!result.success) { 99 throw new Error(result.error || 'AOP execution failed'); 100 } 101 102 return result; 103 }, 104 3, 105 `AOP execution (${assetId})` 106 ); 107 } 108 109 // Usage with comprehensive error handling 110 try { 111 const result = await safeExecuteAOP('asset_analysis_aop', { 112 input: 'market data', 113 format: 'detailed', 114 }); 115 116 console.log('Safe execution result:', result); 117 } catch (errorInfo) { 118 console.error('Final error after retries:', errorInfo); 119 120 // Handle in UI 121 if (typeof window !== 'undefined' && window.showErrorMessage) { 122 window.showErrorMessage(`Failed to execute AOP: ${errorInfo.message}`); 123 } 124 }
Debug and Development Utilities
Helpful utilities for debugging in browser console:
1 // Debug utilities for browser development 2 window.athenaDebug = { 3 // Test connection 4 async testConnection() { 5 try { 6 const userInfo = await client.me.get(); 7 console.log('โ Connection successful:', userInfo); 8 return true; 9 } catch (error) { 10 console.error('โ Connection failed:', error); 11 return false; 12 } 13 }, 14 15 // List available assets 16 async listAssets(limit = 10) { 17 try { 18 const assets = await client.assets.list({ limit }); 19 console.log(`๐ Found ${assets.total} assets (showing first ${limit}):`); 20 21 assets.items.forEach((asset, index) => { 22 console.log(`${index + 1}. ${asset.title} (${asset.athena_original_type})`); 23 console.log(` ID: ${asset.id}`); 24 console.log(` Created: ${asset.created_at}`); 25 }); 26 27 return assets; 28 } catch (error) { 29 console.error('Failed to list assets:', error); 30 return null; 31 } 32 }, 33 34 // Quick AOP test with async execution 35 async testAOP(assetId, userInputs = {}) { 36 console.log(`๐งช Testing AOP: ${assetId}`); 37 console.log('User inputs:', userInputs); 38 39 try { 40 // Start async execution 41 const asyncResponse = await client.aop.executeAsync({ 42 asset_id: assetId, 43 user_inputs: userInputs, 44 }); 45 46 console.log('AOP started:', { 47 threadId: asyncResponse.thread_id, 48 aopTitle: asyncResponse.aop_title, 49 status: asyncResponse.status, 50 }); 51 52 // Monitor execution (short timeout for testing) 53 const maxAttempts = 30; // 2.5 minutes 54 const pollInterval = 5000; 55 56 for (let attempt = 1; attempt <= maxAttempts; attempt++) { 57 const status = await client.threads.getStatus(asyncResponse.thread_id); 58 console.log(`[${attempt}/${maxAttempts}] Status: ${status.status}`); 59 60 if (status.status === 'completed') { 61 console.log('โ Test completed successfully'); 62 console.log('Final result:', { 63 conversationAssetId: status.conversation_asset?.conversation_asset_id, 64 messageCount: status.conversation_asset?.num_messages, 65 hasContent: !!status.conversation_asset?.last_message?.content, 66 }); 67 return status; 68 } else if (status.status === 'failed') { 69 console.error('โ Test failed'); 70 return status; 71 } 72 73 await new Promise(resolve => setTimeout(resolve, pollInterval)); 74 } 75 76 console.warn('โฐ Test timeout reached'); 77 return null; 78 } catch (error) { 79 console.error('AOP test failed:', error); 80 return null; 81 } 82 }, 83 84 // Monitor thread 85 async monitorThread(threadId) { 86 try { 87 const status = await client.threads.getStatus(threadId); 88 console.log('Thread status:', { 89 id: threadId, 90 status: status.status, 91 updatedAt: status.updated_at, 92 hasConversationAsset: !!status.conversation_asset, 93 conversationState: status.conversation_asset?.state, 94 messageCount: status.conversation_asset?.num_messages, 95 }); 96 97 return status; 98 } catch (error) { 99 console.error('Thread monitoring failed:', error); 100 return null; 101 } 102 }, 103 }; 104 105 // Development helper 106 console.log('๐ ๏ธ Athena Debug utilities available:'); 107 console.log(' athenaDebug.testConnection() - Test API connection'); 108 console.log(' athenaDebug.listAssets(limit) - List workspace assets'); 109 console.log(' athenaDebug.testAOP(assetId, inputs) - Test AOP execution'); 110 console.log(' athenaDebug.monitorThread(threadId) - Check thread status');
Complete Browser Example
Hereโs a complete working example that demonstrates all patterns:
1 // Complete browser implementation 2 import { AthenaIntelligenceClient, AthenaIntelligenceError } from 'https://esm.run/athena-intelligence'; 3 4 async function initializeAthenaApp() { 5 try { 6 // Initialize client with optional baseUrl override 7 const client = new AthenaIntelligenceClient({ 8 apiKey: API_KEY, 9 // Optional: override baseUrl for custom environments 10 // baseUrl: 'https://your-custom-api.example.com', // Custom API 11 // baseUrl: 'http://localhost:8000', // Local development 12 }); 13 14 console.log('๐ Athena Intelligence SDK loaded'); 15 16 // Test connection 17 const userInfo = await client.me.get(); 18 console.log('๐ค User:', userInfo.email); 19 console.log('๐ข Workspace:', userInfo.workspace_name); 20 21 // Example: Quick agent interaction 22 const quickResponse = await client.agents.general.invoke({ 23 config: { model: 'gpt-4-turbo-preview' }, 24 messages: [ 25 { 26 content: 'Hello! Can you help me understand how AOPs work?', 27 role: 'user', 28 type: 'user', 29 }, 30 ], 31 }); 32 33 const agentResponse = quickResponse.messages?.[quickResponse.messages.length - 1]?.kwargs?.content; 34 console.log('๐ค Agent says:', agentResponse); 35 36 // Example: Async AOP execution 37 console.log('๐ Starting async AOP execution...'); 38 const asyncResponse = await client.aop.executeAsync({ 39 asset_id: 'asset_example_aop', 40 user_inputs: { 41 topic: 'browser SDK usage', 42 format: 'comprehensive', 43 }, 44 }); 45 46 console.log('โ AOP initiated with thread:', asyncResponse.thread_id); 47 console.log('๐ AOP Title:', asyncResponse.aop_title); 48 49 // Monitor execution (simplified example) 50 console.log('๐ Monitoring execution...'); 51 const maxAttempts = 30; 52 const pollInterval = 5000; 53 54 for (let attempt = 1; attempt <= maxAttempts; attempt++) { 55 const status = await client.threads.getStatus(asyncResponse.thread_id); 56 console.log(`[${attempt}/${maxAttempts}] Status: ${status.status}`); 57 58 if (status.status === 'completed') { 59 console.log('๐ AOP execution completed!'); 60 const finalContent = status.conversation_asset?.last_message?.content; 61 62 if (finalContent) { 63 const result = typeof finalContent === 'string' 64 ? finalContent 65 : Array.isArray(finalContent) 66 ? finalContent.filter(p => p.type === 'text').map(p => p.text).join('\n') 67 : JSON.stringify(finalContent); 68 69 console.log('๐ AOP Output:', result); 70 } else { 71 console.log('โ ๏ธ No final output from AOP'); 72 } 73 break; 74 } else if (status.status === 'failed') { 75 console.error('โ AOP execution failed'); 76 break; 77 } 78 79 if (attempt < maxAttempts) { 80 await new Promise(resolve => setTimeout(resolve, pollInterval)); 81 } 82 } 83 84 // Make client available globally for debugging 85 window.athenaClient = client; 86 console.log('๐ Client available as window.athenaClient'); 87 88 return { 89 client, 90 userInfo, 91 ready: true, 92 }; 93 } catch (error) { 94 console.error('โ Initialization failed:', error); 95 96 if (error instanceof AthenaIntelligenceError) { 97 console.error(`API Error: ${error.statusCode} - ${error.message}`); 98 } 99 100 return { 101 client: null, 102 ready: false, 103 error: error.message, 104 }; 105 } 106 } 107 108 // Initialize when DOM is ready 109 if (document.readyState === 'loading') { 110 document.addEventListener('DOMContentLoaded', initializeAthenaApp); 111 } else { 112 initializeAthenaApp(); 113 }
