Skip to main content

JavaScript

Runtime Name: forward

This fully programmable block type supports running code that is ECMAScript 2018 compatible (JavaScript version 9). The runtime will load the block's code into a JavaScript VM and will then execute it using semantics similar to AWS Lambda, and will use the result as the CXML document to be executed by the Cloudonix Voice Application runtime.

JavaScript not NodeJS!

Pay close the attention, the Cloudonix JavaScript runtime isn't based on NodeJS, it is a based on GraalJS and as such, doesn't provide access to all the bells and whistles NodeJS provides. Pay close attention to the examples below, in order to better understand the difference.

Calling Convention

The JavaScript runtime will expose an object as the global value exports then evaluate the block's code. The code should set up a handler function and assign it to exports.handler - the function should have the signature function(Jevent, context, callback).

After evaluating the code, the JavaScript runtime will call the handler function and will pass it the following parameters:

  • event : an object containing the CXML application request details. It is read-only and contains the following member fields:
  • body : the Voice Application request as a JSON formatted string.
  • headers : the Voice Application request headers as a standard JavaScript object (map of string keys to string values).
  • httpMethod : the method used to make the Voice Application request - either GET or POST.
  • parameters : the Voice Application request parameters as a standard JavaScript object (map of string keys to string values).
  • path : contains the request path to the block being run, within the application - i.e. / followed by the block name.
  • pathParameters : an empty object provided as backward compatibility for AWS Lambda code.
  • queryStringParameters : the same as parameters, provided as backward compatibility for AWS Lambda code.
  • requestContext : an empty object provided as backward compatibility for AWS Lambda code.
  • stageVariables : an empty object provided as backward compatibility for AWS Lambda code.
  • context : a read-write JavaScript object. No specific values are exported through this object.
  • callback : a callable with the signature function(error, response) that should be used by the code to submit the result of the block execution.

The handler function should compute the correct response to the application request and submit a CXML document by calling the callback function with a null value for the first parameter and the response document as a string for the second parameter. If an error has occured during processing, the callback function should be called with just one parameter being a JavaScript Error object describing the error - that error would be propagated to the error field of the Cloudonix session object of the call.

Examples

Dynamic Inbound Call Routing

The below script will be activated upon receiving and inbound call, which will then route the call to a predefined voice trunk.

function preamble() {
return `<?xml version="1.0"?>\n`;
}

function response(content) {
return `<Response>\n${content}\n</Response>\n`;
}

function voiceAgentConnector(callerId, destination) {
return `<Dial callerId="${callerId}">${destination}</Dial>`;
}

exports.handler = function(ev, ctx, callback) {
try {
let callerId = ev.parameters.From;
let destination = ev.parameters.To;

let cxmlResponse = voiceAgentConnector(callerId, destination);
callback(null, preamble() + response(cxmlResponse));
} catch (err) {
callback(err);
}
};

ReTell Voice Agent Inbound Calls

The below script will issue an HTTP Request to the ReTell API, notifying it of a new phone call, thus, retrieving a new call-id to use for calling ReTell. In addition, it will provide the ReTell agent with the following variables:

  • cloudonix_callerid - The caller ID of the inbound call.
  • cloudonix_destination - The destination of the inbound call.
  • cloudonix_token: The Cloudonix session token, to be used by the ReTell agent to perform REST API requests to Cloudonix.
  • cloudonix_domain: The Cloudonix domain, for which the call is being serviced.
const httpClient = require('https');

async function getReTellCallId(ev) {
const url = 'https://api.retellai.com/v2/register-phone-call';
const postHeader = {};

const token = 'key_xxxxxxxxxxxxxxxxxxxxxxxx';
const agentId = 'agent_yyyyyyyyyyyyyyyyyyyyyyyy';

const httpHeaders = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
};

const payload = {
agent_id: agentId,
from_number: ev.parameters.From,
to_number: ev.parameters.To,
direction: 'inbound',
metadata: {},
retell_llm_dynamic_variables: {
cloudonix_callerid: ev.parameters.From,
cloudonix_destination: ev.parameters.To,
cloudonix_token: ev.parameters.Session,
cloudonix_domain: ev.parameters.Domain
}
};
const postPayload = JSON.stringify(payload);

try {
const response = await httpClient.post(url, { headers: httpHeaders, body: postPayload });
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
console.log("Response from ReTell is: " + JSON.stringify(response));
const data = JSON.parse(response.body);
return data.call_id;
} catch (error) {
console.log("Response is Error: " + JSON.stringify(error));
console.error('Failed to fetch agent call_id:', error);
return error;
}
}

function preamble() {
return '<?xml version="1.0"?>\n';

}

function response(content) {
return `<Response>\n${content}\n</Response>\n`;
}

exports.handler = async (ev) => {
let reTellCallId = await getReTellCallId(ev);
let cxmlPayload = `<Dial callerId="${ev.parameters.From}">`;
cxmlPayload += `<Service provider="retell">${reTellCallId}</Service>`;
cxmlPayload += `</Dial>`;
return preamble() + response(cxmlPayload);
};