jQuery(document).ready(function($) { var conciergeDialog = $('#zaa-concierge-dialog'); var chatArea = conciergeDialog.find('.zaa-chat-area'); var inputText = conciergeDialog.find('.zaa-input-text'); var sendButton = conciergeDialog.find('.zaa-send-btn'); var weatherButton = $('#zaa-weather-button'); // var wifiButton = $('#zaa-wifi-button'); // Already defined in previous versions const MAX_HISTORY_MESSAGES = 10; // Store last 10 messages (user + bot) let zaaConversationHistory = []; let zaaSessionId = ''; // --- Initialize Session and Load History --- function zaa_initializeSession() { // Generate a simple session ID if one doesn't exist for this browser session zaaSessionId = sessionStorage.getItem('zaaConciergeSessionId'); if (!zaaSessionId) { zaaSessionId = 'zaa-' + Date.now() + '-' + Math.random().toString(36).substring(2, 10); sessionStorage.setItem('zaaConciergeSessionId', zaaSessionId); } // Load history from sessionStorage const storedHistory = sessionStorage.getItem('zaaConversationHistory_' + zaaSessionId); if (storedHistory) { try { zaaConversationHistory = JSON.parse(storedHistory); // Re-render history (optional, if you want to show it on widget load) // zaaConversationHistory.forEach(msg => { // if (msg.role === 'user') zaa_addUserMessage(msg.parts[0].text, false); // false = don't add to history again // else if (msg.role === 'model') zaa_addBotMessage(msg.parts[0].text, false, false); // false = not thinking, false = don't add // }); } catch (e) { console.error("Error parsing stored conversation history:", e); zaaConversationHistory = []; sessionStorage.removeItem('zaaConversationHistory_' + zaaSessionId); // Clear corrupted data } } } // --- Save History to Session Storage --- function zaa_saveHistory() { // Keep only the last MAX_HISTORY_MESSAGES if (zaaConversationHistory.length > MAX_HISTORY_MESSAGES) { zaaConversationHistory = zaaConversationHistory.slice(-MAX_HISTORY_MESSAGES); } try { sessionStorage.setItem('zaaConversationHistory_' + zaaSessionId, JSON.stringify(zaaConversationHistory)); } catch (e) { console.error("Error saving conversation history to sessionStorage:", e); // Could be due to storage limit, but unlikely for 10 messages. } } // --- Helper function to add a bot message --- // Modified to optionally add to history function zaa_addBotMessage(content, isThinking = false, addToHistory = true) { var botName = conciergeDialog.find('.zaa-message-bot .zaa-bot-name').first().text() || 'Airstay.app'; var avatarUrl = conciergeDialog.find('.zaa-message-bot .zaa-avatar').first().attr('src'); var messageClass = isThinking ? 'zaa-message-thinking' : ''; chatArea.find('.zaa-message-thinking').remove(); var botMessageHtml = '
' + 'Avatar' + '
' + '' + botName + '' + '

' + content + '

' + '
' + '
'; chatArea.append(botMessageHtml); chatArea.scrollTop(chatArea[0].scrollHeight); if (addToHistory && !isThinking) { zaaConversationHistory.push({ role: "model", parts: [{ text: content.replace(//gi, '\n') }] }); // Store with newlines zaa_saveHistory(); } } // --- Helper function to add a user message --- // Modified to optionally add to history function zaa_addUserMessage(text, addToHistory = true) { var sanitizedText = $('
').text(text).html(); var userMessageHtml = '
' + '

' + sanitizedText + '

' + '
'; chatArea.append(userMessageHtml); chatArea.scrollTop(chatArea[0].scrollHeight); if (addToHistory) { zaaConversationHistory.push({ role: "user", parts: [{ text: text }] }); zaa_saveHistory(); } } // --- Function to call Gemini API (now sends history) --- function zaa_callGeminiApi(isWeatherCall = false, weatherPromptText = '', originalButton = null) { if (!zaaConciergeData.gemini_api_ready) { var errorKeyMsg = zaaConciergeData.error_gemini_key; if (!zaaConciergeData.latitude || !zaaConciergeData.longitude) { errorKeyMsg = zaaConciergeData.error_no_coords; } zaa_addBotMessage(errorKeyMsg, false, false); // Don't add error to history if (originalButton) originalButton.prop('disabled', false); sendButton.prop('disabled', zaaConciergeData.gemini_api_ready ? false : true); return; } if (originalButton) originalButton.prop('disabled', true); sendButton.prop('disabled', true); zaa_addBotMessage(zaaConciergeData.thinking, true, false); // Thinking message not part of history let payloadContents; let ajaxData = { action: 'zaa_call_gemini', nonce: zaaConciergeData.nonce, }; if (isWeatherCall && weatherPromptText) { // For weather, send only the specific prompt, not full history // The PHP side will wrap this single prompt into a 'contents' array ajaxData.prompt = weatherPromptText; } else { // For regular chat, send the current conversation history // Ensure history is not empty if (zaaConversationHistory.length === 0) { zaa_addBotMessage("Hmm, the conversation is empty. What would you like to ask?", false, false); if (originalButton) originalButton.prop('disabled', false); sendButton.prop('disabled', false); chatArea.find('.zaa-message-thinking').remove(); return; } // Slice to ensure we don't exceed reasonable limits for the API or our history cap payloadContents = zaaConversationHistory.slice(-MAX_HISTORY_MESSAGES); ajaxData.contents = JSON.stringify(payloadContents); } $.ajax({ url: zaaConciergeData.ajax_url, type: 'POST', data: ajaxData, success: function(response) { chatArea.find('.zaa-message-thinking').remove(); if (response.success && response.data.text) { let formattedText = response.data.text.replace(/\n/g, '
'); // Add bot response to UI and history zaa_addBotMessage(formattedText, false, true); // True to add to history } else { var errorMessage = response.data && response.data.message ? response.data.message : zaaConciergeData.error_gemini_api; zaa_addBotMessage('⚠️ Error: ' + $('
').text(errorMessage).html(), false, false); // Don't add error to history } }, error: function(xhr, status, error) { chatArea.find('.zaa-message-thinking').remove(); var detailedError = xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : error; zaa_addBotMessage('⚠️ AJAX Error: ' + $('
').text(detailedError).html(), false, false); // Don't add error to history }, complete: function() { if (originalButton) originalButton.prop('disabled', false); // Only re-enable if it was meant to be enabled sendButton.prop('disabled', zaaConciergeData.gemini_api_ready ? false : true); } }); } // --- Weather Forecast Button --- if (weatherButton.length) { weatherButton.on('click', function() { if (!zaaConciergeData.latitude || !zaaConciergeData.longitude) { zaa_addBotMessage(zaaConciergeData.error_no_coords, false, false); return; } if (!zaaConciergeData.gemini_api_ready) { zaa_addBotMessage(zaaConciergeData.error_gemini_key, false, false); return; } var weatherUserQuery = "Show me the weather forecast."; var weatherPrompt = "based on the coordinates (latitude: " + zaaConciergeData.latitude + ", longitude: " + zaaConciergeData.longitude + ") give me a 5 day weather forecast with min/max temperatures, very short description, and a tiny weather icon for each day. Do not add any comment nor introduction. Present each day clearly."; zaa_addUserMessage(weatherUserQuery, true); // User's "action" IS part of history // The weather call itself uses a specific prompt, not the whole history for the request. // The bot's *response* will be added to history by zaa_addBotMessage. zaa_callGeminiApi(true, weatherPrompt, $(this)); }); } // --- Send Button for Input Text & Enter Key --- function handleUserQuery() { var userQuestion = inputText.val().trim(); if (userQuestion === '') return; if (!zaaConciergeData.gemini_api_ready) { // ... (error handling as before) ... var errorKeyMsg = zaaConciergeData.error_gemini_key; if (!zaaConciergeData.latitude || !zaaConciergeData.longitude) { errorKeyMsg = zaaConciergeData.error_no_coords; } zaa_addBotMessage(errorKeyMsg, false, false); inputText.val(''); return; } zaa_addUserMessage(userQuestion, true); // Add user message to UI and history inputText.val(''); // No need to construct prompt here, zaa_callGeminiApi will use zaaConversationHistory // The coordinate context is now implicitly part of the ongoing conversation if the bot is prompted for it // or if you choose to prepend it to every user message before adding to history. // For now, we rely on the bot understanding from previous turns if location is mentioned. // If you need to *always* inject coords, you'd modify the object pushed to zaaConversationHistory in zaa_addUserMessage. // Example for always injecting coords: // zaaConversationHistory.push({ // role: "user", // parts: [{ text: "My location is lat " + zaaConciergeData.latitude + ", lon " + zaaConciergeData.longitude + ". Question: " + userQuestion }] // }); // For now, keeping it simple: zaa_callGeminiApi(false, '', sendButton); } if (sendButton.length) { sendButton.on('click', handleUserQuery); } if (inputText.length) { inputText.on('keypress', function(e) { if (e.which === 13 && !sendButton.prop('disabled')) { e.preventDefault(); handleUserQuery(); } }); } // --- Initialize Session on Load --- zaa_initializeSession(); // --- WiFi Button Functionality (from previous version, ensure it's still there) --- // ... (keep existing WiFi button code) ... // --- Top Bar Controls (from previous version, ensure it's still there) --- // ... (keep existing top bar controls code) ... });