From 76d325de97ded9483a2c1cd1b27c22d0c56fe9aa Mon Sep 17 00:00:00 2001 From: janorivera Date: Tue, 20 Jan 2026 13:38:58 -0300 Subject: [PATCH 1/6] Alejandro/usvc/web prod patch (#3833) * prod webchat * test * updates * test * new flex channel --- webchat/configurations/usvc-production.ts | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 webchat/configurations/usvc-production.ts diff --git a/webchat/configurations/usvc-production.ts b/webchat/configurations/usvc-production.ts new file mode 100644 index 0000000000..9b54e00420 --- /dev/null +++ b/webchat/configurations/usvc-production.ts @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2021-2023 Technology Matters + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +import { Configuration } from '../types'; +import { config as usvcStaging } from '../configurations/usvc-staging'; + +const accountSid = 'AC3240f813a27a4c52b12e5c5c23960b25'; +const flexFlowSid = 'FO98a2a2bf5f016669bba61ef9c19983aa'; + +export const config: Configuration = { + ...usvcStaging, + checkOpenHours: false, + accountSid, + flexFlowSid, + twilioServicesUrl: new URL(`https://hrm-production.tl.techmatters.org/lambda/twilio/account-scoped/${accountSid}`), +}; From e18160f076c50d2227b387951f3f44b298fe31f7 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Fri, 6 Feb 2026 10:06:28 +0000 Subject: [PATCH 2/6] Remove identifier from task second line for SMS when message is not from current agent --- plugin-hrm-form/src/maskIdentifiers/index.ts | 31 +++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/plugin-hrm-form/src/maskIdentifiers/index.ts b/plugin-hrm-form/src/maskIdentifiers/index.ts index a3a11c5c63..b1f88b9223 100644 --- a/plugin-hrm-form/src/maskIdentifiers/index.ts +++ b/plugin-hrm-form/src/maskIdentifiers/index.ts @@ -1,4 +1,4 @@ -/* eslint-disable import/no-unused-modules */ +/* eslint-disable import/no-unused-modules,dot-notation */ /** * Copyright (C) 2021-2023 Technology Matters * This program is free software: you can redistribute it and/or modify @@ -14,7 +14,17 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see https://www.gnu.org/licenses/. */ -import { Strings, TaskChannelDefinition, MessagingCanvas, MessageList } from '@twilio/flex-ui'; +import { + Strings, + TaskChannelDefinition, + MessagingCanvas, + MessageList, + StateHelper, + ConversationHelper, + TaskHelper, + DefaultTaskChannels, + Manager, +} from '@twilio/flex-ui'; import { getInitializedCan } from '../permissions/rules'; import { PermissionActions } from '../permissions/actions'; @@ -24,7 +34,7 @@ export const maskChannelStringsWithIdentifiers = (channelType: TaskChannelDefini const can = getInitializedCan(); const maskIdentifiers = !can(PermissionActions.VIEW_IDENTIFIERS); if (!maskIdentifiers) return; - + const { strings } = Manager.getInstance(); const { IncomingTaskCanvas, TaskListItem, @@ -40,7 +50,20 @@ export const maskChannelStringsWithIdentifiers = (channelType: TaskChannelDefini // Task list and panel when a call comes in TaskListItem.firstLine = 'MaskIdentifiers'; - + if (channelType.name === DefaultTaskChannels.ChatSms.name) { + // The unmasked service user number appears in the last message info on SMS if they sent the last message + // Lets replace it with a version that doesn't include the sender, regardless of who s + TaskListItem.secondLine = task => { + const conversationState = StateHelper.getConversationStateForTask(task); + const taskHelper = new TaskHelper(task); + const conversationHelper = new ConversationHelper(conversationState); + return `${taskHelper.durationSinceUpdate} | ${ + conversationHelper.lastMessage.isFromMe + ? conversationHelper.lastMessage.authorName + : strings['MaskIdentifiers'] ?? '-' + }: ${conversationHelper.lastMessage.source.body}`; + }; + } // Task panel during an active call TaskCanvasHeader.title = 'MaskIdentifiers'; Supervisor.TaskCanvasHeader.title = 'MaskIdentifiers'; From 334c6cb0af644319fcbc015bd3447153785c61e9 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Fri, 6 Feb 2026 10:22:02 +0000 Subject: [PATCH 3/6] Fix error where there is no last message for a task that hasn't been accepted yet --- plugin-hrm-form/src/maskIdentifiers/index.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugin-hrm-form/src/maskIdentifiers/index.ts b/plugin-hrm-form/src/maskIdentifiers/index.ts index b1f88b9223..66d7ab5e5e 100644 --- a/plugin-hrm-form/src/maskIdentifiers/index.ts +++ b/plugin-hrm-form/src/maskIdentifiers/index.ts @@ -54,14 +54,17 @@ export const maskChannelStringsWithIdentifiers = (channelType: TaskChannelDefini // The unmasked service user number appears in the last message info on SMS if they sent the last message // Lets replace it with a version that doesn't include the sender, regardless of who s TaskListItem.secondLine = task => { - const conversationState = StateHelper.getConversationStateForTask(task); const taskHelper = new TaskHelper(task); + const conversationState = StateHelper.getConversationStateForTask(task); + if (!conversationState) { + return taskHelper.durationSinceUpdate; + } const conversationHelper = new ConversationHelper(conversationState); return `${taskHelper.durationSinceUpdate} | ${ - conversationHelper.lastMessage.isFromMe - ? conversationHelper.lastMessage.authorName + conversationHelper.lastMessage?.isFromMe + ? conversationHelper.lastMessage?.authorName : strings['MaskIdentifiers'] ?? '-' - }: ${conversationHelper.lastMessage.source.body}`; + }: ${conversationHelper.lastMessage?.source.body ?? ''}`; }; } // Task panel during an active call From 2107a95cf69caf5ea5cb30071342c45c1056f599 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Mon, 26 Jan 2026 08:58:37 +0000 Subject: [PATCH 4/6] Fix chat scripts in E2E tests for Lex 2 default phrases (cherry picked from commit 123ca398348ea55fa5466a3c8b458fe1f1c1564f) --- e2e-tests/chatScripts.ts | 6 ++---- twilio-iac/helplines/tz/staging.hcl | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/e2e-tests/chatScripts.ts b/e2e-tests/chatScripts.ts index d13789ee2b..d069bff2c5 100644 --- a/e2e-tests/chatScripts.ts +++ b/e2e-tests/chatScripts.ts @@ -24,15 +24,13 @@ import { import { getConfigValue } from './config'; export const defaultScript: ChatStatement[] = [ - botStatement( - 'Welcome. To help us better serve you, please answer the following questions. Are you calling about yourself? Please answer Yes or No.', - ), + botStatement('Welcome to the helpline. Please answer the following questions.'), callerStatement('yes'), botStatement('How old are you?'), callerStatement('10'), botStatement('What is your gender?'), callerStatement('girl'), - botStatement("We'll transfer you now. Please hold for a counsellor."), + botStatement('We will transfer you now. Please hold for a counsellor.'), counselorAutoStatement('Hi, this is the counsellor. How can I help you?'), callerStatement('CALLER TEST CHAT MESSAGE'), counselorStatement('COUNSELLOR TEST CHAT MESSAGE'), diff --git a/twilio-iac/helplines/tz/staging.hcl b/twilio-iac/helplines/tz/staging.hcl index 17a0d7864b..0a0aa7232d 100644 --- a/twilio-iac/helplines/tz/staging.hcl +++ b/twilio-iac/helplines/tz/staging.hcl @@ -5,8 +5,7 @@ locals { local_config = { enable_post_survey = true - enable_lex_v2 = false - lex_v2_bot_languages = false + lex_v2_bot_languages = { } enable_datadog_monitoring = false custom_task_routing_filter_expression = "channelType IN [ 'whatsapp', 'instagram'] OR (channelType IN ['web'] AND preEngagementData.area == 'Main Land') OR (channelType IN ['web'] AND preEngagementData.language == 'sw_TZ' AND worker.routing.skills HAS 'Swahili') OR (channelType IN ['messenger'] AND facebookPage == 'mainland') OR twilioNumber == 'instagram:17841472327571934'" From 63b99a20d1834d8f3f83dab64a1a4f5eea9141d9 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Fri, 6 Feb 2026 11:48:29 +0000 Subject: [PATCH 5/6] Update plugin-hrm-form/src/maskIdentifiers/index.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- plugin-hrm-form/src/maskIdentifiers/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-hrm-form/src/maskIdentifiers/index.ts b/plugin-hrm-form/src/maskIdentifiers/index.ts index 66d7ab5e5e..81b5c1dd7d 100644 --- a/plugin-hrm-form/src/maskIdentifiers/index.ts +++ b/plugin-hrm-form/src/maskIdentifiers/index.ts @@ -52,7 +52,7 @@ export const maskChannelStringsWithIdentifiers = (channelType: TaskChannelDefini TaskListItem.firstLine = 'MaskIdentifiers'; if (channelType.name === DefaultTaskChannels.ChatSms.name) { // The unmasked service user number appears in the last message info on SMS if they sent the last message - // Lets replace it with a version that doesn't include the sender, regardless of who s + // Let's replace it with a version that doesn't include the sender's identity, regardless of who sent the last message. TaskListItem.secondLine = task => { const taskHelper = new TaskHelper(task); const conversationState = StateHelper.getConversationStateForTask(task); From 2399a624e5fa2ec9657bcb3a91914ee862e73712 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Fri, 6 Feb 2026 11:54:01 +0000 Subject: [PATCH 6/6] Fall back to better secondLine with missing last message --- plugin-hrm-form/src/maskIdentifiers/index.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugin-hrm-form/src/maskIdentifiers/index.ts b/plugin-hrm-form/src/maskIdentifiers/index.ts index 81b5c1dd7d..bf465d40d6 100644 --- a/plugin-hrm-form/src/maskIdentifiers/index.ts +++ b/plugin-hrm-form/src/maskIdentifiers/index.ts @@ -60,11 +60,14 @@ export const maskChannelStringsWithIdentifiers = (channelType: TaskChannelDefini return taskHelper.durationSinceUpdate; } const conversationHelper = new ConversationHelper(conversationState); + if (!conversationHelper.lastMessage) { + return taskHelper.durationSinceUpdate; + } return `${taskHelper.durationSinceUpdate} | ${ - conversationHelper.lastMessage?.isFromMe - ? conversationHelper.lastMessage?.authorName - : strings['MaskIdentifiers'] ?? '-' - }: ${conversationHelper.lastMessage?.source.body ?? ''}`; + conversationHelper.lastMessage.isFromMe + ? conversationHelper.lastMessage.authorName + : strings['MaskIdentifiers'] ?? 'XXXXXX' + }: ${conversationHelper.lastMessage.source.body ?? ''}`; }; } // Task panel during an active call