Amazon Connect Streams API (Streams) allows developers to create custom agent experiences for Amazon Connect. Since my introductory posts back in late 2017 there have been several changes to Streams, some from the community, some directly from Amazon. These changes are managed as pull requests. This post will review approved pull requests from November 2017 through May 2018, and what the changes mean for building custom applications for Amazon Connect.
Pull Requests
The code for Streams is hosted in Github and open for community contributions in the form of pull requests. A pull request (PR) is a set of pending code changes that the owner of a Github repository can approve (merge) into the main codebase or reject. Each PR has an associated thread for related discussion.
You can see a list of the open PR’s for Streams at: https://github.com/aws/amazon-connect-streams/pulls.
You can see all the commits (approved changes) to Streams at: https://github.com/aws/amazon-connect-streams/commits/master.
The PR’s approved in the timeframe covered by this post are:
-
PR #26: Addressing deprecation of permissions in cross-origin iframes warning…
-
PR #61: API Updates and NPM package system with Basic unit test cases
- PR #69: Update Documentation.md
CCP Browser Compatibility (PR #26 and #30)
PR #26 and PR #40 were community contributions from Sean Romocki (https://github.com/sromocki) that address CCP browser incompatibilities.
PR #26
PR #26 (https://github.com/aws/amazon-connect-streams/pull/26) addressed a pending web browser change that was going to block the Amazon Connect Contact Control Panel (CCP) from working properly.
As described in the PR, the Chrome browser got more strict about granting access to the microphone to applications hosted in an iframe. Since the CCP is hosted in an iframe by Streams, this change updated Streams to explicitly request permission to use the microphone. If you were working with Streams in this time frame you had to build the latest copy of Streams to keep the CCP working.
PR #26 was approved on January 23, 2018: https://github.com/aws/amazon-connect-streams/commit/5fc44af68939a2016cc1c6fd08d13793e74d5ee4
Code Changes for PR #26
As we saw in my intro posts, Streams applications start out by invoking the connect.core.initCCP method from the core.js file. initCCP adds an iframe to the application’s HTML page to host the CCP. With the code changes, before adding the iframe initCCP sets the allow attribute of the iframe to “microphone”. The allow attribute tells Chrome that it is OK to let the iframe use the microphone.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Create the CCP iframe and append it to the container div. | |
var iframe = document.createElement('iframe'); | |
iframe.src = params.ccpUrl; | |
iframe.style = "width: 100%; height: 100%"; | |
iframe.allow = "microphone"; | |
containerDiv.appendChild(iframe); |
PR #30
PR #30 (https://github.com/aws/amazon-connect-streams/pull/30) was a tweak to the notifications code in Streams that removes a deprecation warning in the JavaScript console in Chrome. This warning is not something the typical end user would look for or notice, but it is good practice to avoid warnings like this for future compatibility.
The code change for this PR was to invoke the permissions callback for notifications within a promise, avoiding the warning.
PR #30 was approved on May 29th, 2018: https://github.com/aws/amazon-connect-streams/commit/c965fbd347bcc2e18ab3b1d4f3eeb3c92be46e1b
Code Contribution Guidelines (PR #48)
PR #48 (https://github.com/aws/amazon-connect-streams/pull/48) added a pull request template, a code of conduct and contribution guidelines for the Streams repository. These documents are boilerplate describing how developers interact with the repository when they want to make pull requests. PR #46 was a community contribution from Henri Yandell (https://github.com/hyandell).
Avoid Contact Center Outages: Plan Your Upgrade to Amazon Connect
Learn the six most common pitfalls when upgrading your contact center, and how Amazon Connect can help you avoid them.
PR #48 was approved on May 29th, 2018: https://github.com/aws/amazon-connect-streams/commit/0e4fd831b85a5c97025d33962c913de4801483b8
Documentation Updates (PR #6, #52, #68, #69)
Amazon updated grammar mistakes, cleared up some vague language, and made other minor changes in a series of 3 pull requests:
An example of the type of changes made here is making sure that the documentation always refers to “Amazon Connect” and not just Connect. These pull requests were a contribution from randalld-aws (https://github.com/randalld-aws).
These pull requests were approved on May 29th, 2018:
-
(PR #52) https://github.com/aws/amazon-connect-streams/commit/8857fbe74ad1ac2dcdf973850d5726de01b06fd8
-
(PR #68) https://github.com/aws/amazon-connect-streams/commit/7f7ab6a51917778956fb4d2ebb81e11921119612
-
(PR #69) https://github.com/aws/amazon-connect-streams/commit/4a6ac8cf114a2e261b78534f18a32c62ee3e8031
Community contributor Bast Leblanc (https://github.com/BastLeblanc) added an example of the CCP URL to the documentation with PR #6 (https://github.com/aws/amazon-connect-streams/pull/6). You need this URL to initialize a custom Streams application, so it is nice to have an additional pointer to it in the documentation.
PR #6 was approved on May 29th, 2018: https://github.com/aws/amazon-connect-streams/commit/83b913c897c02c3e2e60ab30b7e5bebccf2e7e91
API Updates (mute) and NPM build (PR #61)
PR #61: https://github.com/aws/amazon-connect-streams/pull/61 was created by Amazon’s jagadeeshaby (https://github.com/jagadeeshaby). This PR added mute control to Streams, made it easier for developers to include the Streams library and fixed a number of small bugs.
These changes are described at a high level in the description of pull request #61 (https://github.com/aws/amazon-connect-streams/pull/61).
Mute Control
With these changes, Streams gets 3 new agent object methods to control the agent’s audio: mute, unmute and onMuteToggle. These methods can be used to create mute and unmute controls in a custom CCP. These methods are documented at: https://github.com/aws/amazon-connect-streams/blob/master/Documentation.md.
Code
The new mute control methods are in the api.js file, hanging off the agent object.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Agent.prototype.onMuteToggle = function(f) { | |
var bus = connect.core.getEventBus(); | |
bus.subscribe(connect.AgentEvents.MUTE_TOGGLE, f); | |
}; | |
Agent.prototype.mute = function() { | |
connect.core.getUpstream().sendUpstream(connect.EventType.BROADCAST, | |
{ | |
event: connect.EventType.MUTE, | |
data: {mute: true} | |
}); | |
}; | |
Agent.prototype.unmute = function() { | |
connect.core.getUpstream().sendUpstream(connect.EventType.BROADCAST, | |
{ | |
event: connect.EventType.MUTE, | |
data: {mute: false} | |
}); | |
}; |
The mute and unmute functions broadcast MUTE events upstream, i.e. to any other listening components, with a mute flag of true to mute, false to unmute.
What other components are listening? Our old friend softphone.js, last seen in my post on implementing a mute button in Amazon Connect (https://blogs.perficient.com/2017/10/26/implementing-a-mute-button-in-amazon-connect/). In softphone.js we see changes in this PR to subscribe and handle MUTE events.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Bind events for mute | |
var handleSoftPhoneMuteToggle = function() { | |
var bus = connect.core.getEventBus(); | |
bus.subscribe(connect.EventType.MUTE, muteToggle); | |
}; | |
// Make sure once we disconnected we get the mute state back to normal | |
var deleteLocalMediaStream = function(connectionId) { | |
delete localMediaStream[connectionId]; | |
connect.core.getUpstream().sendUpstream(connect.EventType.BROADCAST, { | |
event: connect.AgentEvents.MUTE_TOGGLE, | |
data: { muted: false } | |
}); | |
}; | |
// Check for the local streams if exists – revert it | |
// And inform other clients about the change | |
var muteToggle = function(data) { | |
var status; | |
if (connect.keys(localMediaStream).length === 0) { | |
return; | |
} | |
if (data && data.mute !== undefined) { | |
status = data.mute; | |
} | |
for (var connectionId in localMediaStream) { | |
if (localMediaStream.hasOwnProperty(connectionId)) { | |
var localMedia = localMediaStream[connectionId].stream; | |
if (localMedia) { | |
var audioTracks = localMedia.getAudioTracks()[0]; | |
if (status !== undefined) { | |
audioTracks.enabled = !status; | |
localMediaStream[connectionId].muted = status; | |
if (status) { | |
logger.info( | |
"Agent has muted the contact, connectionId – " + connectionId | |
); | |
} else { | |
logger.info( | |
"Agent has unmuted the contact, connectionId – " + connectionId | |
); | |
} | |
} else { | |
status = localMediaStream[connectionId].muted || false; | |
} | |
} | |
} | |
} | |
connect.core.getUpstream().sendUpstream(connect.EventType.BROADCAST, { | |
event: connect.AgentEvents.MUTE_TOGGLE, | |
data: { muted: status } | |
}); | |
}; |
The softphone subscribes to MUTE events in handleSoftPhoneMuteToggle and when it gets a MUTE event it invokes the muteToggle function. The muteToggle function finds the agent’s media stream and sets its enabled property to false (muted) or true (unmuted). A reference to the media stream is stored in the localMediaStream object whenever a media stream is added to the active call. That code is session.onLocalStreamAdded.
After the media stream is modified in muteToggle, the softphone publishes a MUTE_TOGGLE event with the new muted status for any upstream listeners.
If you are curious about the code that publishes events “upstream”, you can refer to the source code for the Stream objects at: https://github.com/aws/amazon-connect-streams/blob/master/src/streams.js. The general idea is that there is a service worker that relays events from the Streams application code to the CCP iframe and from the CCP iframe up to Amazon Connect’s back-end service. For a visual of this interaction see the Architecture diagram at https://github.com/aws/amazon-connect-streams/blob/master/Architecture.md.
NPM Build
NPM (https://www.npmjs.com/) is the most used package manager for JavaScript and this Streams PR adds support for building Streams with NPM. Previously, to use Streams, you had to build it yourself using a buildfile, as I described at https://blogs.perficient.com/2017/10/05/intro-to-amazon-connect-streams-api-part-1/. This type of build added some extra steps for Windows developers and was out of step with common JavaScript library practices.
With this NPM build support, building is a matter of having NPM, which JavaScript developers will and running a few simple terminal commands.
Getting Streams to build using NPM is a nice improvement for developers. There are a few minor issues to be aware of, that have been raised as an issue in Github: https://github.com/aws/amazon-connect-streams/issues/66 by community member extmchristensen (https://github.com/extmchristensen).
Better Logging and Miscellaneous Bug Fixes
The PR doesn’t elaborate on the details of the better logging or bug fixes. The are changes across nearly 20 files and in particular softphone.js has a large diff between the prior version and the PR. With that said, I skimmed through the diff’s and identified some to highlight:
-
Clean up logic in core.js is now invoked on browser onunload versus onbeforeunload. The difference here is subtle. The unload event is fired after beforeunload when a page is being unloaded. I assume this provides smoother shutdown behavior when a user closes the browser or navigates away from a Streams application
-
The publication of certain event types like API_METRIC, LOG and MASTER_RESPONSE are no longer logged in event.js. This presumably helps keep the JavaScript console less cluttered in the browser
-
Ringtone Start and Ringstone Stops telemetry events with call info are now published when ringing starts and stops respectively. Callback ringing is distinguished with a Callback Ringtone Connecting event. I’m not sure where these events go or if they are accessible for querying. This new code is in ringtone.js
-
Additional error handling to stop a ringtone if the onAccepted or onConnected callbacks fail. This new code is also in ringtone.js
-
Better handling for calls getting re-routed to the same agent multiple times and better session clean up in softphone.js.
-
Metrics on the responsiveness of the back-end Connect API, i.e. how long it took a given request to complete, are now gathered by the worker in worker.js. See the WorkerClient method
-
Implements an exponential backoff with retry strategy when trying to refresh the auth token for the back-end Connect API. This should make the Streams apps more resilient when kept open for a long time. See connect.backoff in the util.js and then line 575 in worker.js
Thanks for reading. Next time we will take a look at some open pull requests for Streams. Any questions, comments or corrections are greatly appreciated. To learn more about what we can do with Amazon Connect, check out Helping You Get the Most Out of Amazon Connect