// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. $(function() { const $messagesContainer = $('#messages-container'); const $userInput = $('#user-input'); const $sendBtn = $('#send-btn'); let currentSessionId = null; /** * Updates the active agent profile information panel in the sidebar * based on the currently selected remote agent and user ID configurations. */ const updateAgentInfoPane = () => { const projectId = $('#project-id').val(); const location = $('#location').val(); const agentId = $('#agent-id').val() || $('#agent-select').val(); const userId = $('#user-id').val() || 'default_user_id'; $('#info-agent-mode').text('Remote Vertex AI'); $('#info-project-id').text(projectId || '-'); $('#info-location').text(location || '-'); $('#info-agent-id').text(agentId || '-'); $('#info-session-id').text(currentSessionId || 'No active session'); $('#info-user-id').text(userId || 'default_user_id'); }; /** * Resets the message history container to display the initial greeting * and instructions for the user. */ const resetChatFeed = () => { $messagesContainer.html(`
`); }; /** * Asynchronously fetches the list of available remote agents from the backend * API and populates the remote agent selection dropdown. */ function loadRemoteAgents(showAlert = false) { const projectId = $('#project-id').val().trim(); const location = $('#location').val().trim(); updateAgentInfoPane(); if (!projectId || !location) { if (showAlert) alert('Please configure both Project ID and Location first.'); return; } const $loadAgentsBtn = $('#load-agents-btn'); const $agentSelect = $('#agent-select'); $loadAgentsBtn.prop('disabled', true).html('sync Loading...'); $.getJSON('/list_agents', { project_id: projectId, location: location }) .done(data => { if (data.error) { if (showAlert) alert(`GCP Error: ${data.error}`); console.error(`Remote agent fetch error: ${data.error}`); } else if (data.agents) { $agentSelect.html('')
.addClass('error-traceback')
.text(data.traceback);
$contentDiv.append($pre);
}
$agentMessageDiv.addClass('error-message');
} else if (data.content && data.content.parts) {
data.content.parts.forEach(part => {
if (part.text) {
$contentDiv.append(
$('').html(formatAgentText(part.text)));
}
});
} else if (data.text) {
$contentDiv.append($('').html(formatAgentText(data.text)));
} else if (typeof data === 'string') {
$contentDiv.append($('').html(formatAgentText(data)));
}
$messagesContainer.scrollTop(
$messagesContainer.prop('scrollHeight'));
} catch (err) {
console.error('Error parsing JSON event chunk:', dataStr, err);
}
}
}
}
} catch (error) {
console.error('Error during query stream processing:', error);
if (isFirstEvent) {
$contentDiv.empty();
}
$contentDiv.append(
$('')
.addClass('error-header')
.text(`Network / connection error: ${error.message}`));
$agentMessageDiv.addClass('error-message');
$messagesContainer.scrollTop($messagesContainer.prop('scrollHeight'));
}
}
/**
* Helper utility to create and append a new message container element (user,
* agent, or system) to the chat history DOM, automatically scrolling the view
* to the latest message.
*
* @param {string} text - The HTML or plaintext content of the message.
* @param {string} type - The CSS class defining the message type (e.g.,
* 'user-message', 'agent-message').
* @returns {!jQuery} The jQuery wrapper representing the newly created message
* element.
*/
function appendMessage(text, type) {
const $messageDiv = $('').addClass(`message ${type}`);
const $contentDiv = $('')
.addClass('message-content')
.html(text ? text.replace(/\n/g, '
') : '');
$messageDiv.append($contentDiv);
$messagesContainer.append($messageDiv);
$messagesContainer.scrollTop($messagesContainer.prop('scrollHeight'));
return $messageDiv;
}
});