aa-integration-backend/ui-connector/templates/index.html (469 lines of code) (raw):
<!DOCTYPE HTML>
<!--
Copyright 2025 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.
-->
<html>
<head>
<title>Interactive Demo</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"
integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg=="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js"
integrity="sha512-aMGMvNYu8Ue4G+fHa359jcPb1u+ytAF+P2SCb+PxrjCdO3n3ZTxJ30zuH39rimUggmTwmh2u7wvQsDTHESnmfQ=="
crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function () {
// TODO: Update the URL of your UI Connector Cloud Run Service. Keep it empty for local test/deployment.
let serviceUrl = '';
// Information about current conversation
var versionUrl = '/v2beta1/';
var project_id, location_id, conversation_profile_name, conversation_name, end_user_name, human_agent_name;
var JWT = '';
// An array of joined conversation names
var joined_conversations = [];
// Helper function for printing log
function logPrinter(action, type, msg) {
$('#log').prepend(
$('<div/>').text(action + ' <' + type + '> ' + msg).html() + '<br><br>'
);
}
// Helper function for updating joined conversation names
function updateJoinedConversationNames() {
let content = '';
for (let i = 0; i < joined_conversations.length; i++) {
content += '<br>' + $('<div/>').text(joined_conversations[i]).html();
}
$('#joined_conversations').empty().append(content);
}
// Create a socket for Cloud Pub/Sub Interceptor
function createSocket(jwt, url) {
var socket = io(url, {
transports: ['websocket'],
auth: {
token: jwt
},
});
socket.on('connect', () => {
logPrinter('Listened', 'connect', 'Connected! socket.id: ' + socket.id);
socket.sendBuffer = [];
});
socket.on("disconnect", (reason) => {
logPrinter('Listened', 'disconnect', 'Disconnected! reason: ' + reason);
});
socket.on("connect_error", (err) => {
console.log(`connect_error due to ${err.message}`);
});
socket.on('conversation-lifecycle-event', (msg) => {
logPrinter('Listened', 'conversation-lifecycle-event', JSON.stringify(msg));
});
socket.on('new-message-event', (msg) => {
logPrinter('Listened', 'new-message-event', JSON.stringify(msg));
});
socket.on('human-agent-assistant-event', function (msg) {
logPrinter(
'Listened',
'human-agent-assistant-event',
JSON.stringify(msg)
);
});
socket.on('unauthenticated', function () {
logPrinter('Listened', 'unauthenticated', '');
});
return socket;
}
// Get JWT
var currentSocket;
if (serviceUrl) { // for local dev
fetch(serviceUrl + '/register', {
method: 'POST',
headers: {
'Authorization': '123',
},
})
.then(response => response.json())
.then(data => {
JWT = data.token;
$('#log').prepend(
$('<div/>').text('Received <jwt> ' + JWT).html()
);
// Connect to the Socket.IO server
currentSocket = createSocket(JWT, serviceUrl);
})
.catch((error) => {
console.error('Error:', error);
});
} else { // for service deploy
fetch(serviceUrl + '/register', {
method: 'POST',
headers: {
'Authorization': '123',
},
})
.then(response => response.json())
.then(data => {
JWT = data.token;
$('#log').prepend(
$('<div/>').text('Received <jwt> ' + JWT).html()
);
// Connect to the Socket.IO server
currentSocket = createSocket(JWT, serviceUrl);
})
.catch((error) => {
console.error('Error:', error);
});
}
window.setInterval(function () {
$('#transport').text(currentSocket.io.engine.transport.name);
}, 1000);
$('form#set_conversation_profile').submit(function (event) {
conversation_profile_name = $('#conversation_profile_test_name').val();
$('#conversation_profile_name').text(conversation_profile_name);
project_id = conversation_profile_name.split('/')[1];
location_id = conversation_profile_name.split('/')[3];
$('#gcp_project_id').text(project_id);
$('#gcp_location_id').text(location_id);
return false;
});
$('form#get_conversation_profile').submit(function (event) {
fetch(serviceUrl + versionUrl + conversation_profile_name, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': JWT,
},
})
.then(response => response.json())
.then(data => {
$('#log').prepend(
$('<div/>').text('Received <conversation_profile> ' + JSON.stringify(data)).html() + '<br><br>'
);
})
.catch((error) => {
console.error('Error:', error);
});
return false;
});
$('form#create').submit(function (event) {
fetch(serviceUrl + versionUrl + 'projects/' + project_id + '/locations/' + location_id + '/conversations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': JWT,
},
body: JSON.stringify({ conversation_profile: conversation_profile_name }),
})
.then(response => response.json())
.then(data => {
conversation_name = data.name;
$('#conversation_name').text(conversation_name);
$('#log').prepend(
$('<div/>').text('Received <conversation_name> ' + JSON.stringify(data)).html() + '<br><br>'
);
})
.catch((error) => {
console.error('Error:', error);
});
return false;
});
$('form#set_conversation').submit(function (event) {
conversation_name = $('#input_conversation_name').val();
$('#conversation_name').text(conversation_name);
project_id = conversation_name.split('/')[1];
location_id = conversation_name.split('/')[3];
$('#gcp_project_id').text(project_id);
$('#gcp_location_id').text(location_id);
return false;
});
$('form#join').submit(function (event) {
currentSocket.emit('join-conversation', conversation_name, (ack, result) => {
logPrinter(
'Emitted',
'send_message',
'ACK for joining conversation: ' + ack + ',' + result
)
if (ack) {
joined_conversations.push(conversation_name);
updateJoinedConversationNames();
}
});
return false;
});
$('form#leave').submit(function (event) {
currentSocket.emit('leave-conversation', conversation_name, (ack, result) => {
logPrinter(
'Emitted',
'send_message',
'ACK for leaving conversation: ' + ack + ',' + result
)
if (ack) {
let index = joined_conversations.indexOf(conversation_name);
if (index > -1) {
joined_conversations.splice(index, 1);
updateJoinedConversationNames();
}
}
});
return false;
});
$('form#create_user').submit(function (event) {
fetch(serviceUrl + versionUrl + conversation_name + '/participants', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': JWT,
},
body: JSON.stringify({ role: 'END_USER' }),
})
.then(response => response.json())
.then(data => {
end_user_name = data.name;
$('#end_user_name').text(end_user_name);
$('#log').prepend(
$('<div/>').text('Received <end_user_name> ' + JSON.stringify(data)).html() + '<br><br>'
);
})
.catch((error) => {
console.error('Error:', error);
});
return false;
});
$('form#create_agent').submit(function (event) {
fetch(serviceUrl + versionUrl + conversation_name + '/participants', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': JWT,
},
body: JSON.stringify({ role: 'HUMAN_AGENT' }),
})
.then(response => response.json())
.then(data => {
human_agent_name = data.name;
$('#human_agent_name').text(human_agent_name);
$('#log').prepend(
$('<div/>').text('Received <human_agent_name> ' + JSON.stringify(data)).html() + '<br><br>'
);
})
.catch((error) => {
console.error('Error:', error);
});
return false;
});
$('form#user_send').submit(function (event) {
fetch(serviceUrl + versionUrl + end_user_name + ':analyzeContent', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': JWT,
},
body: JSON.stringify(
{ text_input: { languageCode: 'en-US', text: $('#user_send_message').val() } }),
})
.then(response => response.json())
.then(data => {
$('#log').prepend(
$('<div/>').text('Received <analyzeContent response for user> ' + JSON.stringify(data)).html() + '<br><br>'
);
})
.catch((error) => {
console.error('Error:', error);
});
return false;
});
$('form#agent_send').submit(function (event) {
fetch(serviceUrl + versionUrl + human_agent_name + ':analyzeContent', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': JWT,
},
body: JSON.stringify(
{ text_input: { languageCode: 'en-US', text: $('#agent_send_message').val() } }),
})
.then(response => response.json())
.then(data => {
$('#log').prepend(
$('<div/>').text('Received <analyzeContent response for agent> ' + JSON.stringify(data)).html() + '<br><br>'
);
})
.catch((error) => {
console.error('Error:', error);
});
return false;
});
$('form#search_knowledge').submit(function (event) {
fetch(serviceUrl + versionUrl + conversation_name + '/suggestions:searchKnowledge', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': JWT,
},
body: JSON.stringify(
{
parent: 'projects/' + project_id + '/locations/' + location_id,
query: { languageCode: 'en-US', text: $('#search_knowledge_query').val() },
conversation_profile: conversation_profile_name,
session_id: conversation_name.split('/')[5],
}),
})
.then(response => response.json())
.then(data => {
$('#log').prepend(
$('<div/>').text('Received <searchKnowledge response> ' + JSON.stringify(data)).html() + '<br><br>'
);
})
.catch((error) => {
console.error('Error:', error);
});
return false;
});
$('form#suggest_summary').submit(function (event) {
fetch(serviceUrl + versionUrl + conversation_name + '/suggestions:suggestConversationSummary', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': JWT,
},
body: JSON.stringify({ context_size: 1000 }),
})
.then(response => response.json())
.then(data => {
$('#log').prepend(
$('<div/>').text('Received <suggestConversationSummary response> ' + JSON.stringify(data)).html() + '<br><br>'
);
})
.catch((error) => {
console.error('Error:', error);
});
return false;
});
$('form#complete').submit(function (event) {
fetch(serviceUrl + versionUrl + conversation_name + ':complete', {
method: 'POST',
headers: {
'Authorization': JWT,
},
})
.then(response => response.json())
.then(data => {
$('#log').prepend(
$('<div/>').text('Received <response for complete conversation> ' + JSON.stringify(data)).html() + '<br><br>'
);
})
.catch((error) => {
console.error('Error:', error);
});
return false;
});
$('form#join_conversation').submit(function (event) {
let interested_conversation_name = $('#interested_conversation').val();
currentSocket.emit('join-conversation', interested_conversation_name, (ack, result) => {
logPrinter(
'Emitted',
'join-conversation',
'ACK for joining conversation: ' + ack + ',' + result
)
if (ack) {
if (joined_conversations.indexOf(interested_conversation_name) > -1) {
joined_conversations.push(interested_conversation_name);
updateJoinedConversationNames();
}
}
});
return false;
});
$('form#leave_conversation').submit(function (event) {
let uninterested_conversation_name = $('#uninterested_conversation').val();
currentSocket.emit('leave-conversation', uninterested_conversation_name, (ack, result) => {
logPrinter(
'Emitted',
'leave-conversation',
'ACK for leaving conversation: ' + ack + ',' + result
)
if (ack) {
let index = joined_conversations.indexOf(uninterested_conversation_name);
if (index > -1) {
joined_conversations.splice(index, 1);
updateJoinedConversationNames();
}
}
});
return false;
});
});
</script>
</head>
<body>
<h1>AA Integration Service - Interactive Demo</h1>
<p>
Before sending messages: Set Conversation Profile, Create Conversation, Join Conversation, Create a User
participant and Create an Agent
participant.<br>
</p>
<form id="set_conversation_profile" method="POST" action='#'>
<input type="text" name="conversation_profile_test_name" id="conversation_profile_test_name"
placeholder="projects/your-project-id/conversationProfiles/your-conversation-profile-id">
<input type="submit" value="Set Conversation Profile">
</form>
<form id="get_conversation_profile" method="GET" action="#">
<input type="submit" value="Get Conversation Profile">
</form>
<form id="create" method="POST" action="#">
<input type="submit" value="Create Conversation">
</form>
<form id="set_conversation" method="POST" action='#'>
<input type="text" name="input_conversation_name" id="input_conversation_name">
<input type="submit" value="Set as Current Conversation">
</form>
<form id="join" method="POST" action="#">
<input type="submit" value="Join Current Conversation">
</form>
<form id="create_user" method="POST" action="#">
<input type="submit" value="Create a User participant">
</form>
<form id="create_agent" method="POST" action="#">
<input type="submit" value="Create an Agent participant">
</form>
<form id="user_send" method="POST" action='#'>
<input type="text" name="user_send_message" id="user_send_message" placeholder="Message">
<input type="submit" value="Send Message as End User">
</form>
<form id="agent_send" method="POST" action='#'>
<input type="text" name="agent_send_message" id="agent_send_message" placeholder="Message">
<input type="submit" value="Send Message as Human Agent">
</form>
<form id="search_knowledge" method="POST" action='#'>
<input type="text" name="search_knowledge_query" id="search_knowledge_query" placeholder="Query">
<input type="submit" value="Search Knowledge">
</form>
<form id="suggest_summary" method="POST" action="#">
<input type="submit" value="Suggest Conversation Summary">
</form>
<form id="complete" method="POST" action="#">
<input type="submit" value="Complete Conversation">
</form>
<form id="leave" method="POST" action="#">
<input type="submit" value="Leave Current Conversation">
</form>
<form id="join_conversation" method="POST" action='#'>
<input type="text" name="interested_conversation" id="interested_conversation" placeholder="Conversation Name">
<input type="submit" value="Join Another Conversation">
</form>
<form id="leave_conversation" method="POST" action='#'>
<input type="text" name="uninterested_conversation" id="uninterested_conversation"
placeholder="Conversation Name">
<input type="submit" value="Leave Another Conversation">
</form>
<p>
Current transport is: <b><span id="transport"></span></b><br>
GCP Project Id: <b><span id="gcp_project_id"></span></b><br>
GCP Location Id: <b><span id="gcp_location_id"></span></b><br>
Conversation Profile Name: <b><span id="conversation_profile_name"></span></b><br>
Conversation Name: <b><span id="conversation_name"></span></b><br>
End User Name: <b><span id="end_user_name"></span></b><br>
Human Agent Name: <b><span id="human_agent_name"></span></b><br>
</p>
<h2>Joined Conversations</h2>
<div id="joined_conversations"></div>
<h2>Log (from latest to oldest)</h2>
<div id="log" style="width: 90%; height: 400px; overflow:scroll; border: thin #000 solid; padding: 5px;">
</div>
</body>
</html>