diff --git a/.github/actions/install-flex-plugin/action.yml b/.github/actions/install-flex-plugin/action.yml index ae072815e4..afaf320b8f 100644 --- a/.github/actions/install-flex-plugin/action.yml +++ b/.github/actions/install-flex-plugin/action.yml @@ -23,7 +23,7 @@ runs: using: "composite" steps: - name: Install the Twilio CLI and plugins - run: npm install -g twilio-cli && twilio plugins:install @twilio-labs/plugin-flex@7.0.0 + run: npm install -g twilio-cli && twilio plugins:install @twilio-labs/plugin-flex@7.1.2 shell: bash - name: Install plugin-hrm-form Packages run: npm ci diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index defb6efff0..1846dc0e3c 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -17,23 +17,19 @@ name: End to End Testing CI # Action on: [pull_request, workflow_dispatch] concurrency: e2e -# A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on + e2e_test: + name: E2E tests runs-on: ubuntu-latest - # Steps represent a sequence of tasks that will be executed as part of the job steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - name: Checkout Branch uses: actions/checkout@v6 - name: Use Node.js uses: actions/setup-node@v6 with: - node-version: '20.x' # some twilio dev deps still complain about node 22 :-( + node-version: '22.x' - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v5 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/e2e-tests/package.json b/e2e-tests/package.json index 9e2dd48f02..d80cfb9558 100644 --- a/e2e-tests/package.json +++ b/e2e-tests/package.json @@ -9,9 +9,9 @@ "test": "npx playwright test --workers 1", "test:ui": "npx playwright test --workers 1 --config ui-tests/playwright.ui-test.config.ts", "test:local": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true npm run test", - "test:local:debug": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true npm run test -- --headed --debug --retries 0 caselist.spec.ts", + "test:local:debug": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true npm run test -- --headed --debug --retries 0 offline", "test:development:as": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=development HL=as SKIP_DATA_UPDATE=true npm run test", - "test:development:as:debug": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=development HL=as SKIP_DATA_UPDATE=true npm run test -- --headed --retries 0 login", + "test:development:as:debug": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=development HL=as SKIP_DATA_UPDATE=true npm run test -- --headed --retries 0", "test:development:e2e": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=development HL=e2e npm run test", "test:development:e2e:local": "cross-env LOAD_SSM_CONFIG=true HL_ENV=development HL=e2e npm run test -- --headed", "test:development:e2e:debug": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=development HL=e2e npm run test -- --headed --debug --retries 0 login", diff --git a/lambdas/account-scoped/src/channelCapture/channelCaptureHandlers.ts b/lambdas/account-scoped/src/channelCapture/channelCaptureHandlers.ts index a12dc1d3e3..24cd8a8acd 100644 --- a/lambdas/account-scoped/src/channelCapture/channelCaptureHandlers.ts +++ b/lambdas/account-scoped/src/channelCapture/channelCaptureHandlers.ts @@ -35,12 +35,10 @@ const releaseTypes = ['triggerStudioFlow', 'postSurveyComplete'] as const; export type ReleaseTypes = (typeof releaseTypes)[number]; export type CapturedChannelAttributes = { - enableLexV2: boolean; userId: string; environment: string; helplineCode: string; botLanguage: string; - botLanguageV1: string; botSuffix: string; controlTaskSid: string; releaseType: ReleaseTypes; @@ -93,12 +91,10 @@ const updateChannelWithCapture = async ( attributes: CapturedChannelAttributes, ) => { const { - enableLexV2, userId, environment, helplineCode, botLanguage, - botLanguageV1, botSuffix, controlTaskSid, chatbotCallbackWebhookSid, @@ -125,12 +121,10 @@ const updateChannelWithCapture = async ( participantSid: userIdentityOrParticipantId, // All of this can be passed as url params to the webhook instead capturedChannelAttributes: { - enableLexV2, userId, environment, helplineCode, botLanguage, - botLanguageV1, botSuffix, controlTaskSid, chatbotCallbackWebhookSid, @@ -152,11 +146,9 @@ const updateChannelWithCapture = async ( type CaptureChannelOptions = { accountSid: AccountSID; - enableLexV2: boolean; environment: string; helplineCode: string; botLanguage: string; - botLanguageV1: string; botSuffix: string; inputText: string; userId: string; @@ -185,13 +177,11 @@ const triggerWithUserMessage = async ( channelOrConversation: ChannelInstance | ConversationInstance, { accountSid, - enableLexV2, userId, environment, helplineCode, botSuffix, botLanguage, - botLanguageV1, inputText, controlTaskSid, releaseType, @@ -205,16 +195,12 @@ const triggerWithUserMessage = async ( ) => { // trigger Lex first, in order to reduce the time between the creating the webhook and sending the message const lexResult = await LexClient.postText({ - enableLexV2, - postTextParams: { - botLanguage, - botLanguageV1, - botSuffix, - environment, - helplineCode, - inputText, - sessionId: userId, - }, + botLanguage, + botSuffix, + environment, + helplineCode, + inputText, + sessionId: userId, }); let webhook; @@ -235,12 +221,10 @@ const triggerWithUserMessage = async ( } await updateChannelWithCapture(channelOrConversation, { - enableLexV2, userId, environment, helplineCode, botLanguage, - botLanguageV1, botSuffix, controlTaskSid, releaseType, @@ -261,17 +245,13 @@ const triggerWithUserMessage = async ( throw lexResult.error; } - const { lexResponse, lexVersion } = lexResult.data; + const { lexResponse } = lexResult.data; let messages: string[] = []; - if (lexVersion === 'v1') { - messages.push(lexResponse.message || ''); - } else if (lexVersion === 'v2') { - if (!lexResponse.messages) { - throw new Error('Lex response does not includes messages'); - } - messages = messages.concat(lexResponse.messages.map(m => m.content || '')); + if (!lexResponse.messages) { + throw new Error('Lex response does not includes messages'); } + messages = messages.concat(lexResponse.messages.map(m => m.content || '')); for (const message of messages) { if (isConversation) { @@ -299,12 +279,10 @@ const triggerWithNextMessage = async ( channelOrConversation: ChannelInstance | ConversationInstance, { accountSid, - enableLexV2, userId, environment, helplineCode, botLanguage, - botLanguageV1, botSuffix, inputText, controlTaskSid, @@ -348,12 +326,10 @@ const triggerWithNextMessage = async ( // const updated = await updateChannelWithCapture(channelOrConversation, { - enableLexV2, userId, environment, helplineCode, botLanguage, - botLanguageV1, botSuffix, controlTaskSid, releaseType, @@ -572,17 +548,12 @@ export const handleChannelCapture = async ( ? await twilioClient.conversations.v1.conversations(conversationSid).fetch() : await twilioClient.chat.v2.services(chatServiceSid).channels(channelSid!).fetch(); - const serviceConfig = await twilioClient.flexApi.v1.configuration.get().fetch(); - const enableLexV2 = Boolean(serviceConfig.attributes.feature_flags.enable_lex_v2); - const options: CaptureChannelOptions = { accountSid, - enableLexV2, environment: environment.toLowerCase(), helplineCode: helplineCode.toLowerCase(), botSuffix, botLanguage: languageSanitized.toLowerCase(), - botLanguageV1: languageSanitized, releaseType, studioFlowSid, memoryAttribute, diff --git a/lambdas/account-scoped/src/channelCapture/chatbotCallback.ts b/lambdas/account-scoped/src/channelCapture/chatbotCallback.ts index 919c737064..8778b989df 100644 --- a/lambdas/account-scoped/src/channelCapture/chatbotCallback.ts +++ b/lambdas/account-scoped/src/channelCapture/chatbotCallback.ts @@ -121,27 +121,16 @@ export const handleChatbotCallback: AccountScopedHandler = async ( const capturedChannelAttributes = channelAttributes.capturedChannelAttributes as CapturedChannelAttributes; - const { + const { botLanguage, botSuffix, environment, helplineCode, userId } = + capturedChannelAttributes; + + const lexResult = await LexClient.postText({ botLanguage, - botLanguageV1, botSuffix, - enableLexV2, environment, helplineCode, - userId, - } = capturedChannelAttributes; - - const lexResult = await LexClient.postText({ - enableLexV2, - postTextParams: { - botLanguage, - botLanguageV1, - botSuffix, - environment, - helplineCode, - inputText: Body, - sessionId: userId, - }, + inputText: Body, + sessionId: userId, }); if (isErr(lexResult)) { @@ -160,27 +149,22 @@ export const handleChatbotCallback: AccountScopedHandler = async ( const twilioWorkspaceSid = await getWorkspaceSid(accountSid); - const { lexResponse, lexVersion } = lexResult.data; + const { lexResponse } = lexResult.data; // If the session ended, we should unlock the channel to continue the Studio Flow - if (LexClient.isEndOfDialog({ enableLexV2, lexResponse })) { + if (LexClient.isEndOfDialog(lexResponse)) { await chatbotCallbackCleanup({ accountSid, twilioClient, conversation, channel, channelAttributes, - memory: LexClient.getBotMemory({ enableLexV2, lexResponse }), + memory: LexClient.getBotMemory({ lexResponse }), twilioWorkspaceSid, }); } // TODO: unify with functions/channelCapture/channelCaptureHandlers.ts - let messages: string[] = []; - if (lexVersion === 'v1') { - messages.push(lexResponse.message || ''); - } else if (lexVersion === 'v2' && lexResponse.messages) { - messages = messages.concat(lexResponse.messages.map(m => m.content || '')); - } + const messages = (lexResponse.messages || []).map(m => m.content || ''); // TODO: unify with functions/channelCapture/channelCaptureHandlers.ts for (const message of messages) { diff --git a/lambdas/account-scoped/src/channelCapture/chatbotCallbackCleanup.ts b/lambdas/account-scoped/src/channelCapture/chatbotCallbackCleanup.ts index ab45fb68bf..e2b2ce790c 100644 --- a/lambdas/account-scoped/src/channelCapture/chatbotCallbackCleanup.ts +++ b/lambdas/account-scoped/src/channelCapture/chatbotCallbackCleanup.ts @@ -103,15 +103,8 @@ export const chatbotCallbackCleanup = async ({ } }; - const { - botLanguage, - botLanguageV1, - botSuffix, - enableLexV2, - environment, - helplineCode, - userId, - } = capturedChannelAttributes || {}; + const { botLanguage, botSuffix, environment, helplineCode, userId } = + capturedChannelAttributes || {}; const shouldDeleteSession = botLanguage && botSuffix && environment && helplineCode && userId; @@ -120,15 +113,11 @@ export const chatbotCallbackCleanup = async ({ // Delete Lex session. This is not really needed as the session will expire, but that depends on the config of Lex. shouldDeleteSession && LexClient.deleteSession({ - enableLexV2, - deleteSessionParams: { - botLanguage, - botLanguageV1, - botSuffix, - environment, - helplineCode, - sessionId: userId, - }, + botLanguage, + botSuffix, + environment, + helplineCode, + sessionId: userId, }), // Update channel attributes (remove channelCapturedByBot and add memory) updateChannelOrConversationAttributes(releasedChannelAttributes), diff --git a/lambdas/account-scoped/src/channelCapture/lexClient.ts b/lambdas/account-scoped/src/channelCapture/lexClient.ts index 1aaf7ae15b..65cb671ba1 100644 --- a/lambdas/account-scoped/src/channelCapture/lexClient.ts +++ b/lambdas/account-scoped/src/channelCapture/lexClient.ts @@ -13,17 +13,10 @@ * 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 { - LexRuntimeServiceClient, - PostTextCommand, - DeleteSessionCommand, - PostTextResponse, -} from '@aws-sdk/client-lex-runtime-service'; import { LexRuntimeV2Client, RecognizeTextCommand, DeleteSessionCommand as DeleteSessionCommandV2, - Slot, RecognizeTextResponse, } from '@aws-sdk/client-lex-runtime-v2'; import { isErr, newErr, newOk } from '../Result'; @@ -45,114 +38,7 @@ type DeleteSessionParams = { sessionId: string; }; -const getBotNameV1 = ({ - botLanguage, - botSuffix, - environment, - helplineCode, -}: { - environment: string; - helplineCode: string; - botLanguage: string; - botSuffix: string; -}) => { - // Remove numbers as they are not supported in Lex v1 - const sanitizedHelplineCode = helplineCode.replaceAll(/[0-9]/gi, ''); - return { - botName: `${environment}_${sanitizedHelplineCode}_${botLanguage}_${botSuffix}`, - botAlias: 'latest', // Assume we always use the latest published version - }; -}; - -const postTextV1 = async ({ - botLanguageV1: botLanguage, - botSuffix, - environment, - helplineCode, - inputText, - sessionId, -}: PostTextParams & { botLanguageV1: string }) => { - try { - const { botAlias, botName } = getBotNameV1({ - botLanguage, - botSuffix, - environment, - helplineCode, - }); - - const lexClient = new LexRuntimeServiceClient({}); - - const lexResponse = await lexClient.send( - new PostTextCommand({ - botName, - botAlias, - inputText, - userId: sessionId, - }), - ); - - return newOk({ lexVersion: 'v1', lexResponse } as const); - } catch (error) { - return newErr({ - message: error instanceof Error ? error.message : String(error), - error, - }); - } -}; - -const isEndOfDialogV1 = (dialogState: string | undefined) => - dialogState === 'Fulfilled' || dialogState === 'Failed'; - -const deleteSessionV1 = async ({ - botLanguageV1: botLanguage, - botSuffix, - environment, - helplineCode, - sessionId, -}: DeleteSessionParams & { botLanguageV1: string }) => { - try { - const { botAlias, botName } = getBotNameV1({ - botLanguage, - botSuffix, - environment, - helplineCode, - }); - - const lexClient = new LexRuntimeServiceClient({}); - - const lexResponse = await lexClient.send( - new DeleteSessionCommand({ - botName, - botAlias, - userId: sessionId, - }), - ); - - return newOk({ lexVersion: 'v1', lexResponse } as const); - } catch (error) { - return newErr({ - message: error instanceof Error ? error.message : String(error), - error, - }); - } -}; - -const LexV1 = { - postText: postTextV1, - isEndOfDialog: isEndOfDialogV1, - getBotName: getBotNameV1, - deleteSession: deleteSessionV1, -}; - -export type LexV2Memory = { - [q: string]: { - originalValue: string | number; - interpretedValue: string | number; - resolvedValues: (string | number)[]; - }; -}; - -const getBotNameV2 = async ({ +const getBotName = async ({ botLanguage, botSuffix, environment, @@ -188,7 +74,7 @@ const getBotNameV2 = async ({ } }; -const postTextV2 = async ({ +const postText = async ({ botLanguage, botSuffix, environment, @@ -197,7 +83,7 @@ const postTextV2 = async ({ sessionId, }: PostTextParams & { botLanguage: string }) => { try { - const result = await getBotNameV2({ + const result = await getBotName({ botLanguage, botSuffix, environment, @@ -212,6 +98,10 @@ const postTextV2 = async ({ const lexClient = new LexRuntimeV2Client({}); + console.debug( + `Sending message to bot ${environment}_${helplineCode}_${botLanguage}_${botSuffix} bot id: ${botId}, bot alias: ${botAliasId}, localeId: ${localeId}`, + ); + const lexResponse = await lexClient.send( new RecognizeTextCommand({ botAliasId, @@ -231,9 +121,10 @@ const postTextV2 = async ({ } }; -const isEndOfDialogV2 = (dialogState: string | undefined) => dialogState === 'Close'; +const isEndOfDialog = (lexResponse: RecognizeTextResponse) => + lexResponse.sessionState?.dialogAction?.type === 'Close'; -const deleteSessionV2 = async ({ +const deleteSession = async ({ botLanguage, botSuffix, environment, @@ -241,7 +132,7 @@ const deleteSessionV2 = async ({ sessionId, }: DeleteSessionParams & { botLanguage: string }) => { try { - const result = await getBotNameV2({ + const result = await getBotName({ botLanguage, botSuffix, environment, @@ -274,121 +165,21 @@ const deleteSessionV2 = async ({ } }; -const convertV2ToV1Memory = ( - memory: - | { - [key: string]: Slot; - } - | undefined, -): LexMemory => { - if (!memory) { +const getBotMemory = ({ lexResponse }: { lexResponse: RecognizeTextResponse }) => { + const { slots } = lexResponse.sessionState?.intent || {}; + if (!slots) { return {}; } - return Object.entries(memory).reduce( + return Object.entries(slots).reduce( (accum, [q, { value }]) => ({ ...accum, [q]: value?.interpretedValue || '' }), {} as LexMemory, ); }; -const LexV2 = { - postText: postTextV2, - isEndOfDialog: isEndOfDialogV2, - deleteSession: deleteSessionV2, - getBotName: getBotNameV2, - convertV2ToV1Memory, -}; - -const postText = async ({ - enableLexV2, - postTextParams, -}: { - enableLexV2: boolean; - postTextParams: PostTextParams & { botLanguage: string; botLanguageV1: string }; -}) => { - try { - if (enableLexV2) { - const res = await LexV2.postText(postTextParams); - return res; - } - - const res = await LexV1.postText(postTextParams); - return res; - } catch (error) { - return newErr({ - message: error instanceof Error ? error.message : String(error), - error: error instanceof Error ? error : new Error(String(error)), - }); - } -}; - -const deleteSession = async ({ - enableLexV2, - deleteSessionParams, -}: { - enableLexV2: boolean; - deleteSessionParams: DeleteSessionParams & { - botLanguage: string; - botLanguageV1: string; - }; -}) => { - try { - if (enableLexV2) { - return await LexV2.deleteSession(deleteSessionParams); - } - - return await LexV1.deleteSession(deleteSessionParams); - } catch (error) { - return newErr({ - message: error instanceof Error ? error.message : String(error), - error: error instanceof Error ? error : new Error(String(error)), - }); - } -}; - -const isEndOfDialog = ({ - enableLexV2, - lexResponse, -}: - | { - enableLexV2: false; - lexResponse: PostTextResponse; - } - | { - enableLexV2: true; - lexResponse: RecognizeTextResponse; - }) => { - if (enableLexV2) { - return LexV2.isEndOfDialog(lexResponse.sessionState?.dialogAction?.type); - } - - return LexV1.isEndOfDialog(lexResponse.dialogState); -}; - -const getBotMemory = ({ - enableLexV2, - lexResponse, -}: - | { - enableLexV2: false; - lexResponse: PostTextResponse; - } - | { - enableLexV2: true; - lexResponse: RecognizeTextResponse; - }) => { - if (enableLexV2) { - return LexV2.convertV2ToV1Memory(lexResponse.sessionState?.intent?.slots); - } - - return lexResponse.slots || {}; -}; - -const LexClient = { +export const LexClient = { postText, deleteSession, isEndOfDialog, getBotMemory, }; - -export { LexV1, LexV2, LexClient }; diff --git a/scripts/package-lock.json b/scripts/package-lock.json index 62ba23653b..3e7e30ffe2 100644 --- a/scripts/package-lock.json +++ b/scripts/package-lock.json @@ -83,7 +83,7 @@ "version": "1.0.0", "license": "AGPL", "dependencies": { - "@babel/runtime": "^7.28.4", + "@babel/runtime": "^7.28.6", "lodash": "^4.17.21" }, "devDependencies": { @@ -8993,7 +8993,7 @@ "requires": { "@babel/preset-env": "^7.16.5", "@babel/preset-typescript": "^7.16.5", - "@babel/runtime": "^7.28.4", + "@babel/runtime": "^7.28.6", "@types/jest": "^27.0.3", "@types/lodash": "^4.14.182", "@types/node": "^18.16.2", diff --git a/twilio-iac/helplines/e2e/common.hcl b/twilio-iac/helplines/e2e/common.hcl index a0a48da0c5..2b20711115 100644 --- a/twilio-iac/helplines/e2e/common.hcl +++ b/twilio-iac/helplines/e2e/common.hcl @@ -17,7 +17,11 @@ locals { lex_bot_languages = { - en : ["pre_survey"] + + } + + lex_v2_bot_languages = { + en_US : ["pre_survey"] } diff --git a/twilio-iac/helplines/e2e/development.hcl b/twilio-iac/helplines/e2e/development.hcl index 1539b06380..0b80490921 100644 --- a/twilio-iac/helplines/e2e/development.hcl +++ b/twilio-iac/helplines/e2e/development.hcl @@ -7,14 +7,14 @@ locals { local_config = { enable_external_recordings = true permission_config = "e2e" - custom_task_routing_filter_expression = "helpline IN ['Childline', ''] OR channelType =='web' OR isContactlessTask == true" + custom_task_routing_filter_expression = "*(helpline IN ['Childline', ''] OR channelType =='web') AND isContactlessTask != true" flow_vars = { service_sid = "ZS43ea9fdb2e1901c2fc23b4654b285202" environment_sid = "ZE0241494e654e208f715b4d9612171dc0" capture_channel_with_bot_function_sid = "ZH774135cb0184df6c39c6378f1598cd09" chatbot_callback_cleanup_function_sid = "ZH25485bb64766247dc9102fb9a6532eb8" send_message_janitor_function_sid = "ZH1590b1fcafd0933568a22235adec994b" - bot_language = "en" + bot_language = "en-US" widget_from = "E2E" chat_blocked_message = "Sorry, you're not able to contact E2E from this device or account" error_message = "There has been an error with your message, please try writing us again." 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'" diff --git a/twilio-iac/stages/lex/.terraform.lock.hcl b/twilio-iac/stages/lex/.terraform.lock.hcl index 00e965ec71..4874dc39f4 100644 --- a/twilio-iac/stages/lex/.terraform.lock.hcl +++ b/twilio-iac/stages/lex/.terraform.lock.hcl @@ -1,26 +1,86 @@ # This file is maintained automatically by "terraform init". # Manual edits may be lost in future updates. +provider "registry.terraform.io/datadog/datadog" { + version = "3.46.0" + constraints = "3.46.0" + hashes = [ + "h1:GlDTNVDDyxHICBwJnabjIRe4Yts1SJMQ7NV467KaRr4=", + "zh:14d7b6f2641107111c7b7c021c55db320c44acfb6bf6857359ec4780e2e70870", + "zh:192ebc32b08a38657d7acfff0fb6cbd0e8d8066e207c3f08929966b7e37fd3a4", + "zh:1b51b6ceb80ec90dc4830c7f0c4d7ec5d4315345942d498104bbb01ef7af0392", + "zh:24c5044a79eef22b0876aa75d23fe530a63923a3607c1e52ca4f994e18b054de", + "zh:2c85b675374a599b0fa598205dd3a01bfc5773adc960f3c120417e92417eb34f", + "zh:2ef64060f9378953cf876c1c03fa6b9dde4d34e440548438d261d4d5658b121d", + "zh:3000885923b118d5b2c3b5df2030267f9d88d8cf6cf125ee5ba2906e822bae27", + "zh:3e2101e4fe45f969f006dabb4e8c3798ee212f594e3edc0a0ce093f89191d36b", + "zh:6f778f330a207927f3f0b6fe0d0ed75fa8101233c3e37e4a8d6aed96e39e969a", + "zh:b0afb28a9d176803a668ae07247de098c4a5b9b060feb8c19fcb7a6087cc8d58", + "zh:b889103adae1f962cfca4003893e12364640e89449396a6df3baaef2d2bd6a42", + "zh:cd9bbff5cc7220232520904e977c5b4dafc735dbdcb142f292d67cbdb58dca4b", + "zh:d247fbac1d81a26d0a97428da6f1bbc77a0cc5c1532701c3a4be75221d318ed8", + "zh:ff50be8d703ff49a1548b0061338058c712d21353e38c4aeecdca934a371607d", + ] +} + provider "registry.terraform.io/hashicorp/aws" { - version = "4.67.0" + version = "5.84.0" + constraints = "5.84.0" hashes = [ - "h1:DWVybabEz2gCyQkRM9zop1SKTG1tkH7+ruekC9KQM5w=", - "h1:dCRc4GqsyfqHEMjgtlM1EympBcgTmcTkWaJmtd91+KA=", - "zh:0843017ecc24385f2b45f2c5fce79dc25b258e50d516877b3affee3bef34f060", - "zh:19876066cfa60de91834ec569a6448dab8c2518b8a71b5ca870b2444febddac6", - "zh:24995686b2ad88c1ffaa242e36eee791fc6070e6144f418048c4ce24d0ba5183", - "zh:4a002990b9f4d6d225d82cb2fb8805789ffef791999ee5d9cb1fef579aeff8f1", - "zh:559a2b5ace06b878c6de3ecf19b94fbae3512562f7a51e930674b16c2f606e29", - "zh:6a07da13b86b9753b95d4d8218f6dae874cf34699bca1470d6effbb4dee7f4b7", - "zh:768b3bfd126c3b77dc975c7c0e5db3207e4f9997cf41aa3385c63206242ba043", - "zh:7be5177e698d4b547083cc738b977742d70ed68487ce6f49ecd0c94dbf9d1362", - "zh:8b562a818915fb0d85959257095251a05c76f3467caa3ba95c583ba5fe043f9b", + "h1:dwpeFUdcxgXVAc0JSqO57xf0/r2qOBLPloombCQWFz8=", + "zh:078f77438aba6ec8bf9154b7d223e5c71c48d805d6cd3bcf9db0cc1e82668ac3", + "zh:1f6591ff96be00501e71b792ed3a5a14b21ff03afec9a1c4a3fd9300e6e5b674", + "zh:2ab694e022e81dd74485351c5836148a842ed71cf640664c9d871cb517b09602", + "zh:33c8ccb6e3dc496e828a7572dd981366c6271075c1189f249b9b5236361d7eff", + "zh:6f31068ebad1d627e421c72ccdaafe678c53600ca73714e977bf45ff43ae5d17", + "zh:7488623dccfb639347cae66f9001d39cf06b92e8081975235a1ac3a0ac3f44aa", + "zh:7f042b78b9690a8725c95b91a70fc8e264011b836605bcc342ac297b9ea3937d", + "zh:88b56ac6c7209dc0a775b79975a371918f3aed8f015c37d5899f31deff37c61a", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:9c385d03a958b54e2afd5279cd8c7cbdd2d6ca5c7d6a333e61092331f38af7cf", - "zh:b3ca45f2821a89af417787df8289cb4314b273d29555ad3b2a5ab98bb4816b3b", - "zh:da3c317f1db2469615ab40aa6baba63b5643bae7110ff855277a1fb9d8eb4f2c", - "zh:dc6430622a8dc5cdab359a8704aec81d3825ea1d305bbb3bbd032b1c6adfae0c", - "zh:fac0d2ddeadf9ec53da87922f666e1e73a603a611c57bcbc4b86ac2821619b1d", + "zh:a1979ba840d704af0932f8de5f541cbb4caa9b6bbd25ed552a24e6772175ba07", + "zh:b058c0533dae580e69d1adbc1f69e6a80632374abfc10e8634d06187a108e87b", + "zh:c88610af9cf957f8dcf4382e0c9ca566ef10e3290f5de01d4d90b2d81b078aa8", + "zh:e9562c055a2247d0c287772b55abef468c79f8d66a74780fe1c5e5dae1a284a9", + "zh:f7a7c71d28441d925a25c08c4485c015b2d9f0338bc9707443e91ff8e161d3d9", + "zh:fee533e81976d0900aa6fa443dc54ef171cbd901847f28a6e8edb1d161fa6fde", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.4" + hashes = [ + "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", + "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", + "zh:7b9c7b16f118fbc2b05a983817b8ce2f86df125857966ad356353baf4bff5c0a", + "zh:85e33ab43e0e1726e5f97a874b8e24820b6565ff8076523cc2922ba671492991", + "zh:9d32ac3619cfc93eb3c4f423492a8e0f79db05fec58e449dee9b2d5873d5f69f", + "zh:9e15c3c9dd8e0d1e3731841d44c34571b6c97f5b95e8296a45318b94e5287a6e", + "zh:b4c2ab35d1b7696c30b64bf2c0f3a62329107bd1a9121ce70683dec58af19615", + "zh:c43723e8cc65bcdf5e0c92581dcbbdcbdcf18b8d2037406a5f2033b1e22de442", + "zh:ceb5495d9c31bfb299d246ab333f08c7fb0d67a4f82681fbf47f2a21c3e11ab5", + "zh:e171026b3659305c558d9804062762d168f50ba02b88b231d20ec99578a6233f", + "zh:ed0fe2acdb61330b01841fa790be00ec6beaac91d41f311fb8254f74eb6a711f", + ] +} + +provider "registry.terraform.io/hashicorp/time" { + version = "0.13.1" + hashes = [ + "h1:+W+DMrVoVnoXo3f3M4W+OpZbkCrUn6PnqDF33D2Cuf0=", + "zh:02cb9aab1002f0f2a94a4f85acec8893297dc75915f7404c165983f720a54b74", + "zh:04429b2b31a492d19e5ecf999b116d396dac0b24bba0d0fb19ecaefe193fdb8f", + "zh:26f8e51bb7c275c404ba6028c1b530312066009194db721a8427a7bc5cdbc83a", + "zh:772ff8dbdbef968651ab3ae76d04afd355c32f8a868d03244db3f8496e462690", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:898db5d2b6bd6ca5457dccb52eedbc7c5b1a71e4a4658381bcbb38cedbbda328", + "zh:8de913bf09a3fa7bedc29fec18c47c571d0c7a3d0644322c46f3aa648cf30cd8", + "zh:9402102c86a87bdfe7e501ffbb9c685c32bbcefcfcf897fd7d53df414c36877b", + "zh:b18b9bb1726bb8cfbefc0a29cf3657c82578001f514bcf4c079839b6776c47f0", + "zh:b9d31fdc4faecb909d7c5ce41d2479dd0536862a963df434be4b16e8e4edc94d", + "zh:c951e9f39cca3446c060bd63933ebb89cedde9523904813973fbc3d11863ba75", + "zh:e5b773c0d07e962291be0e9b413c7a22c044b8c7b58c76e8aa91d1659990dfb5", ] } diff --git a/twilio-iac/stages/lex/terragrunt.hcl b/twilio-iac/stages/lex/terragrunt.hcl index 27e393ebbb..4dcc1b7b24 100644 --- a/twilio-iac/stages/lex/terragrunt.hcl +++ b/twilio-iac/stages/lex/terragrunt.hcl @@ -48,7 +48,6 @@ locals { environment = include.root.locals.config.environment lex_bot_languages = include.root.locals.config.lex_bot_languages lex_v2_bot_languages = include.root.locals.config.lex_v2_bot_languages - enable_lex_v2 = include.root.locals.config.enable_lex_v2 lex_bots = tomap({ for language, bots in local.lex_bot_languages : @@ -112,7 +111,7 @@ locals { ) }) - lex_v2_bots = local.enable_lex_v2 ? { + lex_v2_bots = { for language, bots in local.lex_v2_bot_languages : language => merge([ for bot in bots : @@ -126,11 +125,11 @@ locals { "/app/twilio-iac/helplines/configs/lex_v2/${substr(language, 0, 2)}/bots/${bot}.json" )) ]...) - } : null + } //leaving for debugging purposes //print2 = run_cmd("echo", jsonencode(local.lex_v2_bots)) /* - lex_v2_slot_types_names = local.enable_lex_v2 ? tomap({ + lex_v2_slot_types_names = tomap({ for language, bots in local.lex_v2_bot_languages : language => distinct( flatten([ @@ -143,10 +142,10 @@ locals { ] ]) ) - }) : {} + }) */ - lex_v2_slot_types_names = local.enable_lex_v2 ? tomap({ + lex_v2_slot_types_names = tomap({ for language, bots in local.lex_v2_bot_languages : language => distinct( flatten([ @@ -161,9 +160,9 @@ locals { ] ]) ) - }) : {} + }) - lex_v2_slot_types = local.enable_lex_v2 ? { + lex_v2_slot_types = { for language, bots in local.lex_v2_bot_languages : language => [ for slot_type in local.lex_v2_slot_types_names[language] : { @@ -182,13 +181,13 @@ locals { } if !startswith(slot_type.name, "AMAZON") ] - } : null + } //leaving for debugging purposes //print6 = run_cmd("echo", jsonencode(local.lex_v2_slot_types)) /* - lex_v2_intent_names = local.enable_lex_v2 ? tomap({ + lex_v2_intent_names = tomap({ for language, bots in local.lex_v2_bot_languages : language => distinct( flatten([ @@ -201,9 +200,9 @@ locals { ] ]) ) - }) : {} + }) */ - lex_v2_intent_names = local.enable_lex_v2 ? tomap({ + lex_v2_intent_names = tomap({ for language, bots in local.lex_v2_bot_languages : language => distinct( flatten([ @@ -216,9 +215,9 @@ locals { ] ]) ) - }) : {} + }) - lex_v2_intents = local.enable_lex_v2 ? { + lex_v2_intents = { for language, bots in local.lex_v2_bot_languages : language => [ for intent in local.lex_v2_intent_names[language] : { @@ -236,13 +235,13 @@ locals { ) } ] - } : null + } //leaving for debugging purposes //print8 = run_cmd("echo", jsonencode(local.lex_v2_intents)) /* -lex_v2_slot_names = local.enable_lex_v2 ? tomap({ +lex_v2_slot_names = tomap({ for language, bots in local.lex_v2_bot_languages : language => distinct( flatten([ @@ -255,9 +254,9 @@ lex_v2_slot_names = local.enable_lex_v2 ? tomap({ ] ]) ) - }) : {} + }) */ - lex_v2_slot_names = local.enable_lex_v2 ? tomap({ + lex_v2_slot_names = tomap({ for language, bots in local.lex_v2_bot_languages : language => distinct( flatten([ @@ -272,9 +271,9 @@ lex_v2_slot_names = local.enable_lex_v2 ? tomap({ ] ]) ) - }) : {} + }) - lex_v2_slots = local.enable_lex_v2 ? { + lex_v2_slots = { for language, bots in local.lex_v2_bot_languages : language => [ for slot in local.lex_v2_slot_names[language] : { @@ -292,7 +291,7 @@ lex_v2_slot_names = local.enable_lex_v2 ? tomap({ ) } ] -} : null +} //leaving for debugging purposes //print9 = run_cmd("echo", jsonencode(local.lex_v2_slots)) diff --git a/twilio-iac/terraform-modules/lex/v2/main.tf b/twilio-iac/terraform-modules/lex/v2/main.tf index 9299b5042f..02ec8c7f9a 100644 --- a/twilio-iac/terraform-modules/lex/v2/main.tf +++ b/twilio-iac/terraform-modules/lex/v2/main.tf @@ -42,7 +42,7 @@ data "aws_iam_role" "role-lex-v2-bot" { resource "aws_lexv2models_bot" "this" { provider = aws.hl-region for_each = var.lex_v2_bots - name = replace("${local.name_prefix}_${each.key}", "2", "") + name = "${local.name_prefix}_${each.key}" description = each.value.description data_privacy { child_directed = each.value.child_directed @@ -409,15 +409,7 @@ resource "null_resource" "update_slots" { AWS_REGION = var.helpline_region } command = <