Browser JavaScript (ESM)
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:
// Import the SDK from ESM CDNimport { 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 endpointsconst customClient = new AthenaIntelligenceClient({apiKey: API_KEY,baseUrl: 'https://your-custom-api.example.com', // Custom API endpoint});// Use development/localhost environmentconst 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:
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 safelyconst 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 functionrunSimpleAgent().then(result => {if (result) {console.log('Success:', result);}});
Multi-Tool Workflow
Combine multiple tools for complex tasks:
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 responseconst 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 typesconst 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 callsif (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:
class ConversationManager {constructor(client) {this.client = client;this.messages = [];this.threadId = null;}// Add a system messageaddSystemMessage(content) {this.messages.push({content,role: 'system',type: 'system',});}// Add a user messageaddUserMessage(content) {this.messages.push({content,role: 'user',type: 'user',});}// Send messages and get responseasync sendMessage(userInput, config = {}) {try {// Add user input to conversationthis.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 conversationconst responseMessages = response.messages || [];const lastMessage = responseMessages[responseMessages.length - 1];if (lastMessage?.kwargs?.content) {const assistantContent = lastMessage.kwargs.content;// Add assistant response to conversation historythis.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 historygetHistory() {return [...this.messages];}// Clear conversationclear() {this.messages = [];this.threadId = null;}}// Usage exampleasync function runConversation() {const conversation = new ConversationManager(client);// Set up conversation contextconversation.addSystemMessage('You are a helpful AI assistant specializing in technology and business analysis.');// First messageconst 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 contextconst 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 historyconsole.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:
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:
// 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 itconsole.log('โ AOP execution initiated (running in background)');console.log('Thread ID:', asyncResponse.thread_id);console.log('Status:', asyncResponse.status); // Will be "started" or similarconsole.log('AOP Title:', asyncResponse.aop_title);// Step 2: Monitor execution until it actually completesconst 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 functionasync function monitorExecution(threadId) {const maxAttempts = 60; // 5 minutes with 5-second intervalsconst 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 statusconst status = await client.threads.getStatus(threadId);// Reset error counter on successful responseconsecutiveErrors = 0;console.log(`[${attempt}/${maxAttempts}] Status: ${status.status} (Updated: ${status.updated_at})`);// Check if execution completedif (status.status === 'completed') {console.log('๐ AOP execution completed successfully!');// Extract final result safelyconst conversationAsset = status.conversation_asset;if (conversationAsset?.last_message?.content) {const finalContent = conversationAsset.last_message.content;// Handle string contentif (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 contentreturn {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 pollconsole.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 errorsif (consecutiveErrors >= maxConsecutiveErrors) {return {success: false,status: 'error',error: `Too many consecutive status check failures: ${error.message}`,threadId,};}// Wait before retryingawait new Promise(resolve => setTimeout(resolve, pollInterval));}}// Timeout reachedconsole.warn('โฐ Polling timeout reached');return {success: false,status: 'timeout',error: 'Monitoring timeout reached - execution may still be running',threadId,};}// Example usageconst 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:
// Execute AOP with custom progress trackingasync 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 callbacksconst 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 supportasync function monitorWithCallback(threadId, onProgress = null) {const maxAttempts = 120; // 10 minutes for longer workflowsconst 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 counterconsecutiveErrors = 0;// Call progress callback if providedif (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 resultconst conversationAsset = status.conversation_asset;if (conversationAsset?.last_message?.content) {const finalContent = conversationAsset.last_message.content;// Handle string or array contentlet 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 pollingawait new Promise(resolve => setTimeout(resolve, pollInterval));} catch (error) {consecutiveErrors++;console.error(`Status check failed (${consecutiveErrors}/${maxConsecutiveErrors}):`, error.message);// Fail fast if too many consecutive errorsif (consecutiveErrors >= maxConsecutiveErrors) {return {success: false,status: 'error',error: `Too many consecutive failures: ${error.message}`,};}// Wait before retryingawait 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 trackingconst progressCallback = (info) => {console.log(`๐ Progress: ${info.attempt}/${info.maxAttempts} - ${info.status}`);// Update UI or send to analyticsif (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:
// Batch AOP execution with async patternasync 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 completionconsole.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 resultsconst allResults = [...finalResults,...startResults.filter(r => !r.success),];// Calculate summaryconst 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 configurationconst 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:
// File upload and processing workflow with async executionasync function uploadAndProcessFile(file, processingAOPId, processingInputs = {}) {try {console.log(`๐ Uploading file: ${file.name}`);// Step 1: Upload the fileconst 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 AOPconsole.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 completionconst 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 handlerfunction 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:
// Real-time data processorclass RealTimeAOPProcessor {constructor(client, aopAssetId) {this.client = client;this.aopAssetId = aopAssetId;this.processing = false;this.queue = [];this.results = [];}// Add data to processing queueaddData(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 processingif (!this.processing) {this.processQueue();}}// Process queued dataasync 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 executionasync processItem(item) {try {// Start async executionconst 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 itemsconst 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 resultsgetResults() {return [...this.results];}// Clear resultsclearResults() {this.results = [];}}// Usage exampleconst dataProcessor = new RealTimeAOPProcessor(client, 'asset_data_analysis_aop');// Simulate data streamconst 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 metadatasampleData.forEach((data, index) => {dataProcessor.addData(data, {source: 'sensor_network',batch_id: 'batch_001',sequence: index + 1,});});// Wait for processing to completesetTimeout(() => {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:
// Global error handler for SDK operationsclass 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 debuggingconsole.error('Athena API Error Details:', errorInfo);// Handle specific error codesswitch (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 backoffstatic 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 executionasync function safeExecuteAOP(assetId, userInputs = {}) {return await AthenaErrorHandler.withRetry(async () => {// Start async executionconst asyncResponse = await client.aop.executeAsync({asset_id: assetId,user_inputs: userInputs,});// Monitor until completionconst 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 handlingtry {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 UIif (typeof window !== 'undefined' && window.showErrorMessage) {window.showErrorMessage(`Failed to execute AOP: ${errorInfo.message}`);}}
Debug and Development Utilities
Helpful utilities for debugging in browser console:
// Debug utilities for browser developmentwindow.athenaDebug = {// Test connectionasync 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 assetsasync 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 executionasync testAOP(assetId, userInputs = {}) {console.log(`๐งช Testing AOP: ${assetId}`);console.log('User inputs:', userInputs);try {// Start async executionconst 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 minutesconst 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 threadasync 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 helperconsole.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:
// Complete browser implementationimport { AthenaIntelligenceClient, AthenaIntelligenceError } from 'https://esm.run/@athenaintel/sdk';async function initializeAthenaApp() {try {// Initialize client with optional baseUrl overrideconst 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 connectionconst userInfo = await client.users.me();console.log('๐ค User:', userInfo.email);console.log('๐ค Name:', userInfo.first_name, userInfo.last_name);// Example: Quick agent interactionconst 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 executionconsole.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 debuggingwindow.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 readyif (document.readyState === 'loading') {document.addEventListener('DOMContentLoaded', initializeAthenaApp);} else {initializeAthenaApp();}
