> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.athenaintel.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.athenaintel.com/_mcp/server.

# Browser JavaScript (ESM)

> Use the Athena Intelligence SDK directly in the browser with ESM modules

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:

```javascript
// Import the SDK from ESM CDN
import { AthenaIntelligenceClient, AthenaIntelligenceError } from 'https://esm.run/@athenaintel/sdk';

// Basic client initialization (uses default production API)
const client = new AthenaIntelligenceClient({
  apiKey: API_KEY, // Assumes API_KEY is defined globally
});

// Override baseUrl for custom API endpoints
const customClient = new AthenaIntelligenceClient({
  apiKey: API_KEY,
  baseUrl: 'https://your-custom-api.example.com', // Custom API endpoint
});

// Use development/localhost environment
const devClient = new AthenaIntelligenceClient({
  apiKey: API_KEY,
  baseUrl: 'http://localhost:8000', // Local development server
});

console.log('Athena Intelligence client initialized');
```

### Simple Agent Interaction

Execute basic agent requests with full error handling:

```javascript
async function runSimpleAgent() {
  try {
    console.log('🤖 Running General Agent...');
    
    const response = await client.agents.general.invoke({
      config: {
        model: 'gpt-4-turbo-preview',
        enabled_tools: ['search'],
      },
      messages: [
        {
          content: 'Search for the latest news about artificial intelligence',
          role: 'user',
          type: 'user',
        },
      ],
    });

    console.log('✅ Response received');
    
    // Extract the response content safely
    const messages = response.messages || [];
    const lastMessage = messages[messages.length - 1];
    
    if (lastMessage?.kwargs?.content) {
      console.log('Agent Response:', lastMessage.kwargs.content);
      return lastMessage.kwargs.content;
    } else {
      console.warn('No content in response');
      return null;
    }
  } catch (error) {
    if (error instanceof AthenaIntelligenceError) {
      console.error(`API Error: ${error.statusCode} - ${error.message}`);
    } else {
      console.error('Unexpected error:', error);
    }
    return null;
  }
}

// Execute the function
runSimpleAgent().then(result => {
  if (result) {
    console.log('Success:', result);
  }
});
```

### Multi-Tool Workflow

Combine multiple tools for complex tasks:

```javascript
async function runMultiToolWorkflow() {
  try {
    const request = {
      config: {
        enabled_tools: ['search', 'browse'],
        system_prompt: 'You are a research assistant. Use search and browse tools to gather comprehensive information.',
        model: 'gpt-4-turbo-preview',
      },
      messages: [
        {
          content: 'Research the latest developments in quantum computing and provide a detailed summary with sources.',
          role: 'user',
          type: 'user',
        },
      ],
    };

    console.log('🔍 Starting multi-tool research...');
    const response = await client.agents.general.invoke(request);
    
    // Process the response
    const messages = response.messages || [];
    
    messages.forEach((message, index) => {
      console.log(`Message ${index + 1}:`);
      console.log(`  Type: ${message.type}`);
      console.log(`  Role: ${message.role || 'unknown'}`);
      
      // Handle different content types
      const content = message.kwargs?.content || message.content;
      if (typeof content === 'string') {
        console.log(`  Content: ${content.substring(0, 200)}...`);
      } else if (Array.isArray(content)) {
        console.log(`  Content: ${content.length} content parts`);
      }
      
      // Check for tool calls
      if (message.kwargs?.tool_calls && message.kwargs.tool_calls.length > 0) {
        console.log(`  Tool Calls: ${message.kwargs.tool_calls.length}`);
      }
    });
    
    return response;
  } catch (error) {
    console.error('Multi-tool workflow failed:', error);
    return null;
  }
}
```

### Conversational Interaction

Build interactive conversations with context preservation:

```javascript
class ConversationManager {
  constructor(client) {
    this.client = client;
    this.messages = [];
    this.threadId = null;
  }

  // Add a system message
  addSystemMessage(content) {
    this.messages.push({
      content,
      role: 'system',
      type: 'system',
    });
  }

  // Add a user message
  addUserMessage(content) {
    this.messages.push({
      content,
      role: 'user',
      type: 'user',
    });
  }

  // Send messages and get response
  async sendMessage(userInput, config = {}) {
    try {
      // Add user input to conversation
      this.addUserMessage(userInput);

      const defaultConfig = {
        model: 'gpt-4-turbo-preview',
        enabled_tools: ['search'],
      };

      const request = {
        config: { ...defaultConfig, ...config },
        messages: [...this.messages],
        thread_id: this.threadId,
      };

      console.log(`💬 Sending message: "${userInput}"`);
      const response = await this.client.agents.general.invoke(request);

      // Extract assistant response and add to conversation
      const responseMessages = response.messages || [];
      const lastMessage = responseMessages[responseMessages.length - 1];
      
      if (lastMessage?.kwargs?.content) {
        const assistantContent = lastMessage.kwargs.content;
        
        // Add assistant response to conversation history
        this.messages.push({
          content: assistantContent,
          role: 'assistant',
          type: 'assistant',
        });

        console.log('🤖 Assistant response received');
        return {
          content: assistantContent,
          fullResponse: response,
          conversationLength: this.messages.length,
        };
      } else {
        console.warn('No assistant content in response');
        return null;
      }
    } catch (error) {
      console.error('Conversation error:', error);
      return null;
    }
  }

  // Get conversation history
  getHistory() {
    return [...this.messages];
  }

  // Clear conversation
  clear() {
    this.messages = [];
    this.threadId = null;
  }
}

// Usage example
async function runConversation() {
  const conversation = new ConversationManager(client);
  
  // Set up conversation context
  conversation.addSystemMessage('You are a helpful AI assistant specializing in technology and business analysis.');
  
  // First message
  const response1 = await conversation.sendMessage(
    'What are the key trends in AI for 2024?',
    { enabled_tools: ['search'] }
  );
  
  if (response1) {
    console.log('Response 1:', response1.content);
  }
  
  // Follow-up message with context
  const response2 = await conversation.sendMessage(
    'Can you provide specific examples of companies implementing these trends?'
  );
  
  if (response2) {
    console.log('Response 2:', response2.content);
    console.log(`Total conversation length: ${response2.conversationLength} messages`);
  }
  
  // Show full conversation history
  console.log('Full conversation:', conversation.getHistory());
}
```

### 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**:

1. `executeAsync` **starts** execution and returns immediately with a `thread_id`
2. The AOP runs in the background on the server
3. You poll `threads.getStatus` to monitor progress
4. When status is `completed`, extract the final result

### Basic Async AOP Execution

Execute AOPs asynchronously with proper monitoring:

```javascript
// Async AOP execution (recommended for production)
async function executeAOP(assetId, userInputs = {}) {
  try {
    console.log(`🚀 Starting async AOP execution: ${assetId}`);
    console.log('User inputs:', userInputs);
    
    // Step 1: Start async execution (returns immediately with thread_id)
    const asyncResponse = await client.aop.executeAsync({
      asset_id: assetId,
      user_inputs: userInputs,
    });
    
    // executeAsync only STARTS the execution - it does NOT complete it
    console.log('✅ AOP execution initiated (running in background)');
    console.log('Thread ID:', asyncResponse.thread_id);
    console.log('Status:', asyncResponse.status); // Will be "started" or similar
    console.log('AOP Title:', asyncResponse.aop_title);
    
    // Step 2: Monitor execution until it actually completes
    const result = await monitorExecution(asyncResponse.thread_id);
    
    return result;
  } catch (error) {
    console.error('AOP execution failed:', error);
    
    if (error instanceof AthenaIntelligenceError) {
      return {
        success: false,
        error: `API Error: ${error.statusCode} - ${error.message}`,
        statusCode: error.statusCode,
      };
    } else {
      return {
        success: false,
        error: error.message || 'Unknown error',
      };
    }
  }
}

// Progress monitoring function
async function monitorExecution(threadId) {
  const maxAttempts = 60; // 5 minutes with 5-second intervals
  const pollInterval = 5000;
  let consecutiveErrors = 0;
  const maxConsecutiveErrors = 3;
  
  console.log(`📊 Starting progress monitoring for thread: ${threadId}`);
  
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      // Poll thread status
      const status = await client.threads.getStatus(threadId);
      
      // Reset error counter on successful response
      consecutiveErrors = 0;
      
      console.log(`[${attempt}/${maxAttempts}] Status: ${status.status} (Updated: ${status.updated_at})`);
      
      // Check if execution completed
      if (status.status === 'completed') {
        console.log('🎉 AOP execution completed successfully!');
        
        // Extract final result safely
        const conversationAsset = status.conversation_asset;
        if (conversationAsset?.last_message?.content) {
          const finalContent = conversationAsset.last_message.content;
          
          // Handle string content
          if (typeof finalContent === 'string') {
            return {
              success: true,
              status: 'completed',
              result: finalContent,
              threadId,
              conversationAssetId: conversationAsset.conversation_asset_id,
              messageCount: conversationAsset.num_messages,
            };
          }
          
          // Handle multimodal content (array)
          if (Array.isArray(finalContent)) {
            const textParts = finalContent
              .filter(part => part.type === 'text' && part.text)
              .map(part => part.text)
              .join('\n');
            
            return {
              success: true,
              status: 'completed',
              result: textParts,
              threadId,
              conversationAssetId: conversationAsset.conversation_asset_id,
              messageCount: conversationAsset.num_messages,
              isMultimodal: true,
            };
          }
        }
        
        // Completed but no content
        return {
          success: true,
          status: 'completed',
          result: 'AOP completed but no final message available',
          threadId,
        };
      } else if (status.status === 'failed') {
        console.error('❌ AOP execution failed');
        return {
          success: false,
          status: 'failed',
          error: 'AOP execution failed',
          threadId,
        };
      }
      
      // Still running - wait before next poll
      console.log(`⏳ Still running... (${status.status})`);
      await new Promise(resolve => setTimeout(resolve, pollInterval));
    } catch (error) {
      consecutiveErrors++;
      console.error(`Status check failed (${consecutiveErrors}/${maxConsecutiveErrors}):`, error.message);
      
      // Fail fast if too many consecutive errors
      if (consecutiveErrors >= maxConsecutiveErrors) {
        return {
          success: false,
          status: 'error',
          error: `Too many consecutive status check failures: ${error.message}`,
          threadId,
        };
      }
      
      // Wait before retrying
      await new Promise(resolve => setTimeout(resolve, pollInterval));
    }
  }
  
  // Timeout reached
  console.warn('⏰ Polling timeout reached');
  return {
    success: false,
    status: 'timeout',
    error: 'Monitoring timeout reached - execution may still be running',
    threadId,
  };
}

// Example usage
const marketAnalysisResult = await executeAOP(
  'asset_market_research_aop',
  {
    company: 'Tesla',
    quarter: 'Q3 2024',
    analysis_type: 'comprehensive',
  }
);

if (marketAnalysisResult.success) {
  console.log('✅ Market analysis result:', marketAnalysisResult.result);
} else {
  console.error('❌ Market analysis failed:', marketAnalysisResult.error);
}
```

### Advanced: Custom Progress Callbacks

Add custom progress callbacks for UI updates and analytics:

```javascript
// Execute AOP with custom progress tracking
async function executeAOPWithProgress(assetId, userInputs = {}, onProgress = null) {
  try {
    console.log(`🚀 Starting async AOP: ${assetId}`);
    
    // Step 1: Start async execution (returns immediately)
    const asyncResponse = await client.aop.executeAsync({
      asset_id: assetId,
      user_inputs: userInputs,
    });
    
    console.log('✅ AOP execution initiated');
    console.log('Thread ID:', asyncResponse.thread_id);
    console.log('AOP Title:', asyncResponse.aop_title);
    
    // Step 2: Monitor progress with callbacks
    const result = await monitorWithCallback(asyncResponse.thread_id, onProgress);
    
    return {
      success: result.success,
      startResponse: asyncResponse,
      finalResult: result,
    };
  } catch (error) {
    console.error('Async AOP execution failed:', error);
    return {
      success: false,
      error: error.message || 'Unknown error',
    };
  }
}

// Progress monitoring with callback support
async function monitorWithCallback(threadId, onProgress = null) {
  const maxAttempts = 120; // 10 minutes for longer workflows
  const pollInterval = 5000;
  let consecutiveErrors = 0;
  const maxConsecutiveErrors = 3;
  
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      const status = await client.threads.getStatus(threadId);
      
      // Reset error counter
      consecutiveErrors = 0;
      
      // Call progress callback if provided
      if (onProgress) {
        onProgress({
          attempt,
          maxAttempts,
          status: status.status,
          updatedAt: status.updated_at,
          threadId: status.thread_id,
        });
      }
      
      console.log(`[${attempt}/${maxAttempts}] Status: ${status.status} (${status.updated_at})`);
      
      if (status.status === 'completed') {
        console.log('🎉 AOP execution completed!');
        
        // Extract final result
        const conversationAsset = status.conversation_asset;
        if (conversationAsset?.last_message?.content) {
          const finalContent = conversationAsset.last_message.content;
          
          // Handle string or array content
          let resultText;
          if (typeof finalContent === 'string') {
            resultText = finalContent;
          } else if (Array.isArray(finalContent)) {
            resultText = finalContent
              .filter(part => part.type === 'text' && part.text)
              .map(part => part.text)
              .join('\n');
          } else {
            resultText = JSON.stringify(finalContent);
          }
          
          return {
            success: true,
            status: 'completed',
            result: resultText,
            conversationAssetId: conversationAsset.conversation_asset_id,
            messageCount: conversationAsset.num_messages,
            threadStatus: status,
          };
        } else {
          return {
            success: true,
            status: 'completed',
            result: 'AOP completed but no final message available',
            threadStatus: status,
          };
        }
      } else if (status.status === 'failed') {
        console.error('❌ AOP execution failed');
        return {
          success: false,
          status: 'failed',
          error: 'AOP execution failed',
          threadStatus: status,
        };
      }
      
      // Continue polling
      await new Promise(resolve => setTimeout(resolve, pollInterval));
    } catch (error) {
      consecutiveErrors++;
      console.error(`Status check failed (${consecutiveErrors}/${maxConsecutiveErrors}):`, error.message);
      
      // Fail fast if too many consecutive errors
      if (consecutiveErrors >= maxConsecutiveErrors) {
        return {
          success: false,
          status: 'error',
          error: `Too many consecutive failures: ${error.message}`,
        };
      }
      
      // Wait before retrying
      await new Promise(resolve => setTimeout(resolve, pollInterval));
    }
  }
  
  console.warn('⏰ Polling timeout reached');
  return {
    success: false,
    status: 'timeout',
    error: 'Monitoring timeout reached - execution may still be running',
  };
}

// Example usage with progress tracking
const progressCallback = (info) => {
  console.log(`📊 Progress: ${info.attempt}/${info.maxAttempts} - ${info.status}`);
  
  // Update UI or send to analytics
  if (typeof window !== 'undefined' && window.updateProgressUI) {
    window.updateProgressUI({
      percent: (info.attempt / info.maxAttempts) * 100,
      status: info.status,
      updatedAt: info.updatedAt,
    });
  }
};

const comprehensiveAnalysis = await executeAOPWithProgress(
  'asset_comprehensive_research_aop',
  {
    company: 'OpenAI',
    research_depth: 'comprehensive',
    include_financials: 'true',
    time_horizon: '2024-2025',
  },
  progressCallback
);

if (comprehensiveAnalysis.success) {
  console.log('✅ Comprehensive analysis result:', comprehensiveAnalysis.finalResult.result);
} else {
  console.error('❌ Analysis failed:', comprehensiveAnalysis.error);
}
```

### Batch Processing with Async Execution

Process multiple AOPs concurrently using async execution:

```javascript
// Batch AOP execution with async pattern
async function executeBatchAOPs(aopConfigs) {
  console.log(`🔄 Starting ${aopConfigs.length} AOPs concurrently...`);
  
  // Step 1: Start all AOPs asynchronously (all return immediately with thread_ids)
  const startPromises = aopConfigs.map(async (config, index) => {
    try {
      console.log(`Starting AOP ${index + 1}: ${config.name || config.assetId}`);
      
      const response = await client.aop.executeAsync({
        asset_id: config.assetId,
        user_inputs: config.userInputs || {},
      });
      
      console.log(`✅ ${config.name || 'AOP'} started with thread: ${response.thread_id}`);
      
      return {
        index,
        name: config.name || `AOP ${index + 1}`,
        threadId: response.thread_id,
        aopTitle: response.aop_title,
        success: true,
      };
    } catch (error) {
      console.error(`❌ Failed to start AOP ${index + 1}:`, error.message);
      return {
        index,
        name: config.name || `AOP ${index + 1}`,
        success: false,
        error: error.message || 'Unknown error',
      };
    }
  });
  
  const startResults = await Promise.all(startPromises);
  
  // Step 2: Monitor all successful starts until completion
  console.log(`📊 Monitoring ${startResults.filter(r => r.success).length} running AOPs...`);
  
  const monitorPromises = startResults
    .filter(result => result.success && result.threadId)
    .map(async (result) => {
      try {
        const finalResult = await monitorExecution(result.threadId);
        return {
          ...result,
          ...finalResult,
        };
      } catch (error) {
        return {
          ...result,
          success: false,
          status: 'error',
          error: error.message || 'Monitoring failed',
        };
      }
    });
  
  const finalResults = await Promise.all(monitorPromises);
  
  // Combine failed starts with monitoring results
  const allResults = [
    ...finalResults,
    ...startResults.filter(r => !r.success),
  ];
  
  // Calculate summary
  const successful = allResults.filter(r => r.success && r.status === 'completed');
  const failed = allResults.filter(r => !r.success || r.status !== 'completed');
  
  console.log(`\n✅ Batch complete: ${successful.length} successful, ${failed.length} failed`);
  
  return {
    successful,
    failed,
    summary: {
      total: aopConfigs.length,
      successful: successful.length,
      failed: failed.length,
    },
  };
}

// Example batch configuration
const batchConfigs = [
  {
    name: 'Market Research',
    assetId: 'asset_market_research_aop',
    userInputs: { company: 'Apple', quarter: 'Q3 2024' },
  },
  {
    name: 'Competitor Analysis',
    assetId: 'asset_competitor_analysis_aop',
    userInputs: { company: 'Apple', competitors: 'Samsung,Google,Microsoft' },
  },
  {
    name: 'Financial Summary',
    assetId: 'asset_financial_analysis_aop',
    userInputs: { company: 'Apple', period: 'annual', year: '2024' },
  },
];

const batchResults = await executeBatchAOPs(batchConfigs);

console.log('\n=== Batch Results ===');
batchResults.successful.forEach(result => {
  console.log(`✅ ${result.name}: ${result.result?.substring(0, 100)}...`);
});
batchResults.failed.forEach(result => {
  console.log(`❌ ${result.name}: ${result.error}`);
});
console.log(`\nSummary: ${batchResults.summary.successful}/${batchResults.summary.total} completed`);
```

### File Upload and Processing

Upload files and process them with AOPs using async execution:

```javascript
// File upload and processing workflow with async execution
async function uploadAndProcessFile(file, processingAOPId, processingInputs = {}) {
  try {
    console.log(`📁 Uploading file: ${file.name}`);
    
    // Step 1: Upload the file
    const uploadResponse = await client.tools.saveAsset({ file });
    
    if (!uploadResponse.asset_id) {
      throw new Error('File upload failed - no asset ID returned');
    }
    
    console.log('✅ File uploaded:', uploadResponse.asset_id);
    
    // Step 2: Start async processing with AOP
    console.log('🔄 Starting AOP processing...');
    
    const asyncResponse = await client.aop.executeAsync({
      asset_id: processingAOPId,
      user_inputs: {
        ...processingInputs,
        file_asset_id: uploadResponse.asset_id,
      },
    });
    
    console.log('✅ Processing started with thread:', asyncResponse.thread_id);
    
    // Step 3: Monitor processing until completion
    const processingResult = await monitorExecution(asyncResponse.thread_id);
    
    if (processingResult.success) {
      return {
        success: true,
        uploadedAssetId: uploadResponse.asset_id,
        processingResult: processingResult.result,
        threadId: asyncResponse.thread_id,
        conversationAssetId: processingResult.conversationAssetId,
      };
    } else {
      return {
        success: false,
        uploadedAssetId: uploadResponse.asset_id,
        error: processingResult.error || 'Processing failed',
        threadId: asyncResponse.thread_id,
      };
    }
  } catch (error) {
    console.error('File processing failed:', error);
    return {
      success: false,
      error: error.message || 'Unknown error',
    };
  }
}

// File input handler
function handleFileUpload(inputElement, processingAOPId) {
  inputElement.addEventListener('change', async (event) => {
    const file = event.target.files?.[0];
    
    if (!file) {
      console.log('No file selected');
      return;
    }
    
    console.log(`Selected file: ${file.name} (${file.size} bytes)`);
    
    const result = await uploadAndProcessFile(
      file,
      processingAOPId,
      {
        analysis_type: 'comprehensive',
        extract_insights: 'true',
      }
    );
    
    if (result.success) {
      console.log('File processing completed:', result.processingResult);
    } else {
      console.error('File processing failed:', result.error);
    }
  });
}
```

### Real-time Data Processing

Process data streams and handle updates:

```javascript
// Real-time data processor
class RealTimeAOPProcessor {
  constructor(client, aopAssetId) {
    this.client = client;
    this.aopAssetId = aopAssetId;
    this.processing = false;
    this.queue = [];
    this.results = [];
  }

  // Add data to processing queue
  addData(data, metadata = {}) {
    this.queue.push({
      data,
      metadata,
      timestamp: new Date().toISOString(),
    });
    
    console.log(`📊 Added data to queue. Queue length: ${this.queue.length}`);
    
    // Auto-process if not currently processing
    if (!this.processing) {
      this.processQueue();
    }
  }

  // Process queued data
  async processQueue() {
    if (this.processing || this.queue.length === 0) {
      return;
    }
    
    this.processing = true;
    console.log(`🔄 Processing ${this.queue.length} items...`);
    
    while (this.queue.length > 0) {
      const item = this.queue.shift();
      
      try {
        const result = await this.processItem(item);
        this.results.push(result);
        console.log(`✅ Processed item: ${result.success ? 'success' : 'failed'}`);
      } catch (error) {
        console.error('Item processing error:', error);
        this.results.push({
          success: false,
          error: error.message,
          originalData: item,
        });
      }
    }
    
    this.processing = false;
    console.log('🏁 Queue processing complete');
  }

  // Process individual item with async execution
  async processItem(item) {
    try {
      // Start async execution
      const asyncResponse = await this.client.aop.executeAsync({
        asset_id: this.aopAssetId,
        user_inputs: {
          input_data: JSON.stringify(item.data),
          metadata: JSON.stringify(item.metadata),
          timestamp: item.timestamp,
        },
      });
      
      console.log(`Processing item with thread: ${asyncResponse.thread_id}`);
      
      // Monitor execution (simplified for real-time processing)
      const result = await this.monitorItemExecution(asyncResponse.thread_id);
      
      return {
        success: result.success,
        result: result.result || 'No result content',
        threadId: asyncResponse.thread_id,
        originalData: item,
        processedAt: new Date().toISOString(),
      };
    } catch (error) {
      return {
        success: false,
        error: error.message || 'Processing failed',
        originalData: item,
        processedAt: new Date().toISOString(),
      };
    }
  }

  // Simplified monitoring for real-time items (shorter timeout)
  async monitorItemExecution(threadId) {
    const maxAttempts = 30; // 2.5 minutes for individual items
    const pollInterval = 5000;
    
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      try {
        const status = await this.client.threads.getStatus(threadId);
        
        if (status.status === 'completed') {
          const conversationAsset = status.conversation_asset;
          if (conversationAsset?.last_message?.content) {
            const content = conversationAsset.last_message.content;
            const result = typeof content === 'string' 
              ? content 
              : Array.isArray(content)
                ? content.filter(p => p.type === 'text').map(p => p.text).join('\n')
                : JSON.stringify(content);
            
            return { success: true, result };
          }
          return { success: true, result: 'Completed with no content' };
        } else if (status.status === 'failed') {
          return { success: false, error: 'Execution failed' };
        }
        
        await new Promise(resolve => setTimeout(resolve, pollInterval));
      } catch (error) {
        if (attempt === maxAttempts) {
          return { success: false, error: error.message };
        }
      }
    }
    
    return { success: false, error: 'Timeout' };
  }

  // Get processing results
  getResults() {
    return [...this.results];
  }

  // Clear results
  clearResults() {
    this.results = [];
  }
}

// Usage example
const dataProcessor = new RealTimeAOPProcessor(client, 'asset_data_analysis_aop');

// Simulate data stream
const sampleData = [
  { temperature: 23.5, humidity: 45, location: 'NYC' },
  { temperature: 21.2, humidity: 52, location: 'LA' },
  { temperature: 18.7, humidity: 38, location: 'Chicago' },
];

// Add data items with metadata
sampleData.forEach((data, index) => {
  dataProcessor.addData(data, { 
    source: 'sensor_network',
    batch_id: 'batch_001',
    sequence: index + 1,
  });
});

// Wait for processing to complete
setTimeout(() => {
  const results = dataProcessor.getResults();
  console.log(`📈 Processing complete: ${results.length} results`);
  results.forEach((result, index) => {
    console.log(`Result ${index + 1}:`, result.success ? result.result : result.error);
  });
}, 10000);
```

### Error Handling and Debugging

Comprehensive error handling patterns for browser environments:

```javascript
// Global error handler for SDK operations
class AthenaErrorHandler {
  static handleError(error, context = '') {
    console.error(`❌ Error in ${context}:`, error);
    
    if (error instanceof AthenaIntelligenceError) {
      const errorInfo = {
        type: 'AthenaIntelligenceError',
        statusCode: error.statusCode,
        message: error.message,
        context,
        timestamp: new Date().toISOString(),
      };
      
      // Log for debugging
      console.error('Athena API Error Details:', errorInfo);
      
      // Handle specific error codes
      switch (error.statusCode) {
        case 401:
          console.error('🔑 Authentication failed - check your API key');
          break;
        case 404:
          console.error('🔍 Resource not found - check asset IDs');
          break;
        case 400:
          console.error('📝 Bad request - check your input parameters');
          break;
        case 429:
          console.error('🚦 Rate limit exceeded - slow down requests');
          break;
        case 500:
          console.error('🏥 Server error - try again later');
          break;
        default:
          console.error(`🤷 Unknown API error: ${error.statusCode}`);
      }
      
      return errorInfo;
    } else {
      const errorInfo = {
        type: 'UnknownError',
        message: error.message || 'Unknown error occurred',
        context,
        timestamp: new Date().toISOString(),
      };
      
      console.error('Unknown Error Details:', errorInfo);
      return errorInfo;
    }
  }
  
  // Retry wrapper with exponential backoff
  static async withRetry(asyncFn, maxRetries = 3, context = '') {
    let lastError;
    
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        console.log(`🔄 Attempt ${attempt}/${maxRetries} for ${context}`);
        const result = await asyncFn();
        console.log(`✅ Success on attempt ${attempt} for ${context}`);
        return result;
      } catch (error) {
        lastError = error;
        
        // Don't retry on client errors (4xx)
        if (error instanceof AthenaIntelligenceError && 
            error.statusCode >= 400 && error.statusCode < 500) {
          console.error('❌ Client error - not retrying');
          break;
        }
        
        if (attempt < maxRetries) {
          const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
          console.log(`⏳ Waiting ${delay}ms before retry...`);
          await new Promise(resolve => setTimeout(resolve, delay));
        }
      }
    }
    
    throw this.handleError(lastError, context);
  }
}

// Safe execution wrapper with async execution
async function safeExecuteAOP(assetId, userInputs = {}) {
  return await AthenaErrorHandler.withRetry(
    async () => {
      // Start async execution
      const asyncResponse = await client.aop.executeAsync({
        asset_id: assetId,
        user_inputs: userInputs,
      });
      
      // Monitor until completion
      const result = await monitorExecution(asyncResponse.thread_id);
      
      if (!result.success) {
        throw new Error(result.error || 'AOP execution failed');
      }
      
      return result;
    },
    3,
    `AOP execution (${assetId})`
  );
}

// Usage with comprehensive error handling
try {
  const result = await safeExecuteAOP('asset_analysis_aop', {
    input: 'market data',
    format: 'detailed',
  });
  
  console.log('Safe execution result:', result);
} catch (errorInfo) {
  console.error('Final error after retries:', errorInfo);
  
  // Handle in UI
  if (typeof window !== 'undefined' && window.showErrorMessage) {
    window.showErrorMessage(`Failed to execute AOP: ${errorInfo.message}`);
  }
}
```

### Debug and Development Utilities

Helpful utilities for debugging in browser console:

```javascript
// Debug utilities for browser development
window.athenaDebug = {
  // Test connection
  async testConnection() {
    try {
      const userInfo = await client.me.get();
      console.log('✅ Connection successful:', userInfo);
      return true;
    } catch (error) {
      console.error('❌ Connection failed:', error);
      return false;
    }
  },

  // List available assets
  async listAssets(limit = 10) {
    try {
      const assets = await client.assets.list({ limit });
      console.log(`📁 Found ${assets.total} assets (showing first ${limit}):`);
      
      assets.items.forEach((asset, index) => {
        console.log(`${index + 1}. ${asset.title} (${asset.athena_original_type})`);
        console.log(`   ID: ${asset.id}`);
        console.log(`   Created: ${asset.created_at}`);
      });
      
      return assets;
    } catch (error) {
      console.error('Failed to list assets:', error);
      return null;
    }
  },

  // Quick AOP test with async execution
  async testAOP(assetId, userInputs = {}) {
    console.log(`🧪 Testing AOP: ${assetId}`);
    console.log('User inputs:', userInputs);
    
    try {
      // Start async execution
      const asyncResponse = await client.aop.executeAsync({
        asset_id: assetId,
        user_inputs: userInputs,
      });
      
      console.log('AOP started:', {
        threadId: asyncResponse.thread_id,
        aopTitle: asyncResponse.aop_title,
        status: asyncResponse.status,
      });
      
      // Monitor execution (short timeout for testing)
      const maxAttempts = 30; // 2.5 minutes
      const pollInterval = 5000;
      
      for (let attempt = 1; attempt <= maxAttempts; attempt++) {
        const status = await client.threads.getStatus(asyncResponse.thread_id);
        console.log(`[${attempt}/${maxAttempts}] Status: ${status.status}`);
        
        if (status.status === 'completed') {
          console.log('✅ Test completed successfully');
          console.log('Final result:', {
            conversationAssetId: status.conversation_asset?.conversation_asset_id,
            messageCount: status.conversation_asset?.num_messages,
            hasContent: !!status.conversation_asset?.last_message?.content,
          });
          return status;
        } else if (status.status === 'failed') {
          console.error('❌ Test failed');
          return status;
        }
        
        await new Promise(resolve => setTimeout(resolve, pollInterval));
      }
      
      console.warn('⏰ Test timeout reached');
      return null;
    } catch (error) {
      console.error('AOP test failed:', error);
      return null;
    }
  },

  // Monitor thread
  async monitorThread(threadId) {
    try {
      const status = await client.threads.getStatus(threadId);
      console.log('Thread status:', {
        id: threadId,
        status: status.status,
        updatedAt: status.updated_at,
        hasConversationAsset: !!status.conversation_asset,
        conversationState: status.conversation_asset?.state,
        messageCount: status.conversation_asset?.num_messages,
      });
      
      return status;
    } catch (error) {
      console.error('Thread monitoring failed:', error);
      return null;
    }
  },
};

// Development helper
console.log('🛠️ Athena Debug utilities available:');
console.log('  athenaDebug.testConnection() - Test API connection');
console.log('  athenaDebug.listAssets(limit) - List workspace assets');
console.log('  athenaDebug.testAOP(assetId, inputs) - Test AOP execution');
console.log('  athenaDebug.monitorThread(threadId) - Check thread status');
```

### Complete Browser Example

Here's a complete working example that demonstrates all patterns:

```javascript
// Complete browser implementation
import { AthenaIntelligenceClient, AthenaIntelligenceError } from 'https://esm.run/@athenaintel/sdk';

async function initializeAthenaApp() {
  try {
    // Initialize client with optional baseUrl override
    const client = new AthenaIntelligenceClient({
      apiKey: API_KEY,
      // Optional: override baseUrl for custom environments
      // baseUrl: 'https://your-custom-api.example.com', // Custom API
      // baseUrl: 'http://localhost:8000', // Local development
    });
    
    console.log('🚀 Athena Intelligence SDK loaded');
    
    // Test connection
    const userInfo = await client.users.me();
    console.log('👤 User:', userInfo.email);
    console.log('👤 Name:', userInfo.first_name, userInfo.last_name);
    
    // Example: Quick agent interaction
    const quickResponse = await client.agents.general.invoke({
      config: { model: 'gpt-4-turbo-preview' },
      messages: [
        {
          content: 'Hello! Can you help me understand how AOPs work?',
          role: 'user',
          type: 'user',
        },
      ],
    });
    
    const agentResponse = quickResponse.messages?.[quickResponse.messages.length - 1]?.kwargs?.content;
    console.log('🤖 Agent says:', agentResponse);
    
    // Example: Async AOP execution
    console.log('🚀 Starting async AOP execution...');
    const asyncResponse = await client.aop.executeAsync({
      asset_id: 'asset_example_aop',
      user_inputs: {
        topic: 'browser SDK usage',
        format: 'comprehensive',
      },
    });
    
    console.log('✅ AOP initiated with thread:', asyncResponse.thread_id);
    console.log('📋 AOP Title:', asyncResponse.aop_title);
    
    // Monitor execution (simplified example)
    console.log('📊 Monitoring execution...');
    const maxAttempts = 30;
    const pollInterval = 5000;
    
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      const status = await client.threads.getStatus(asyncResponse.thread_id);
      console.log(`[${attempt}/${maxAttempts}] Status: ${status.status}`);
      
      if (status.status === 'completed') {
        console.log('🎉 AOP execution completed!');
        const finalContent = status.conversation_asset?.last_message?.content;
        
        if (finalContent) {
          const result = typeof finalContent === 'string' 
            ? finalContent 
            : Array.isArray(finalContent)
              ? finalContent.filter(p => p.type === 'text').map(p => p.text).join('\n')
              : JSON.stringify(finalContent);
          
          console.log('📝 AOP Output:', result);
        } else {
          console.log('⚠️ No final output from AOP');
        }
        break;
      } else if (status.status === 'failed') {
        console.error('❌ AOP execution failed');
        break;
      }
      
      if (attempt < maxAttempts) {
        await new Promise(resolve => setTimeout(resolve, pollInterval));
      }
    }
    
    // Make client available globally for debugging
    window.athenaClient = client;
    console.log('🌐 Client available as window.athenaClient');
    
    return {
      client,
      userInfo,
      ready: true,
    };
  } catch (error) {
    console.error('❌ Initialization failed:', error);
    
    if (error instanceof AthenaIntelligenceError) {
      console.error(`API Error: ${error.statusCode} - ${error.message}`);
    }
    
    return {
      client: null,
      ready: false,
      error: error.message,
    };
  }
}

// Initialize when DOM is ready
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', initializeAthenaApp);
} else {
  initializeAthenaApp();
}
```