Javascript APIs

The Javascript APIs offer Client Side automation to interact with your Digital twin, such as sending a message, listing favorites and executing assistant instructions.
You must integrate your Digital Twin in a Web Application using the Web SDK or in Canvas using the Theme based injection to leverage the Javascript API functionality.

Global Window Object

Once loaded in your web application, Pria is available as a global window object and exposes the following methods:
const pria = {
    load: priasdk,                // Initialize Pria SDK
    send: priaSend,               // Send requests to Pria
    subscribe: priaSubscribe,     // Subscribe to responses
    unsubscribe: priaUnsubscribe, // Unsubscribe from responses
    setVisible: priaSetVisible,   // Control UI visibility
    version: 1                    // SDK version
}

Available Commands

CommandDescriptionParameters
post.messageSend text message to Priainputs: [Array of strings]
convo.startStart speech-to-speech conversationNone
convo.stopStop speech-to-speech conversationNone
assistants.listGet available assistantsNone
favorites.listGet list of user’s favoritesNone
conversations.listGet list of user’s conversationsNone

Sending Requests

Basic Message Request

Send a text message to your digital twin:
const request = {
    command: 'post.message',
    inputs: ['How are you?', 'Today is my birthday!']
}

pria.send(request)

Conversation Mode

Start speech-to-speech conversation:
const request = {
    command: 'convo.start'
}

pria.send(request)
Stop conversation mode:
const request = {
    command: 'convo.stop'
}

pria.send(request)

Error Handling

The pria.send() function may throw these errors:
  • “Connect Pria first, then retry” - Pria is not properly initialized
  • “Function requires valid JSON” - Invalid request format

Receiving Responses

Subscribe to Responses

To receive responses from Pria, you must first subscribe:
const handlePriaResponse = (response) => {
    console.log('Received from Pria:', response)
    // Process the response here
}

pria.subscribe(handlePriaResponse)

Response Format

All responses follow this structure:
{
    "type": "pria-response",
    "response": {
        "command": "post.message",
        "content": {
            "success": true,
            "outputs": ["Response text here"],
            "usage": 12048,
            "query_duration_ms": 9404,
            "model": "us.anthropic.claude-3-5-sonnet-20240620-v1:0"
        },
        "isError": false,
        "type": "object"
    },
    "version": 1
}

Response Examples

{
    "type": "pria-response",
    "response": {
        "command": "post.message",
        "content": {
            "success": true,
            "outputs": ["I am doing great! Happy birthday by the way.."],
            "usage": 12048,
            "query_duration_ms": 9404,
            "model": "us.anthropic.claude-3-5-sonnet-20240620-v1:0"
        },
        "isError": false,
        "type": "object"
    },
    "version": 1
}

Authentication & Security

The SDK uses the identity of the user currently connected to the digital twin. Ensure proper authentication is in place before making requests.

Requirements

  • Pria must be properly configured and fully connected
  • User must be authenticated with appropriate permissions
  • Valid session must be established

Content Format

Pria outputs content in Markdown format. Parse responses accordingly in your application.

Usage Metrics

The usage property in responses indicates the total number of tokens consumed (input + output) for billing and monitoring purposes.

Best Practices

Error Handling

const sendMessage = async (message) => {
    try {
        const request = {
            command: 'post.message',
            inputs: [message]
        }
        
        pria.send(request)
    } catch (error) {
        console.error('Failed to send message:', error)
        // Handle error appropriately
    }
}

Response Processing

const handleResponse = (response) => {
    if (response.response.isError) {
        console.error('Pria error:', response.response.content)
        return
    }
    
    // Process successful response
    const outputs = response.response.content.outputs
    outputs.forEach(output => {
        // Display or process each output
        console.log(output)
    })
}

Cleanup

// Unsubscribe when component unmounts or page unloads
window.addEventListener('beforeunload', () => {
    pria.unsubscribe(handleResponse)
})

Troubleshooting

Common Issues

IssueSolution
”Connect Pria first” errorEnsure SDK is loaded and initialized
No responses receivedCheck if you’ve subscribed to responses
Unauthorized errorsVerify user authentication and permissions
Invalid JSON errorsValidate request format and structure

Debug Mode

Enable debug logging to troubleshoot integration issues:
// Add to your configuration
var displayOptions = {
    // ... other options
    debug: true  // Enable debug logging
}

SDK Playground Example

You can take a look at a running example at SDK Playground Example.
https://pria.praxislxp.com/pria-sdk-web-sample.html
SDK Playground Example This example demonstrates how to cleanly initialize the integration, detects when sucessfully connected, execute specific commands; such as starting conversation, listing favorites, conversations or assistants, posting a new message, and more.

API Class Example

This example is provided AS IS to demonstrate how you can cleanly integrate a Digital Twin in your Web Application and sendvarious commands programatically in response to user actions on the page. It is extracted from the playground example code.
/**
* Pria SDK Test Harness Application
* Enhanced version with modern JavaScript patterns and professional UI
*/
class PriaTestHarness {
    constructor() {
        this.pria = null;
        this.waitForPriaTimer = null;
        this.uiDisplayed = false;
        this.isConnected = false;
        
        // Configuration
        this.config = {
            displayOptions: {
                buttonPositionRight: 'calc(50% - 40px)',
                buttonPositionBottom: '80px'
            },
            instanceConfig: {
                publicIdguest: '41407647-248c-4f0e-a317-71fc151ba8fb', 
                publicId: 'f831501f-b645-481a-9cbb-331509aaf8c1',
                pictureUrl: 'https://ca.slack-edge.com/T08Q47N2NUT-U08PZ8CUVDK-d32d2c5679ad-512'
            },
            userConfig: {
                email: 'alex@praxis-ai.com',
                profilename: 'Alex Lebegue',
                usertype: 1,
                userid: 110,
                roleid: 123,               
                rolename: "Course ABC",
                partnerid: 1,              
                partnername: "ABC Global Inc." 
            },
            conversation: {
                id: 777,
                name: "My Conversation"
            }
        };
        
        this.init();
    }
    
    /**
    * Initialize the application
    */
    async init() {
        try {
            await this.loadPriaSDK();
            this.bindEventListeners();
            this.showToast('Application initialized successfully', 'success');
        } catch (error) {
            console.error('Failed to initialize application:', error);
            this.showToast('Failed to initialize application', 'error');
        }
    }
    
    /**
    * Load the Pria SDK
    */
    loadPriaSDK() {
        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.src = 'pria-sdk-web.js';
            script.async = true;
            
            script.onload = () => {
                console.log('Web SDK Script loaded');

                const url = 'https://pria.praxislxp.com';
                
                PriaIntegration.loadSdk(
                    url, 
                    this.config.displayOptions, 
                    this.config.instanceConfig, 
                    this.config.userConfig
                );
                
                this.waitForPriaTimer = setInterval(() => this.waitForPria(), 2000);
                resolve();
            };
            
            script.onerror = (error) => {
                console.error('Failed to load Web SDK:', error);
                reject(new Error('Web SDK loading failed'));
            };
            
            document.body.appendChild(script);
        });
    }
    
    /**
    * Wait for Pria to be available and set up subscriptions
    */
    waitForPria() {
        if (!window.pria) {
            console.log("Waiting for Pria to load...");
            return;
        }
        
        // console.log('Pria loaded:', JSON.stringify(window.pria.priaObj, null, 2));
        
        clearInterval(this.waitForPriaTimer);
        this.pria = window.pria;
        this.isConnected = true;
        
        this.updateConnectionStatus(true);
        this.pria.subscribe(this.handlePriaResponse.bind(this));
        this.showToast('Connected to Pria SDK', 'success');
    }
    
    /**
    * Handle responses from Pria
    */
    handlePriaResponse(response) {
        console.log("Response from Pria:", JSON.stringify(response, null, 2));
        this.displayResponse(response);
        this.hideLoading();
    }
    
    /**
    * Bind event listeners to UI elements
    */
    bindEventListeners() {
        // Message sending
        document.getElementById('send-message-btn').addEventListener('click', () => {
            this.sendMessage();
        });
        
        // Quick actions
        document.getElementById('start-conversation-btn').addEventListener('click', () => {
            this.startConversation();
        });
        
        document.getElementById('stop-conversation-btn').addEventListener('click', () => {
            this.stopConversation();
        });
        
        document.getElementById('get-assistants-btn').addEventListener('click', () => {
            this.getAssistants();
        });
        
        document.getElementById('get-conversations-btn').addEventListener('click', () => {
            this.getConversations();
        });
        
        document.getElementById('get-favorites-btn').addEventListener('click', () => {
            this.getFavorites();
        });
        
        // Toggle Pria visibility
        document.getElementById('toggle-pria-btn').addEventListener('click', () => {
            this.togglePriaVisibility();
        });
        
        // Clear response
        document.getElementById('clear-response-btn').addEventListener('click', () => {
            this.clearResponse();
        });
        
        // Enter key support for message input
        document.getElementById('message-input').addEventListener('keydown', (e) => {
            if (e.ctrlKey && e.key === 'Enter') {
                this.sendMessage();
            }
        });
    }
    
    /**
    * Send a message to Pria
    */
    sendMessage() {
        if (!this.ensurePriaConnection()) return;
        
        const message = document.getElementById('message-input').value.trim();
        const assistantId = document.getElementById('assistant-id-input').value.trim();
        
        if (!message) {
            this.showToast('Please enter a message', 'warning');
            return;
        }
        
        if (!assistantId) {
            this.showToast('Please enter an assistant ID', 'warning');
            return;
        }
        
        this.showLoading();
        this.clearResponse();
        
        const request = {
            command: 'message.post',
            inputs: [message],
            assistantId: assistantId,
            selectedCourse: {
                course_id: this.config.conversation.id,
                course_name: this.config.conversation.name
            }
        };
        
        this.pria.send(request);
        this.showPria();
        this.showToast('Message sent', 'info');
    }
    
    /**
    * Start a conversation
    */
    startConversation() {
        if (!this.ensurePriaConnection()) return;
        
        this.showLoading();
        this.clearResponse();
        
        const request = {
            command: 'convo.start',
            assistantId: '674e9fd3d7e18aa82eb49fda',
            selectedCourse: {
                course_id: 22345,
                course_name: 'Conversational Assist'
            }
        };
        
        this.pria.send(request);
        this.showPria();
        this.showToast('Starting conversation', 'info');
    }
    
    /**
    * Stop a conversation
    */
    stopConversation() {
        if (!this.ensurePriaConnection()) return;
        
        const request = {
            command: 'convo.stop'
        };
        
        this.pria.send(request);
        this.showToast('Conversation stopped', 'info');
    }
    
    /**
    * Get list of assistants
    */
    getAssistants() {
        if (!this.ensurePriaConnection()) return;
        
        this.showLoading();
        this.clearResponse();
        
        const request = {
            command: 'assistants.list'
        };
        
        this.pria.send(request);
        this.showToast('Fetching assistants', 'info');
    }
    
    /**
    * Get list of conversations
    */
    getConversations() {
        if (!this.ensurePriaConnection()) return;
        
        this.showLoading();
        this.clearResponse();
        
        const request = {
            command: 'conversations.list'
        };
        
        this.pria.send(request);
        this.showToast('Fetching conversations', 'info');
    }
    
    /**
    * Get list of favorites
    */
    getFavorites() {
        if (!this.ensurePriaConnection()) return;
        
        this.showLoading();
        this.clearResponse();
        
        const request = {
            command: 'favorites.list'
        };
        
        this.pria.send(request);
        this.showToast('Fetching favorites', 'info');
    }
    
    
    /**
    * Toggle Pria visibility
    */
    togglePriaVisibility() {
        if (!this.ensurePriaConnection()) return;
        
        this.uiDisplayed = !this.uiDisplayed;
        this.pria.display(this.uiDisplayed);
        
        const btn = document.getElementById('toggle-pria-btn');
        const icon = btn.querySelector('i');
        const text = btn.querySelector('span');
        
        if (this.uiDisplayed) {
            icon.className = 'fas fa-eye-slash';
            text.textContent = 'Hide Pria';
            this.showToast('Pria UI shown', 'info');
        } else {
            icon.className = 'fas fa-eye';
            text.textContent = 'Show Pria';
            this.showToast('Pria UI hidden', 'info');
        }
    }
    
    /**
    * Show Pria interface
    */
    showPria() {
        if (this.pria && !this.uiDisplayed) {
            this.pria.display(true)
            this.uiDisplayed = true;
        }
    }
    
    /**
    * Display response in the viewer
    */
    displayResponse(data) {
        const viewer = document.getElementById('response-viewer');
        viewer.value = data ? JSON.stringify(data, null, 2) : '';
    }
    
    /**
    * Clear the response viewer
    */
    clearResponse() {
        document.getElementById('response-viewer').value = '';
    }
    
    /**
    * Show loading indicator
    */
    showLoading() {
        document.getElementById('loading-indicator').classList.remove('hidden');
    }
    
    /**
    * Hide loading indicator
    */
    hideLoading() {
        document.getElementById('loading-indicator').classList.add('hidden');
    }
    
    /**
    * Update connection status indicator
    */
    updateConnectionStatus(connected) {
        const statusElement = document.getElementById('connection-status');
        const dot = statusElement.querySelector('div');
        const text = statusElement.querySelector('span');
        
        if (connected) {
            dot.className = 'w-3 h-3 bg-green-500 rounded-full';
            text.textContent = 'Connected';
            text.className = 'text-sm text-green-600';
        } else {
            dot.className = 'w-3 h-3 bg-red-500 rounded-full animate-pulse';
            text.textContent = 'Disconnected';
            text.className = 'text-sm text-red-600';
        }
    }
    
    /**
    * Ensure Pria connection exists
    */
    ensurePriaConnection() {
        if (!this.pria || !this.isConnected) {
            this.showToast('Pria SDK not connected', 'error');
            return false;
        }
        return true;
    }
    
    /**
    * Show toast notification
    */
    showToast(message, type = 'info') {
        const container = document.getElementById('toast-container');
        const toast = document.createElement('div');
        
        const colors = {
            success: 'bg-green-500',
            error: 'bg-red-500',
            warning: 'bg-yellow-500',
            info: 'bg-blue-500'
        };
        
        const icons = {
            success: 'fas fa-check-circle',
            error: 'fas fa-exclamation-circle',
            warning: 'fas fa-exclamation-triangle',
            info: 'fas fa-info-circle'
        };
        
        toast.className = `${colors[type]} text-white px-6 py-3 rounded-lg shadow-lg flex items-center space-x-3 transform transition-all duration-300 translate-x-full`;
        toast.innerHTML = `
            <i class="${icons[type]}"></i>
            <span>${message}</span>
        `;
        
        container.appendChild(toast);
        
        // Animate in
        setTimeout(() => {
            toast.classList.remove('translate-x-full');
        }, 100);
        
        // Auto remove
        setTimeout(() => {
            toast.classList.add('translate-x-full');
            setTimeout(() => {
                if (container.contains(toast)) {
                    container.removeChild(toast);
                }
            }, 300);
        }, 3000);
    }
}

// Initialize the application when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
    new PriaTestHarness();
});