Skip to content

Commit

Permalink
Adding AWS Workspace as a VDI Platform Option (#903)
Browse files Browse the repository at this point in the history
Adding AWS Workspace as a VDI option and updating README

---------

Co-authored-by: Andy Wang <[email protected]>
  • Loading branch information
andywang219 and Andy Wang authored Jul 31, 2024
1 parent 8cfe111 commit e1689ac
Show file tree
Hide file tree
Showing 12 changed files with 103 additions and 15 deletions.
14 changes: 11 additions & 3 deletions Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ In version 1.x, we also support `make` for legacy builds. This option was remove

# Important Announcements

1. March 2024 - In response to a Google Chrome feature launched on 7/13/2023 called [Storage Partitioning](https://developers.google.com/privacy-sandbox/3pcd/storage-partitioning), we made a short term fix on 2/10/2024 to adjust our mute functionality and synchronize the mute state across all CCPs. However, due to current limitations, this change required us to disable muting while being on hold. As a workaround, agents should mute themselves on the call before going on hold. We are planning to address this issue by August 2024 and revert back to original mute behavior.
1. July 2024 - The issue with muting while a Voice contact is on hold has been resolved. Agents can use the mute button while a contact is placed on hold. The following APIs will be available when the contact is on hold:
* `voiceConnection.muteParticipant()`
* `voiceConnection.unmuteParticipant()`
* `agent.mute()`
* `agent.unmute()`
1. February 2024 - In response to a Google Chrome feature launched on 7/13/2023 called [Storage Partitioning](https://developers.google.com/privacy-sandbox/3pcd/storage-partitioning), we made a short term fix on 2/10/2024 to adjust our mute functionality and synchronize the mute state across all CCPs. However, due to current limitations, this change required us to disable muting while being on hold. As a workaround, agents should mute themselves on the call before going on hold. We are planning to address this issue by August 2024 and revert back to original mute behavior.
* At the moment, the following APIs will fail when the contact is on hold:
* `voiceConnection.muteParticipant()`
* `voiceConnection.unmuteParticipant()`
* `agent.mute()`
* `agent.unmute()`
* As a workaround, you can mute the call prior to placing the call on hold.

1. December 2022 - In addition to the CCP, customers can now embed an application that provides guided experiences to your agents using the connect.agentApp. See the [updated documentation](https://github.com/amazon-connect/amazon-connect-streams/blob/master/Documentation.md#initialization-for-ccp-customer-profiles-amazon-q-connect-and-customviews) for details on usage.
- ### Guided experiences for agents
- With Amazon Connect you can now create guided step-by-step experiences that walk agents through tailored views that focus on what must be seen or done by the agent at a given moment during an interaction. You can design workflows for various types of customer interactions and present agents with different step-by-step guides based on context, such as call queue, customer information, and interactive voice response (IVR). This feature is available in the Connect agent workspace as well as an embeddable application that can be embedded into another website via the Streams API. For more information, visit the AWS website: https://aws.amazon.com/connect/agent-workspace/
Expand Down Expand Up @@ -225,8 +229,12 @@ everything set up correctly and that you are able to listen for events.
VDIPlatform: null, // optional, provide with 'CITRIX' if using Citrix VDI, or use enum VDIPlatformType
allowEarlyGum: true, //optional, default to true
},
task: {
disableRingtone: false, // optional, defaults to false
ringtoneUrl: "[your-ringtone-filepath].mp3" // optional, defaults to CCP's default ringtone if a falsy value is set
},
storageAccess: {
canRequest: true, // By default this is set to true. You can set it to false to opt out from checking storage access.
canRequest: false, // By default this is set to false. You can set it to true to opt in for checking storage access.
mode: "custom", // To use the default banner, set this to "default"
/** More customization options can be found here: https://github.com/amazon-connect/amazon-connect-streams/blob/master/src/index.d.ts under StorageAccessParameters */
},
Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ Run `npm run release` to generate new release files. Full instructions for build
In version 1.x, we also support `make` for legacy builds. This option was removed in version 2.x.

# Important Announcements
1. March 2024 - In response to a Google Chrome feature launched on 7/13/2023 called [Storage Partitioning](https://developers.google.com/privacy-sandbox/3pcd/storage-partitioning), we made a short term fix on 2/10/2024 to adjust our mute functionality and synchronize the mute state across all CCPs. However, due to current limitations, this change required us to disable muting while being on hold. As a workaround, agents should mute themselves on the call before going on hold. We are planning to address this issue by August 2024 and revert back to original mute behavior.
1. July 2024 - The issue with muting while a Voice contact is on hold has been resolved. Agents can use the mute button while a contact is placed on hold. The following APIs will be available when the contact is on hold:
* `voiceConnection.muteParticipant()`
* `voiceConnection.unmuteParticipant()`
* `agent.mute()`
* `agent.unmute()`
1. February 2024 - In response to a Google Chrome feature launched on 7/13/2023 called [Storage Partitioning](https://developers.google.com/privacy-sandbox/3pcd/storage-partitioning), we made a short term fix on 2/10/2024 to adjust our mute functionality and synchronize the mute state across all CCPs. However, due to current limitations, this change required us to disable muting while being on hold. As a workaround, agents should mute themselves on the call before going on hold. We are planning to address this issue by August 2024 and revert back to original mute behavior.
* At the moment, the following APIs will fail when the contact is on hold:
* `voiceConnection.muteParticipant()`
* `voiceConnection.unmuteParticipant()`
Expand Down Expand Up @@ -208,7 +213,7 @@ everything setup correctly and that you will be able to listen for events.
},
task: {
disableRingtone: false, // optional, defaults to false
ringtoneUrl: "[your-ringtone-filepath].mp3", // optional, defaults to CCP's default ringtone if a falsy value is set
ringtoneUrl: "[your-ringtone-filepath].mp3" // optional, defaults to CCP's default ringtone if a falsy value is set
},
pageOptions: { //optional
enableAudioDeviceSettings: false, //optional, defaults to 'false'
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "amazon-connect-streams",
"version": "2.14.3",
"version": "2.14.4",
"description": "Amazon Connect Streams Library",
"engines": {
"node": ">=12.0.0"
Expand Down
2 changes: 1 addition & 1 deletion release/connect-streams-dr-min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion release/connect-streams-dr.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion release/connect-streams-min.js

Large diffs are not rendered by default.

25 changes: 23 additions & 2 deletions release/connect-streams.js
Original file line number Diff line number Diff line change
Expand Up @@ -26896,7 +26896,7 @@ AWS.apiLoader.services['connect']['2017-02-15'] = require('../apis/connect-2017-

connect.core = {};
connect.core.initialized = false;
connect.version = "2.14.3";
connect.version = "2.14.4";
connect.outerContextStreamsVersion = null;
connect.DEFAULT_BATCH_SIZE = 500;

Expand Down Expand Up @@ -31771,6 +31771,7 @@ AWS.apiLoader.services['connect']['2017-02-15'] = require('../apis/connect-2017-

const VDIPlatformType = {
CITRIX: "CITRIX",
AWS_WORKSPACE: "AWS_WORKSPACE",
}

var RTPJobIntervalMs = 1000;
Expand Down Expand Up @@ -31803,6 +31804,11 @@ AWS.apiLoader.services['connect']['2017-02-15'] = require('../apis/connect-2017-
var consecutiveNoAudioOutputPackets = 0;
var consecutiveLowOutputAudioLevel = 0;
var audioInputConnectedDurationSeconds = 0;
// Time from CCP received the softphone contact till local media is added to the softphone session
var ccpMediaReadyLatencyMillis = 0;
var allowEarlyGum = false;
var earlyGumWorked = false;
var vdiPlatform = null;
var rtpStatsJob = null;
var reportStatsJob = null;
//Logger specific to softphone.
Expand Down Expand Up @@ -31846,10 +31852,15 @@ AWS.apiLoader.services['connect']['2017-02-15'] = require('../apis/connect-2017-

let rtcJsStrategy;
if (softphoneParams.VDIPlatform) {
vdiPlatform = softphoneParams.VDIPlatform;
try {
if (softphoneParams.VDIPlatform === VDIPlatformType.CITRIX) {
rtcJsStrategy = new connect.CitrixVDIStrategy();
logger.info(`[SoftphoneManager] Strategy constructor retrieved: ${rtcJsStrategy}`).sendInternalLogToServer();
}
else if (softphoneParams.VDIPlatform === VDIPlatformType.AWS_WORKSPACE) {
rtcJsStrategy = new connect.DCVWebRTCStrategy();
logger.info(`[SoftphoneManager] Strategy constructor retrieved: ${rtcJsStrategy}`).sendInternalLogToServer();
} else {
throw new Error("VDI Strategy not supported");
}
Expand All @@ -31862,6 +31873,10 @@ AWS.apiLoader.services['connect']['2017-02-15'] = require('../apis/connect-2017-
publishError(SoftphoneErrorTypes.VDI_REDIR_NOT_SUPPORTED, error.message, "");
throw error;
}
else if (error.message === "DCV WebRTC redirection feature is NOT supported!") {
publishError(SoftphoneErrorTypes.VDI_REDIR_NOT_SUPPORTED, error.message, "");
throw error;
}
else {
publishError(SoftphoneErrorTypes.OTHER, error.message, "");
throw error;
Expand Down Expand Up @@ -32582,7 +32597,13 @@ AWS.apiLoader.services['connect']['2017-02-15'] = require('../apis/connect-2017-
consecutiveLowInputAudioLevel: consecutiveLowInputAudioLevel,
consecutiveNoAudioOutputPackets: consecutiveNoAudioOutputPackets,
consecutiveLowOutputAudioLevel: consecutiveLowOutputAudioLevel,
audioInputConnectedDurationSeconds: audioInputConnectedDurationSeconds
audioInputConnectedDurationSeconds: audioInputConnectedDurationSeconds,
ccpMediaReadyLatencyMillis: ccpMediaReadyLatencyMillis,
contactSubtype: contact.getContactSubtype(),
earlyGumEnabled: allowEarlyGum,
earlyGumWorked: earlyGumWorked,
vdiPlatform: vdiPlatform || null,
streamJsVersion: connect.version
}

connect.publishSoftphoneReport({
Expand Down
3 changes: 2 additions & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,8 @@ declare namespace connect {
/** This enumeration lists the different types of VDI Platform supported. */
enum VDIPlatformType {
/** Citrix. */
CITRIX = "CITRIX"
CITRIX = "CITRIX",
AWS_WORKSPACE = "AWS_WORKSPACE",
}

/** This enumeration lists the different types of contact channels. */
Expand Down
23 changes: 22 additions & 1 deletion src/softphone.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

const VDIPlatformType = {
CITRIX: "CITRIX",
AWS_WORKSPACE: "AWS_WORKSPACE",
}

var RTPJobIntervalMs = 1000;
Expand Down Expand Up @@ -44,6 +45,11 @@
var consecutiveNoAudioOutputPackets = 0;
var consecutiveLowOutputAudioLevel = 0;
var audioInputConnectedDurationSeconds = 0;
// Time from CCP received the softphone contact till local media is added to the softphone session
var ccpMediaReadyLatencyMillis = 0;
var allowEarlyGum = false;
var earlyGumWorked = false;
var vdiPlatform = null;
var rtpStatsJob = null;
var reportStatsJob = null;
//Logger specific to softphone.
Expand Down Expand Up @@ -87,10 +93,15 @@

let rtcJsStrategy;
if (softphoneParams.VDIPlatform) {
vdiPlatform = softphoneParams.VDIPlatform;
try {
if (softphoneParams.VDIPlatform === VDIPlatformType.CITRIX) {
rtcJsStrategy = new connect.CitrixVDIStrategy();
logger.info(`[SoftphoneManager] Strategy constructor retrieved: ${rtcJsStrategy}`).sendInternalLogToServer();
}
else if (softphoneParams.VDIPlatform === VDIPlatformType.AWS_WORKSPACE) {
rtcJsStrategy = new connect.DCVWebRTCStrategy();
logger.info(`[SoftphoneManager] Strategy constructor retrieved: ${rtcJsStrategy}`).sendInternalLogToServer();
} else {
throw new Error("VDI Strategy not supported");
}
Expand All @@ -103,6 +114,10 @@
publishError(SoftphoneErrorTypes.VDI_REDIR_NOT_SUPPORTED, error.message, "");
throw error;
}
else if (error.message === "DCV WebRTC redirection feature is NOT supported!") {
publishError(SoftphoneErrorTypes.VDI_REDIR_NOT_SUPPORTED, error.message, "");
throw error;
}
else {
publishError(SoftphoneErrorTypes.OTHER, error.message, "");
throw error;
Expand Down Expand Up @@ -823,7 +838,13 @@
consecutiveLowInputAudioLevel: consecutiveLowInputAudioLevel,
consecutiveNoAudioOutputPackets: consecutiveNoAudioOutputPackets,
consecutiveLowOutputAudioLevel: consecutiveLowOutputAudioLevel,
audioInputConnectedDurationSeconds: audioInputConnectedDurationSeconds
audioInputConnectedDurationSeconds: audioInputConnectedDurationSeconds,
ccpMediaReadyLatencyMillis: ccpMediaReadyLatencyMillis,
contactSubtype: contact.getContactSubtype(),
earlyGumEnabled: allowEarlyGum,
earlyGumWorked: earlyGumWorked,
vdiPlatform: vdiPlatform || null,
streamJsVersion: connect.version
}

connect.publishSoftphoneReport({
Expand Down
31 changes: 31 additions & 0 deletions test/unit/softphone.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,37 @@ describe('SoftphoneManager', () => {
// });
});

describe('VDIPlatform: AWS_WORKSPACE', () => {
before(() => {
connect.isChromeBrowser.returns(true);
connect.isFirefoxBrowser.returns(false);
connect.hasOtherConnectedCCPs.returns(false);
});
afterEach(() => {
sandbox.resetHistory();
});
it('should create RTC session and call session.connect()', function () {
const softphoneManager = new connect.SoftphoneManager({ VDIPlatform: "AWS_WORKSPACE" });
stubbedGetStatus.returns({ type: connect.ContactStatusType.CONNECTING });
softphoneManager.startSession(contact, agentConnectionId);
sinon.assert.calledOnce(stubbedRTCSessionConnect);
});
it('should NOT create another RTC session if startSession is called twice', function () {
const softphoneManager = new connect.SoftphoneManager({ VDIPlatform: "AWS_WORKSPACE" });
stubbedGetStatus.returns({ type: connect.ContactStatusType.CONNECTING });
softphoneManager.startSession(contact, agentConnectionId);
stubbedGetStatus.returns({ type: connect.ContactStatusType.CONNECTED });
let error;
try {
softphoneManager.startSession(contact, agentConnectionId);
} catch (e) {
error = e;
}
sinon.assert.calledOnce(stubbedRTCSessionConnect);
expect(error).not.to.be.undefined;
});
});

describe('disableEchoCancellation', () => {
const disableEchoCancellation = true;
before(() => {
Expand Down
1 change: 1 addition & 0 deletions test/unit/test-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ require('../../release/connect-streams.js');

global.connect.StandardStrategy = function () {};
global.connect.CitrixVDIStrategy = function () {};
global.connect.DCVWebRTCStrategy = function () {};
global.connect.RTCSession = function () {};
global.connect.RtcPeerConnectionFactory = function () {};
global.AWS = {
Expand Down

0 comments on commit e1689ac

Please sign in to comment.