The human handover itself does work, but the events “TRANSFER_FAIL” and “TRANSFER_SUCCESS” do never arrive at Dialogflow. I try to hit the TRANSFER_FAIL by using a wrong password.
This is the complete code:
require(Modules.AI);
const languageCode = "";
const agentId = 0000;
const profile = "";
const appName = "";
const region = "";
let agent,
call,
conversation,
conversationParticipant,
isConversationCreated = false,
isCallCreated = false,
isCallConnected = false,
isParticipantCreated = false,
hangup = false,
transfer = false,
outboundCall,
phonenumberCaller,
phonenumberCalled,
singleResponse = false,
sipUsername,
sipPassword,
sipConnectionstring,
shortAnswers = []; //["ja","nee"];
VoxEngine.addEventListener(AppEvents.Started, function(ev) {
agent = new CCAI.Agent(agentId, region);
agent.addEventListener(CCAI.Events.Agent.Started, () => {
conversation = new CCAI.Conversation({
agent,
profile: {
name: profile
},
project: appName
});
conversation.addEventListener(CCAI.Events.Conversation.Created, () => {
isConversationCreated = true;
createParticipant();
});
});
});
VoxEngine.addEventListener(AppEvents.CallAlerting, function(ev) {
isCallCreated = true;
createParticipant();
call = ev.call;
call.record();
phonenumberCaller = ev.callerid;
displayName = ev.displayName;
if(ev.headers.Diversion != null){
phonenumberCalled = ev.headers.Diversion.substring(ev.headers.Diversion.indexOf(':')+1,ev.headers.Diversion.indexOf('@'));
}else {
phonenumberCalled = ev.destination;
}
call.answer();
call.addEventListener(CallEvents.Connected, function() {
isCallConnected = true;
});
call.addEventListener(CallEvents.Disconnected, function() {
conversationParticipant.analyzeContent({
eventInput: { name: "EARLY_HANGUP", languageCode: languageCode },
});
conversation.stop();
VoxEngine.terminate();
});
});
function endConversation() {
conversation.stop();
call.hangup();
VoxEngine.terminate();
}
function createParticipant() {
if (!isConversationCreated || !isCallCreated) return;
conversationParticipant = conversation.addParticipant({
call: call,
options: {
role: "END_USER"
},
dialogflowSettings: {
enableMixingAudio: true,
lang: languageCode,
singleUtterance: true,
replyAudioConfig: {
audioEncoding: "OUTPUT_AUDIO_ENCODING_OGG_OPUS",
// Synthesized voice configuration
synthesizeSpeechConfig: {
voice: {
name: "nl-NL-Wavenet-E"
}
},
}
}
});
conversationParticipant.addEventListener(CCAI.Events.Participant.Created, () => {
isParticipantCreated = true;
setupMedia();
});
conversationParticipant.addEventListener(CCAI.Events.Participant.Response, (e) => {
if (e.response.automatedAgentReply?.responseMessages) {
e.response.automatedAgentReply.responseMessages.forEach((response) => {
if (response.liveAgentHandoff) transfer = true;
if (response.endInteraction && e.response.replyText) hangup = true;
else if (response.endInteraction) endConversation();
})
}
});
conversationParticipant.addEventListener(CCAI.Events.Participant.Response, (e) => {
if (e.response.automatedAgentReply) {
let webhookPayload = e.response.automatedAgentReply.parameters
if (
webhookPayload &&
webhookPayload.expectShortAnswer &&
webhookPayload.shortAnswers &&
webhookPayload.shortAnswers.length > 0
) {
Logger.write("Expecting a short answer, so starting check for intermediary speech recognition results");
singleResponse = true;
shortAnswers = webhookPayload.shortAnswers;
Logger.write(shortAnswers);
} else {
singleResponse = false;
shortAnswers = [];
}
}
if (!singleResponse && e.response.automatedAgentReply?.responseMessages) {
e.response.automatedAgentReply.responseMessages.forEach((response) => {
if (response.liveAgentHandoff) {
Logger.write("Agent handoff");
let webhookPayload = e.response.automatedAgentReply.parameters;
sipUsername = webhookPayload.SIP_USERNAME;
sipPassword = webhookPayload.SIP_PASSWORD;
sipConnectionstring = webhookPayload.SIP_CONNECTIONSTRING;
transfer = true;
}
if (response.endInteraction && e.response.replyText) {
Logger.write("Hangup");
hangup = true;
}
else if (response.endInteraction) {
Logger.write("End conversation");
endConversation();
}
})
}else{
if (singleResponse && e.response.recognitionResult && !e.response.automatedAgentReply) {
const transcript = e.response.recognitionResult.transcript;
if (transcript) {
Logger.write("Found transcript");
if (e.response.recognitionResult.isFinal) {
Logger.write("Got a final response from Dialogflow so sending query")
call.stopMediaTo(conversationParticipant) // Stop sending media to Dialogflow
} else if (singleResponse) {
if (shortAnswers.includes(transcript.toLowerCase())) {
Logger.write("Short answer found");
singleResponse = false;
call.stopMediaTo(conversationParticipant);
}
else {
Logger.write("No short answer match");
call.stopMediaTo(conversationParticipant);
}
}
} else {
Logger.write("No matches");
call.stopMediaTo(conversationParticipant);
}
}
}
});
conversationParticipant.addEventListener(CCAI.Events.Participant.PlaybackFinished, (e) => {
if (transfer) {
Logger.write("Do transfer");
transfer = false;
outboundCall = VoxEngine.callSIP(sipConnectionstring, {
authUser: sipUsername,
password: "wrong_password",
extraHeaders: {},
video: false,
outProxy: null
});
outboundCall.addEventListener(CallEvents.Connected, () => {
Logger.write('Transfer connected');
VoxEngine.easyProcess(call, outboundCall, () => {
conversationParticipant.analyzeContent({
eventInput: { name: "TRANSFER_SUCCESS", languageCode: languageCode, parameters:{} },
});
endConversation();
});
});
outboundCall.addEventListener(CallEvents.Failed, (a) => {
Logger.write('Transfer failed')
conversationParticipant.analyzeContent({
eventInput: { name: "TRANSFER_FAIL", languageCode: languageCode, parameters:{} },
});
});
}else
if (hangup) {
endConversation();
}
})
conversationParticipant.addEventListener(CCAI.Events.Participant.MarkerReached, (e) => {
// without transfer check, the conversation stops immediately
if (transfer) {
Logger.write("MARKER REACHED IN USER VE SCRIPT")
call.stopMediaTo(conversationParticipant);
}
});
}
function setupMedia() {
if (!isParticipantCreated || !isCallConnected) return;
conversationParticipant.analyzeContent({
eventInput: {
name: "WELCOME",
languageCode: languageCode,
parameters: {
phonenumber: phonenumberCaller,
phonenumberCalled: phonenumberCalled
}
},
});
conversationParticipant.sendMediaTo(call);
}
Thanks for the help.
Greetings