- Introduce Rooms in chat-sessions, as different clients received the same messages.

This commit is contained in:
Josako
2024-08-19 07:22:06 +02:00
parent 688f2300b9
commit 733f115e92
9 changed files with 175 additions and 42 deletions

View File

@@ -47,7 +47,7 @@
<div class="col-12"> <div class="col-12">
<nav class="navbar navbar-expand-lg navbar-light bg-white z-index-3 py-3"> <nav class="navbar navbar-expand-lg navbar-light bg-white z-index-3 py-3">
<div class="container-fluid px-0"> <div class="container-fluid px-0">
<a class="navbar-brand font-weight-bolder ms-sm-3 d-none d-md-block" href=" https://www.flow-it.net " rel="tooltip" title="Realised by Josako & Kobe" data-placement="bottom" target="_blank"> <a class="navbar-brand font-weight-bolder ms-sm-3 d-none d-md-block" href=" https://www.askeveai.com " rel="tooltip" title="Realised by Josako & Kobe" data-placement="bottom" target="_blank">
EveAI EveAI
</a> </a>
<a class="navbar-brand font-weight-bolder ms-sm-3 d-block d-md-none" href=" https://www.flow-it.net " rel="tooltip" title="Realised by Josako & Kobe" data-placement="bottom" target="_blank"> <a class="navbar-brand font-weight-bolder ms-sm-3 d-block d-md-none" href=" https://www.flow-it.net " rel="tooltip" title="Realised by Josako & Kobe" data-placement="bottom" target="_blank">

View File

@@ -1,7 +1,7 @@
import uuid import uuid
from flask_jwt_extended import create_access_token, get_jwt_identity, verify_jwt_in_request, decode_token from flask_jwt_extended import create_access_token, get_jwt_identity, verify_jwt_in_request, decode_token
from flask_socketio import emit, disconnect from flask_socketio import emit, disconnect, join_room, leave_room
from flask import current_app, request, session from flask import current_app, request, session
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from datetime import datetime, timedelta from datetime import datetime, timedelta
@@ -32,17 +32,23 @@ def handle_connect():
token = create_access_token(identity={"tenant_id": tenant_id, "api_key": api_key}) token = create_access_token(identity={"tenant_id": tenant_id, "api_key": api_key})
current_app.logger.debug(f'SocketIO: Connection handling created token: {token} for tenant {tenant_id}') current_app.logger.debug(f'SocketIO: Connection handling created token: {token} for tenant {tenant_id}')
# Create a unique room for this client
room = f"{tenant_id}_{request.sid}"
join_room(room)
current_app.logger.debug(f'SocketIO: Client joined room: {room}')
# Create a unique session ID # Create a unique session ID
if 'session_id' not in session: if 'session_id' not in session:
session['session_id'] = str(uuid.uuid4()) session['session_id'] = str(uuid.uuid4())
session['last_activity'] = datetime.now() session['last_activity'] = datetime.now()
session['room'] = room
# Communicate connection to client # Communicate connection to client
current_app.logger.debug(f'SocketIO: Connection handling sending status to client for tenant {tenant_id}') current_app.logger.debug(f'SocketIO: Connection handling sending status to client for tenant {tenant_id}')
emit('connect', {'status': 'Connected', 'tenant_id': tenant_id}) emit('connect', {'status': 'Connected', 'tenant_id': tenant_id, 'room': room})
current_app.logger.debug(f'SocketIO: Connection handling sending authentication token to client') current_app.logger.debug(f'SocketIO: Connection handling sending authentication token to client')
emit('authenticated', {'token': token}) # Emit custom event with the token emit('authenticated', {'token': token, 'room': room}) # Emit custom event with the token
current_app.logger.debug(f'SocketIO: Connection handling sent token to client for tenant {tenant_id}') current_app.logger.debug(f'SocketIO: Connection handling sent token to client for tenant {tenant_id}')
except Exception as e: except Exception as e:
current_app.logger.error(f'SocketIO: Connection failed: {e}') current_app.logger.error(f'SocketIO: Connection failed: {e}')
@@ -53,6 +59,10 @@ def handle_connect():
@socketio.on('disconnect') @socketio.on('disconnect')
def handle_disconnect(): def handle_disconnect():
room = session.get('room')
if room:
leave_room(room)
current_app.logger.debug(f'SocketIO: Client left room: {room}')
current_app.logger.debug('SocketIO: Client disconnected') current_app.logger.debug('SocketIO: Client disconnected')
@@ -73,6 +83,7 @@ def handle_message(data):
session['last_activity'] = datetime.now() session['last_activity'] = datetime.now()
current_tenant_id = validate_incoming_data(data) current_tenant_id = validate_incoming_data(data)
room = session.get('room')
# Offload actual processing of question # Offload actual processing of question
task = current_celery.send_task('ask_question', queue='llm_interactions', args=[ task = current_celery.send_task('ask_question', queue='llm_interactions', args=[
@@ -80,7 +91,8 @@ def handle_message(data):
data['message'], data['message'],
data['language'], data['language'],
session['session_id'], session['session_id'],
data['timezone'] data['timezone'],
room
]) ])
current_app.logger.debug(f'SocketIO: Message offloading for tenant {current_tenant_id}, ' current_app.logger.debug(f'SocketIO: Message offloading for tenant {current_tenant_id}, '
f'Question: {task.id}') f'Question: {task.id}')
@@ -90,7 +102,7 @@ def handle_message(data):
'taskId': task.id, 'taskId': task.id,
} }
current_app.logger.debug(f"SocketIO: Message handling sent bot response: {response}") current_app.logger.debug(f"SocketIO: Message handling sent bot response: {response}")
emit('bot_response', response, broadcast=True) emit('bot_response', response, room=room)
except Exception as e: except Exception as e:
current_app.logger.error(f'SocketIO: Message handling failed: {e}') current_app.logger.error(f'SocketIO: Message handling failed: {e}')
disconnect() disconnect()
@@ -99,15 +111,16 @@ def handle_message(data):
@socketio.on('check_task_status') @socketio.on('check_task_status')
def check_task_status(data): def check_task_status(data):
task_id = data.get('task_id') task_id = data.get('task_id')
room = session.get('room')
current_app.logger.debug(f'SocketIO: Check task status for task_id: {task_id}') current_app.logger.debug(f'SocketIO: Check task status for task_id: {task_id}')
if not task_id: if not task_id:
emit('task_status', {'status': 'error', 'message': 'Missing task ID'}) emit('task_status', {'status': 'error', 'message': 'Missing task ID'}, room=room)
return return
task_result = current_celery.AsyncResult(task_id) task_result = current_celery.AsyncResult(task_id)
if task_result.state == 'PENDING': if task_result.state == 'PENDING':
current_app.logger.debug(f'SocketIO: Task {task_id} is pending') current_app.logger.debug(f'SocketIO: Task {task_id} is pending')
emit('task_status', {'status': 'pending', 'taskId': task_id}) emit('task_status', {'status': 'pending', 'taskId': task_id}, room=room)
elif task_result.state == 'SUCCESS': elif task_result.state == 'SUCCESS':
current_app.logger.debug(f'SocketIO: Task {task_id} has finished. Status: {task_result.state}, ' current_app.logger.debug(f'SocketIO: Task {task_id} has finished. Status: {task_result.state}, '
f'Result: {task_result.result}') f'Result: {task_result.result}')
@@ -120,10 +133,10 @@ def check_task_status(data):
'algorithm': result['algorithm'], 'algorithm': result['algorithm'],
'interaction_id': result['interaction_id'], 'interaction_id': result['interaction_id'],
} }
emit('task_status', response) emit('task_status', response, room=room)
else: else:
current_app.logger.error(f'SocketIO: Task {task_id} has failed. Error: {task_result.info}') current_app.logger.error(f'SocketIO: Task {task_id} has failed. Error: {task_result.info}')
emit('task_status', {'status': task_result.state, 'message': str(task_result.info)}) emit('task_status', {'status': task_result.state, 'message': str(task_result.info)}, room=room)
@socketio.on('feedback') @socketio.on('feedback')

View File

@@ -47,7 +47,7 @@ def detail_question(question, language, model_variables, session_id):
@current_celery.task(name='ask_question', queue='llm_interactions') @current_celery.task(name='ask_question', queue='llm_interactions')
def ask_question(tenant_id, question, language, session_id, user_timezone): def ask_question(tenant_id, question, language, session_id, user_timezone, room):
"""returns result structured as follows: """returns result structured as follows:
result = { result = {
'answer': 'Your answer here', 'answer': 'Your answer here',
@@ -90,12 +90,14 @@ def ask_question(tenant_id, question, language, session_id, user_timezone):
result, interaction = answer_using_tenant_rag(question, language, tenant, chat_session) result, interaction = answer_using_tenant_rag(question, language, tenant, chat_session)
result['algorithm'] = current_app.config['INTERACTION_ALGORITHMS']['RAG_TENANT']['name'] result['algorithm'] = current_app.config['INTERACTION_ALGORITHMS']['RAG_TENANT']['name']
result['interaction_id'] = interaction.id result['interaction_id'] = interaction.id
result['room'] = room # Include the room in the result
if result['insufficient_info']: if result['insufficient_info']:
if 'LLM' in tenant.fallback_algorithms: if 'LLM' in tenant.fallback_algorithms:
result, interaction = answer_using_llm(question, language, tenant, chat_session) result, interaction = answer_using_llm(question, language, tenant, chat_session)
result['algorithm'] = current_app.config['INTERACTION_ALGORITHMS']['LLM']['name'] result['algorithm'] = current_app.config['INTERACTION_ALGORITHMS']['LLM']['name']
result['interaction_id'] = interaction.id result['interaction_id'] = interaction.id
result['room'] = room # Include the room in the result
return result return result
except Exception as e: except Exception as e:

View File

@@ -3,7 +3,7 @@
Plugin Name: EveAI Chat Widget Plugin Name: EveAI Chat Widget
Plugin URI: https://askeveai.com/ Plugin URI: https://askeveai.com/
Description: Integrates the EveAI chat interface into your WordPress site. Description: Integrates the EveAI chat interface into your WordPress site.
Version: 1.3.20 Version: 1.3.21
Author: Josako, Pieter Laroy Author: Josako, Pieter Laroy
Author URI: https://askeveai.com/about/ Author URI: https://askeveai.com/about/
*/ */

View File

@@ -13,6 +13,7 @@ class EveAIChatWidget extends HTMLElement {
this.idleTime = 0; // in milliseconds this.idleTime = 0; // in milliseconds
this.maxConnectionIdleTime = 1 * 60 * 60 * 1000; // 1 hours in milliseconds this.maxConnectionIdleTime = 1 * 60 * 60 * 1000; // 1 hours in milliseconds
this.languages = [] this.languages = []
this.room = null;
console.log('EveAIChatWidget constructor called'); console.log('EveAIChatWidget constructor called');
} }
@@ -163,6 +164,10 @@ class EveAIChatWidget extends HTMLElement {
this.setStatusMessage('Connected to EveAI.'); this.setStatusMessage('Connected to EveAI.');
this.updateConnectionStatus(true); this.updateConnectionStatus(true);
this.startHeartbeat(); this.startHeartbeat();
if (data.room) {
this.room = data.room;
console.log(`Joined room: ${this.room}`);
}
}); });
this.socket.on('authenticated', (data) => { this.socket.on('authenticated', (data) => {
@@ -171,6 +176,10 @@ class EveAIChatWidget extends HTMLElement {
if (data.token) { if (data.token) {
this.jwtToken = data.token; // Store the JWT token received from the server this.jwtToken = data.token; // Store the JWT token received from the server
} }
if (data.room) {
this.room = data.room;
console.log(`Confirmed room: ${this.room}`);
}
}); });
this.socket.on('connect_error', (err) => { this.socket.on('connect_error', (err) => {

View File

@@ -19,7 +19,8 @@
'4', '4',
'EveAI-CHAT-9628-4110-5263-6256-7601', 'EveAI-CHAT-9628-4110-5263-6256-7601',
'http://macstudio.ask-eve-ai-local.com', 'http://macstudio.ask-eve-ai-local.com',
'en' 'en',
'en,fr,nl'
); );
eveAI.initializeChat('chat-container'); eveAI.initializeChat('chat-container');
}); });

View File

@@ -13,7 +13,7 @@
--algorithm-color-llm: #800080; /* Purple for RAG_LLM */ --algorithm-color-llm: #800080; /* Purple for RAG_LLM */
/*--font-family: 'Arial, sans-serif'; !* Default font family *!*/ /*--font-family: 'Arial, sans-serif'; !* Default font family *!*/
--font-family: 'ui-sans-serif, -apple-system, system-ui, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica, Apple Color Emoji, Arial, Segoe UI Emoji, Segoe UI Symbol'; --font-family: 'Segoe UI, Roboto, Cantarell, Noto Sans, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol';
--font-color: #e9e9e9; /* Default font color */ --font-color: #e9e9e9; /* Default font color */
--user-message-font-color: #e9e9e9; /* User message font color */ --user-message-font-color: #e9e9e9; /* User message font color */
--bot-message-font-color: #e9e9e9; /* Bot message font color */ --bot-message-font-color: #e9e9e9; /* Bot message font color */
@@ -91,7 +91,7 @@
.chat-container { .chat-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 99vh; height: 75vh;
/*max-height: 100vh;*/ /*max-height: 100vh;*/
max-width: 600px; max-width: 600px;
margin: auto; margin: auto;
@@ -103,6 +103,13 @@
color: var(--font-color); /* Apply the default font color */ color: var(--font-color); /* Apply the default font color */
} }
.disclaimer {
font-size: 0.7em;
text-align: right;
padding: 5px 20px 5px 5px;
margin-bottom: 5px;
}
.messages-area { .messages-area {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
@@ -115,6 +122,7 @@
margin-bottom: 10px; margin-bottom: 10px;
padding: 10px; padding: 10px;
border-radius: 15px; border-radius: 15px;
font-size: 1rem;
} }
.message.user { .message.user {
@@ -150,21 +158,50 @@
} }
.question-area { .question-area {
padding: 10px;
display: flex; display: flex;
flex-direction: row;
align-items: center; align-items: center;
background-color: var(--user-message-bg); background-color: var(--user-message-bg);
padding: 10px;
} }
.question-area input { .language-select-container {
width: 100%;
margin-bottom: 10px; /* Spacing between the dropdown and the textarea */
}
.language-select {
width: 100%;
margin-bottom: 5px; /* Space between the dropdown and the send button */
padding: 8px;
border-radius: 5px;
border: 1px solid var(--input-border);
background-color: var(--input-bg);
color: var(--input-text-color);
font-size: 1rem;
}
.question-area textarea {
flex: 1; flex: 1;
border: none; border: none;
padding: 10px; padding: 10px;
border-radius: 15px; border-radius: 15px;
margin-right: 10px; background-color: var(--input-bg);
background-color: var(--input-bg); /* Apply input background color */ border: 1px solid var(--input-border);
border: 1px solid var(--input-border); /* Apply input border color */ color: var(--input-text-color);
color: var(--input-text-color); /* Apply input text color */ font-family: var(--font-family); /* Apply the default font family */
font-size: 1rem;
resize: vertical;
min-height: 60px;
max-height: 150px;
overflow-y: auto;
margin-right: 10px; /* Space between textarea and right-side container */
}
.right-side {
display: flex;
flex-direction: column;
align-items: center;
} }
.question-area button { .question-area button {
@@ -176,8 +213,9 @@
/* Styles for the send icon */ /* Styles for the send icon */
.send-icon { .send-icon {
font-size: 24px; /* Size of the icon */ font-size: 24px;
color: var(--button-color); /* Color of the icon */ color: var(--button-color);
cursor: pointer;
} }
.send-icon.disabled { .send-icon.disabled {

View File

@@ -1,6 +1,6 @@
class EveAIChatWidget extends HTMLElement { class EveAIChatWidget extends HTMLElement {
static get observedAttributes() { static get observedAttributes() {
return ['tenant-id', 'api-key', 'domain', 'language']; return ['tenant-id', 'api-key', 'domain', 'language', 'languages'];
} }
constructor() { constructor() {
@@ -12,6 +12,8 @@ class EveAIChatWidget extends HTMLElement {
this.heartbeatInterval = null; this.heartbeatInterval = null;
this.idleTime = 0; // in milliseconds this.idleTime = 0; // in milliseconds
this.maxConnectionIdleTime = 1 * 60 * 60 * 1000; // 1 hours in milliseconds this.maxConnectionIdleTime = 1 * 60 * 60 * 1000; // 1 hours in milliseconds
this.languages = []
this.room = null;
console.log('EveAIChatWidget constructor called'); console.log('EveAIChatWidget constructor called');
} }
@@ -19,15 +21,17 @@ class EveAIChatWidget extends HTMLElement {
console.log('connectedCallback called'); console.log('connectedCallback called');
this.innerHTML = this.getTemplate(); this.innerHTML = this.getTemplate();
this.messagesArea = this.querySelector('.messages-area'); this.messagesArea = this.querySelector('.messages-area');
this.questionInput = this.querySelector('.question-area input'); this.questionInput = this.querySelector('.question-area textarea');
this.sendButton = this.querySelector('.send-icon'); this.sendButton = this.querySelector('.send-icon');
this.languageSelect = this.querySelector('.language-select');
this.statusLine = this.querySelector('.status-line'); this.statusLine = this.querySelector('.status-line');
this.statusMessage = this.querySelector('.status-message'); this.statusMessage = this.querySelector('.status-message');
this.connectionStatusIcon = this.querySelector('.connection-status-icon'); this.connectionStatusIcon = this.querySelector('.connection-status-icon');
this.sendButton.addEventListener('click', () => this.handleSendMessage()); this.sendButton.addEventListener('click', () => this.handleSendMessage());
this.questionInput.addEventListener('keydown', (event) => { this.questionInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter') { if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault(); // Prevent adding a new line
this.handleSendMessage(); this.handleSendMessage();
} }
}); });
@@ -38,6 +42,30 @@ class EveAIChatWidget extends HTMLElement {
} }
} }
populateLanguageDropdown() {
// Clear existing options
this.languageSelect.innerHTML = '';
console.log(`languages for options: ${this.languages}`)
// Populate with new options
this.languages.forEach(lang => {
const option = document.createElement('option');
option.value = lang;
option.textContent = lang.toUpperCase();
if (lang === this.currentLanguage) {
option.selected = true;
}
console.log(`Adding option for language: ${lang}`)
this.languageSelect.appendChild(option);
});
// Add event listener for language change
this.languageSelect.addEventListener('change', (e) => {
this.currentLanguage = e.target.value;
// You might want to emit an event or update the backend about the language change
});
}
attributeChangedCallback(name, oldValue, newValue) { attributeChangedCallback(name, oldValue, newValue) {
console.log(`attributeChangedCallback called: ${name} changed from ${oldValue} to ${newValue}`); console.log(`attributeChangedCallback called: ${name} changed from ${oldValue} to ${newValue}`);
this.updateAttributes(); this.updateAttributes();
@@ -45,6 +73,9 @@ class EveAIChatWidget extends HTMLElement {
if (this.areAllAttributesSet() && !this.socket) { if (this.areAllAttributesSet() && !this.socket) {
console.log('All attributes set in attributeChangedCallback, initializing socket'); console.log('All attributes set in attributeChangedCallback, initializing socket');
this.attributesSet = true; this.attributesSet = true;
console.log('All attributes are set, populating language dropdown');
this.populateLanguageDropdown();
console.log('All attributes are set, initializing socket')
this.initializeSocket(); this.initializeSocket();
} }
} }
@@ -54,11 +85,16 @@ class EveAIChatWidget extends HTMLElement {
this.apiKey = this.getAttribute('api-key'); this.apiKey = this.getAttribute('api-key');
this.domain = this.getAttribute('domain'); this.domain = this.getAttribute('domain');
this.language = this.getAttribute('language'); this.language = this.getAttribute('language');
const languageAttr = this.getAttribute('languages');
this.languages = languageAttr ? languageAttr.split(',') : [];
this.currentLanguage = this.language;
console.log('Updated attributes:', { console.log('Updated attributes:', {
tenantId: this.tenantId, tenantId: this.tenantId,
apiKey: this.apiKey, apiKey: this.apiKey,
domain: this.domain, domain: this.domain,
language: this.language language: this.language,
currentLanguage: this.currentLanguage,
languages: this.languages
}); });
} }
@@ -67,13 +103,34 @@ class EveAIChatWidget extends HTMLElement {
const apiKey = this.getAttribute('api-key'); const apiKey = this.getAttribute('api-key');
const domain = this.getAttribute('domain'); const domain = this.getAttribute('domain');
const language = this.getAttribute('language'); const language = this.getAttribute('language');
const languages = this.getAttribute('languages');
console.log('Checking if all attributes are set:', { console.log('Checking if all attributes are set:', {
tenantId, tenantId,
apiKey, apiKey,
domain, domain,
language language,
languages
}); });
return tenantId && apiKey && domain && language; return tenantId && apiKey && domain && language && languages;
}
createLanguageDropdown() {
const select = document.createElement('select');
select.id = 'languageSelect';
this.languages.forEach(lang => {
const option = document.createElement('option');
option.value = lang;
option.textContent = lang.toUpperCase();
if (lang === this.currentLanguage) {
option.selected = true;
}
select.appendChild(option);
});
select.addEventListener('change', (e) => {
this.currentLanguage = e.target.value;
// You might want to emit an event or update the backend about the language change
});
return select;
} }
initializeSocket() { initializeSocket() {
@@ -81,15 +138,11 @@ class EveAIChatWidget extends HTMLElement {
console.log('Socket already initialized'); console.log('Socket already initialized');
return; return;
} }
if (!this.domain || this.domain === 'null') {
console.error('Domain attribute is missing or invalid'); console.log(`Initializing socket connection to Evie`);
this.setStatusMessage('EveAI Chat Widget needs further configuration by site administrator.');
return;
}
console.log(`Initializing socket connection to ${this.domain}`);
// Ensure apiKey is passed in the query parameters // Ensure apiKey is passed in the query parameters
this.socket = io(this.domain, { this.socket = io('https://evie.askeveai.com', {
path: '/chat/socket.io/', path: '/chat/socket.io/',
transports: ['websocket', 'polling'], transports: ['websocket', 'polling'],
query: { query: {
@@ -104,13 +157,17 @@ class EveAIChatWidget extends HTMLElement {
timeout: 20000 // Connection timeout timeout: 20000 // Connection timeout
}); });
console.log(`Finished initializing socket connection to ${this.domain}`); console.log(`Finished initializing socket connection to Evie`);
this.socket.on('connect', (data) => { this.socket.on('connect', (data) => {
console.log('Socket connected OK'); console.log('Socket connected OK');
this.setStatusMessage('Connected to EveAI.'); this.setStatusMessage('Connected to EveAI.');
this.updateConnectionStatus(true); this.updateConnectionStatus(true);
this.startHeartbeat(); this.startHeartbeat();
if (data.room) {
this.room = data.room;
console.log(`Joined room: ${this.room}`);
}
}); });
this.socket.on('authenticated', (data) => { this.socket.on('authenticated', (data) => {
@@ -119,6 +176,10 @@ class EveAIChatWidget extends HTMLElement {
if (data.token) { if (data.token) {
this.jwtToken = data.token; // Store the JWT token received from the server this.jwtToken = data.token; // Store the JWT token received from the server
} }
if (data.room) {
this.room = data.room;
console.log(`Confirmed room: ${this.room}`);
}
}); });
this.socket.on('connect_error', (err) => { this.socket.on('connect_error', (err) => {
@@ -243,9 +304,13 @@ class EveAIChatWidget extends HTMLElement {
return ` return `
<div class="chat-container"> <div class="chat-container">
<div class="messages-area"></div> <div class="messages-area"></div>
<div class="disclaimer">Evie can make mistakes. Please double-check responses.</div>
<div class="question-area"> <div class="question-area">
<input type="text" placeholder="Type your message here..." /> <textarea placeholder="Type your message here..." rows="3"></textarea>
<i class="material-icons send-icon outlined">send</i> <div class="right-side">
<select class="language-select"></select>
<i class="material-icons send-icon outlined">send</i>
</div>
</div> </div>
<div class="status-line"> <div class="status-line">
<i class="material-icons connection-status-icon">link_off</i> <i class="material-icons connection-status-icon">link_off</i>
@@ -370,12 +435,15 @@ toggleFeedback(thumbsUp, thumbsDown, feedback, interactionId) {
console.error('JWT token is not available'); console.error('JWT token is not available');
return; return;
} }
const selectedLanguage = this.languageSelect.value;
console.log('Sending message to backend'); console.log('Sending message to backend');
this.socket.emit('user_message', { this.socket.emit('user_message', {
tenantId: this.tenantId, tenantId: this.tenantId,
token: this.jwtToken, token: this.jwtToken,
message, message,
language: this.language, language: selectedLanguage,
timezone: this.userTimezone timezone: this.userTimezone
}); });
this.setStatusMessage('Processing started ...') this.setStatusMessage('Processing started ...')

View File

@@ -1,12 +1,13 @@
// static/js/eveai-sdk.js // static/js/eveai-sdk.js
class EveAI { class EveAI {
constructor(tenantId, apiKey, domain, language) { constructor(tenantId, apiKey, domain, language, languages) {
this.tenantId = tenantId; this.tenantId = tenantId;
this.apiKey = apiKey; this.apiKey = apiKey;
this.domain = domain; this.domain = domain;
this.language = language; this.language = language;
this.languages = languages;
console.log('EveAI constructor:', { tenantId, apiKey, domain }); console.log('EveAI constructor:', { tenantId, apiKey, domain, language, languages });
} }
initializeChat(containerId) { initializeChat(containerId) {
@@ -19,6 +20,7 @@ class EveAI {
chatWidget.setAttribute('api-key', this.apiKey); chatWidget.setAttribute('api-key', this.apiKey);
chatWidget.setAttribute('domain', this.domain); chatWidget.setAttribute('domain', this.domain);
chatWidget.setAttribute('language', this.language); chatWidget.setAttribute('language', this.language);
chatWidget.setAttribute('languages', this.languages);
}); });
} else { } else {
console.error('Container not found'); console.error('Container not found');