Skip to main content

JavaScript/TypeScript Integration

Complete JavaScript examples for integrating with Enclava chatbots.

Create and Chat

class EnclavaChatbot {
constructor(apiKey, baseUrl = 'http://localhost/api/v1') {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
this.headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
}

async createChatbot(config) {
const response = await fetch(`${this.baseUrl}/chatbot/create`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify(config)
});

if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Failed to create chatbot');
}

return await response.json();
}

async chat(chatbotId, message, conversationId = null) {
const response = await fetch(`${this.baseUrl}/chatbot/chat`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
chatbot_id: chatbotId,
message,
conversation_id: conversationId
})
});

if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Failed to chat');
}

return await response.json();
}
}

// Usage
async function main() {
const client = new EnclavaChatbot('YOUR_API_KEY');

// Create chatbot
const chatbot = await client.createChatbot({
name: 'Support Bot',
model: 'gpt-3.5-turbo',
system_prompt: 'You are a helpful support agent.',
use_rag: true,
rag_collection: 'documentation'
});

console.log(`Created chatbot: ${chatbot.id}`);

// Chat
const response = await client.chat(
chatbot.id,
'How do I reset my password?'
);

console.log(`Bot: ${response.response}`);

if (response.rag_used) {
console.log(`RAG sources: ${response.rag_sources?.length || 0}`);
}
}

main().catch(console.error);

Conversation Management

class EnclavaConversation {
constructor(client, chatbotId) {
this.client = client;
this.chatbotId = chatbotId;
this.conversationId = null;
this.history = [];
}

async send(message) {
const response = await this.client.chat(
this.chatbotId,
message,
this.conversationId
);

// Update conversation ID
this.conversationId = response.conversation_id || null;

// Track history
this.history.push({
role: 'user',
content: message,
timestamp: new Date().toISOString()
});

if (response.response) {
this.history.push({
role: 'assistant',
content: response.response,
timestamp: new Date().toISOString()
});
}

return response;
}

getHistory() {
return this.history;
}
}

async function main() {
const client = new EnclavaChatbot('YOUR_API_KEY');

const chatbot = await client.createChatbot({
name: 'Conversation Bot',
model: 'gpt-3.5-turbo',
system_prompt: 'You are a helpful assistant. Remember our conversation.'
});

const conv = new EnclavaConversation(client, chatbot.id);

// Multi-turn conversation
await conv.send('My name is Alice');
console.log('User: My name is Alice');

await conv.send('What\'s your name?');
console.log('Bot:', (await conv.send('I live in New York')).response);

await conv.send('Where am I from?');
console.log('User: Where am I from?');

// View history
console.log('\nConversation History:');
conv.getHistory().forEach((msg, i) => {
console.log(`${i + 1}. [${msg.role}]: ${msg.content}`);
});
}

main().catch(console.error);

RAG-Enhanced Chatbot

class RAGChatbot {
constructor(apiKey) {
this.apiKey = apiKey;
this.headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
}

async createRAGChatbot(name, ragCollection) {
const systemPrompt = `You are a helpful assistant that answers questions based on the ${ragCollection} knowledge base.
When you find relevant information, cite it naturally in your response.
If you don't find relevant information, say so honestly.`;

const response = await fetch('http://localhost/api/v1/chatbot/create', {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
name,
model: 'gpt-3.5-turbo',
system_prompt: systemPrompt,
use_rag: true,
rag_collection: ragCollection,
rag_top_k: 5,
similarity_threshold: 0.7
})
});

return await response.json();
}

async chatWithContext(chatbotId, message) {
const response = await fetch('http://localhost/api/v1/chatbot/chat', {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
chatbot_id: chatbotId,
message
})
});

const result = await response.json();
const answer = result.response;

// Display RAG context if available
if (result.rag_sources && result.rag_sources.length > 0) {
console.log('\n**Relevant Documents:**');
result.rag_sources.forEach((source, i) => {
console.log(`${i + 1}. Document: ${source.document_id} (relevance: ${source.score.toFixed(2)})`);
if (source.content) {
const preview = source.content.substring(0, 100);
console.log(` Preview: ${preview}...`);
}
});
}

console.log(`\nAnswer: ${answer}`);
return result;
}
}

async function main() {
const client = new RAGChatbot('YOUR_API_KEY');

const chatbot = await client.createRAGChatbot(
'Documentation Assistant',
'product_docs'
);

console.log(`Created chatbot: ${chatbot.id}`);

await client.chatWithContext(
chatbot.id,
'How do I configure the API key?'
);
}

main().catch(console.error);

React Integration

import React, { useState, useCallback } from 'react';

function ChatbotInterface() {
const [chatbotId, setChatbotId] = useState('');
const [message, setMessage] = useState('');
const [conversation, setConversation] = useState([]);
const [loading, setLoading] = useState(false);
const [conversationId, setConversationId] = useState(null);

const sendMessage = useCallback(async () => {
if (!message.trim() || loading) return;

setLoading(true);
try {
const response = await fetch('http://localhost/api/v1/chatbot/chat', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
chatbot_id: chatbotId,
message,
conversation_id: conversationId
})
});

const result = await response.json();

// Add user message to conversation
setConversation(prev => [...prev, { role: 'user', content: message }]);

// Add bot response
setConversation(prev => [...prev, { role: 'assistant', content: result.response }]);

// Update conversation ID
setConversationId(result.conversation_id || conversationId);

setMessage('');
} catch (error) {
console.error('Error sending message:', error);
alert('Failed to send message');
} finally {
setLoading(false);
}
}, [chatbotId, message, conversationId, loading]);

const createChatbot = async () => {
try {
const response = await fetch('http://localhost/api/v1/chatbot/create', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'My Chatbot',
model: 'gpt-3.5-turbo',
system_prompt: 'You are a helpful assistant.',
use_rag: true,
rag_collection: 'docs'
})
});

const chatbot = await response.json();
setChatbotId(chatbot.id);
console.log('Created chatbot:', chatbot.id);
} catch (error) {
console.error('Error creating chatbot:', error);
}
};

return (
<div className="max-w-4xl mx-auto p-6">
{!chatbotId ? (
<button
onClick={createChatbot}
className="px-4 py-2 bg-blue-500 text-white rounded"
>
Create Chatbot
</button>
) : (
<div className="space-y-4">
<div className="border rounded-lg p-4">
{conversation.map((msg, i) => (
<div key={i} className={`mb-2 ${msg.role === 'user' ? 'text-right' : 'text-left'}`}>
<span className={`inline-block px-3 py-1 rounded ${
msg.role === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-200'
}`}>
{msg.content}
</span>
</div>
))}
</div>

<div className="flex space-x-2">
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
className="flex-1 px-4 py-2 border rounded"
placeholder="Type your message..."
disabled={loading}
/>
<button
onClick={sendMessage}
disabled={loading}
className="px-6 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
>
{loading ? 'Sending...' : 'Send'}
</button>
</div>
</div>
)}
</div>
);
}

export default ChatbotInterface;

Streaming Responses

class EnclavaChatbotStream {
constructor(apiKey) {
this.apiKey = apiKey;
this.headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
}

async chatStream(chatbotId, message, onChunk) {
const response = await fetch('http://localhost/api/v1/chatbot/chat', {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
chatbot_id: chatbotId,
message,
stream: true
})
});

if (!response.ok) {
throw new Error('Stream request failed');
}

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
const { done, value } = await reader.read();
if (done) break;

const chunk = decoder.decode(value);
const lines = chunk.split('\n');

for (const line of lines) {
if (line.startsWith('response:')) {
const content = line.slice(9);
onChunk(content);
}
}
}
}
}

async function main() {
const client = new EnclavaChatbotStream('YOUR_API_KEY');

let fullResponse = '';

await client.chatStream(
'your-chatbot-id',
'Tell me a story',
(chunk) => {
process.stdout.write(chunk);
fullResponse += chunk;
}
);

console.log('\nFull response:', fullResponse);
}

main().catch(console.error);

Error Handling

class RobustChatbotClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.base_url = 'http://localhost/api/v1';
this.headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
this.maxRetries = 3;
this.retryDelay = 1000;
}

async chatWithRetry(chatbotId, message, retries = 0) {
try {
const response = await fetch(`${this.base_url}/chatbot/chat`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
chatbot_id: chatbotId,
message
})
});

if (!response.ok) {
// Retry on rate limit or server errors
if (retries < this.maxRetries && [429, 500, 502, 503].includes(response.status)) {
console.log(`Attempt ${retries + 1} failed. Retrying...`);
await new Promise(resolve => setTimeout(resolve, this.retryDelay * (retries + 1)));
return this.chatWithRetry(chatbotId, message, retries + 1);
}
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}

return await response.json();
} catch (error) {
console.error('Request failed:', error);
throw error;
}
}
}

async function main() {
const client = new RobustChatbotClient('YOUR_API_KEY');

try {
const response = await client.chatWithRetry(
'your-chatbot-id',
'Hello!'
);
console.log('Response:', response.response);
} catch (error) {
console.error('Failed after retries:', error);
}
}

main().catch(console.error);

Best Practices

  1. Use Conversation IDs - Maintain context across messages
  2. Handle Streaming - Provide better UX for long responses
  3. Error Handling - Implement retry logic for failed requests
  4. Loading States - Show loading indicators during requests
  5. TypeScript - Use TypeScript for better development experience
  6. React State Management - Use state management for complex applications

Next Steps