From 9baa4aae0a458a53399d98e9d04865c30e77b9bb Mon Sep 17 00:00:00 2001 From: Abhishek Patil Date: Thu, 29 Aug 2024 10:42:25 -0400 Subject: [PATCH] Update to version v6.1.0 --- .nightswatch/functional/conftest.py | 18 +- .../helpers/cfn_parameter_fetcher.py | 37 + .../functional/helpers/cloud_watch_client.py | 4 +- .../functional/helpers/s3_client.py | 60 +- .../helpers/website_model/edit_page.py | 15 +- .../helpers/website_model/menu_nav.py | 9 +- .../helpers/website_model/settings_page.py | 98 +- .nightswatch/functional/test_1_login.py | 10 + .../functional/test_knowledge_base.py | 59 +- .nightswatch/functional/test_llm.py | 37 +- .nightswatch/functional/test_tuning.py | 15 +- CHANGELOG.md | 112 +- NOTICE.txt | 1683 +++++++- README.md | 36 +- SECURITY.md | 6 + deployment/run-unit-tests.sh | 3 +- source/bin/config.js | 2 +- .../aws_solutions/qnabot/cli/qnabot_cli.py | 2 +- .../qnabot/cli/qnabot_cli_helper.py | 31 +- source/cli/requirements-test.txt | 10 +- source/cli/requirements.txt | 4 +- .../tests/aws_solutions/core/test_helpers.py | 4 +- .../fixtures/cloudformation_fixtures.py | 4 +- .../qnabot/fixtures/s3_fixtures.py | 5 +- .../aws_solutions/qnabot/test_helpers.py | 11 +- source/config.json | 4 +- source/docs/Blogpost-SimpleNavigation.json | 6 +- .../README.md | 12 +- .../images/Bedrock_KB.png | Bin 0 -> 150615 bytes source/docs/Technical Information.md | 10 +- source/docs/bedrock_guardrails/README.md | 50 + .../images/content_filters.png | Bin 0 -> 217904 bytes .../images/provide_guardrail_detail.png | Bin 0 -> 141671 bytes .../images/test_guardrail.png | Bin 0 -> 188462 bytes .../images/update_settings.png | Bin 0 -> 145928 bytes .../docs/bedrock_knowledgebase_rag/README.md | 27 +- .../images/image2.png | Bin 162445 -> 155036 bytes source/docs/bot_routing/README.md | 12 +- .../bot_routing/images/botroutingconfig.png | Bin 209788 -> 70557 bytes source/docs/canvaslms_integration/README.md | 115 - source/docs/intent_slot_matching/README.md | 8 - source/docs/kendra_fallback/README.md | 3 +- source/docs/lambda_hooks/README.md | 1 + source/docs/lambda_hooks/lambda_hook_sdk.MD | 2 +- .../README.md | 1 + source/lambda/aws-sdk-layer/package-lock.json | 2025 ++-------- source/lambda/aws-sdk-layer/package.json | 4 +- .../lambda/cfn-lambda-layer/package-lock.json | 4 +- source/lambda/cfn-lambda-layer/package.json | 2 +- source/lambda/cfn/lib/PostUpgradeImport.js | 61 +- source/lambda/cfn/lib/PreUpgradeExport.js | 71 +- source/lambda/cfn/package-lock.json | 935 ++++- source/lambda/cfn/package.json | 2 +- .../cfn/test/lib/PostUpgradeImport.test.js | 6 +- .../cfn/test/lib/PreUpgradeExport.test.js | 4 +- .../common-modules-layer/package-lock.json | 416 +- .../lambda/common-modules-layer/package.json | 2 +- source/lambda/connect/package-lock.json | 4 +- source/lambda/connect/package.json | 2 +- .../es-proxy-layer/lib/bedrock/AmazonLlm.js | 2 +- .../bedrock/BedrockModelProviderPrototype.js | 7 +- .../lib/bedrock/bedrockAgents.js | 133 +- .../lib/bedrock/bedrockClient.js | 11 +- .../lib/bedrock/bedrockModels.js | 6 +- .../lambda/es-proxy-layer/lib/embeddings.js | 4 +- .../lib/fulfillment-event/getHit.js | 4 +- source/lambda/es-proxy-layer/lib/llm.js | 14 +- .../es-proxy-layer/lib/sanitizeOutput.js | 13 + .../lambda/es-proxy-layer/package-lock.json | 3044 ++++++++++++-- source/lambda/es-proxy-layer/package.json | 11 +- .../es-proxy-layer/test/bedrockAgents.test.js | 581 ++- .../es-proxy-layer/test/bedrockModels.test.js | 89 +- .../es-proxy-layer/test/llm.fixtures.js | 2 + source/lambda/es-proxy-layer/test/llm.test.js | 85 +- .../test/sanitizeOutput.test.js | 62 + source/lambda/export/index.js | 73 +- source/lambda/export/jest.config.js | 6 +- source/lambda/export/kendraSync.js | 2 +- source/lambda/export/lib/start.js | 1 + source/lambda/export/package-lock.json | 4 +- source/lambda/export/package.json | 2 +- source/lambda/export/test/index.fixtures.js | 32 +- source/lambda/export/test/index.test.js | 156 +- source/lambda/export/test/kendraSync.test.js | 26 +- source/lambda/export/test/lib/start.test.js | 2 + .../fulfillment/lib/middleware/1_parse.js | 5 +- .../fulfillment/lib/middleware/3_query.js | 6 +- .../lambda/fulfillment/lib/middleware/lex.js | 149 +- .../fulfillment/lib/middleware/lexRouter.js | 80 +- .../lib/middleware/specialtyBotRouter.js | 72 +- source/lambda/fulfillment/package-lock.json | 390 +- source/lambda/fulfillment/package.json | 2 +- .../test/lib/middleware/1_parse.fixtures.js | 12 +- .../test/lib/middleware/1_parse.test.js | 2 +- .../test/lib/middleware/3_query.test.js | 1 - .../test/lib/middleware/lex.fixtures.js | 4 - .../test/lib/middleware/lex.test.js | 101 - .../test/lib/middleware/lexRouter.fixtures.js | 13 - .../test/lib/middleware/lexRouter.test.js | 147 - .../middleware/specialtyBotRouter.fixtures.js | 17 - .../lib/middleware/specialtyBotRouter.test.js | 138 - source/lambda/genesys/package-lock.json | 4 +- source/lambda/genesys/package.json | 2 +- source/lambda/import/index.js | 166 +- source/lambda/import/package-lock.json | 225 +- source/lambda/import/package.json | 4 +- source/lambda/import/test/index.test.js | 30 +- .../js_lambda_hook_sdk/package-lock.json | 4 +- source/lambda/js_lambda_hook_sdk/package.json | 2 +- .../requirements-test.txt | 6 +- .../test/test_lambda_function.py | 4 +- .../requirements-test.txt | 6 +- .../test/test_lambda_function.py | 4 +- .../kendra-webcrawler/requirements-test.txt | 6 +- .../test/test_lambda_function.py | 5 +- source/lambda/lex-build/lib/alias.js | 26 - source/lambda/lex-build/lib/bot.js | 64 - source/lambda/lex-build/lib/delete.js | 57 - source/lambda/lex-build/lib/index.js | 9 - source/lambda/lex-build/lib/intent.js | 35 - source/lambda/lex-build/lib/intentFallback.js | 33 - source/lambda/lex-build/lib/lexv1bot.js | 104 - source/lambda/lex-build/lib/run.js | 56 - source/lambda/lex-build/lib/slot.js | 36 - source/lambda/lex-build/lib/statusv1.js | 43 - source/lambda/lex-build/lib/utterances.js | 57 - source/lambda/lex-build/lib/wait.js | 35 - source/lambda/lex-build/package-lock.json | 180 +- source/lambda/lex-build/package.json | 2 +- .../lambda/lex-build/test/lib/alias.test.js | 52 - .../lambda/lex-build/test/lib/bot.fixtures.js | 73 - source/lambda/lex-build/test/lib/bot.test.js | 135 - .../lambda/lex-build/test/lib/delete.test.js | 219 - .../lambda/lex-build/test/lib/index.test.js | 43 +- .../lambda/lex-build/test/lib/intent.test.js | 81 - .../lex-build/test/lib/intentFallback.test.js | 60 - .../lex-build/test/lib/lexv1bot.test.js | 128 - source/lambda/lex-build/test/lib/run.test.js | 92 - source/lambda/lex-build/test/lib/slot.test.js | 60 - .../lex-build/test/lib/statusv1.test.js | 138 - .../lex-build/test/lib/utterances.test.js | 82 - source/lambda/lex-build/test/lib/wait.test.js | 51 - .../lambda/lexv2-build/requirements-test.txt | 6 +- source/lambda/lexv2-build/requirements.txt | 2 +- .../lexv2-build/test/test_lambda_function.py | 5 +- source/lambda/proxy-es/package-lock.json | 4 +- source/lambda/proxy-es/package.json | 2 +- .../qnabot-common-layer/package-lock.json | 180 +- .../lambda/qnabot-common-layer/package.json | 2 +- source/lambda/s3-clean/requirements-test.txt | 8 +- source/lambda/s3-clean/requirements.txt | 2 +- .../s3-clean/test/test_lambda_function.py | 4 +- source/lambda/schema/package-lock.json | 4 +- source/lambda/schema/package.json | 2 +- source/lambda/schema/qna.js | 13 +- source/lambda/solution-helper/.coveragerc | 10 +- source/lambda/solution-helper/.gitignore | 11 - source/lambda/solution-helper/README.md | 11 + .../lambda/solution-helper/lambda_function.py | 107 +- source/lambda/solution-helper/pytest.ini | 2 + .../solution-helper/requirements-test.txt | 7 +- .../lambda/solution-helper/requirements.txt | 3 +- .../solution-helper/{ => test}/conftest.py | 3 + .../test/test_lambda_function.py | 220 + .../solution-helper/test_lambda_function.py | 121 - source/lambda/testall/index.js | 77 +- source/lambda/testall/jest.config.js | 6 +- source/lambda/testall/lib/start.js | 1 + source/lambda/testall/package-lock.json | 222 +- source/lambda/testall/package.json | 2 +- source/lambda/testall/test/index.fixtures.js | 8 +- source/lambda/testall/test/index.test.js | 158 +- source/lambda/testall/test/lib/start.test.js | 2 + source/lambda/translate/package-lock.json | 4 +- source/lambda/translate/package.json | 2 +- source/package-lock.json | 805 ++-- source/package.json | 17 +- .../dev/__tests__/masterConfig.test.js | 4 +- .../dev/__tests__/masterNoConfig.test.js | 2 +- .../dev/__tests__/mockConfigFull.json | 2 +- source/templates/dev/__tests__/mockMaster.js | 6 +- source/templates/dev/master.js | 2 +- .../examples/__snapshots__/index.test.js.snap | 3551 ++++------------- .../examples/PrairieLineTrailTour.json | 122 +- source/templates/examples/examples/index.js | 115 +- .../examples/examples/package-lock.json | 38 +- .../templates/examples/examples/package.json | 7 +- .../examples/examples/py/requirements-dev.txt | 6 +- .../examples/examples/responsebots.js | 2100 ---------- source/templates/examples/extensions/index.js | 106 +- .../package-lock.json | 4 +- .../CreateRecentTopicsResponse/package.json | 2 +- .../CustomJSHook/package-lock.json | 71 +- .../js_lambda_hooks/CustomJSHook/package.json | 7 +- .../CanvasLMSHook/CanvasLMSHelper.py | 496 --- .../CanvasLMSHook/CanvasLMSHook.py | 118 - .../CanvasLMSHook/__tests__/__init__.py | 0 .../__tests__/test_CanvasLMSHelper.py | 847 ---- .../__tests__/test_CanvasLMSHook.py | 475 --- .../py_lambda_hooks/CanvasLMSHook/pytest.ini | 2 - .../CanvasLMSHook/requirements-dev.txt | 4 - .../CanvasLMSHook/requirements.txt | 4 - .../CustomPYHook/requirements-dev.txt | 6 +- .../content/CanvasLMSIntegration.json | 357 -- .../content/CanvasLMSIntegration.txt | 4 - .../extensions/ui_imports/package-lock.json | 71 +- .../extensions/ui_imports/package.json | 7 +- source/templates/examples/index.js | 5 +- source/templates/examples/index.test.js | 7 - .../export/__snapshots__/index.test.js.snap | 538 ++- source/templates/export/bucket.js | 39 +- source/templates/export/index.js | 7 +- source/templates/export/resources.js | 242 +- source/templates/import/UpgradeAutoImport.js | 3 + .../import/__snapshots__/index.test.js.snap | 143 + source/templates/import/index.js | 3 + source/templates/import/resources.js | 63 +- source/templates/master/UpgradeAutoExport.js | 3 + .../master/__snapshots__/index.test.js.snap | 2759 +++++++++---- source/templates/master/bucket.js | 138 +- source/templates/master/cfn/index.js | 58 +- source/templates/master/examples.js | 2 +- source/templates/master/exportstack.js | 8 +- source/templates/master/importstack.js | 2 + source/templates/master/index.js | 69 +- .../master/lex-build/__tests__/start.test.js | 11 +- source/templates/master/lex-build/index.js | 114 +- source/templates/master/lex-build/start.js | 14 +- source/templates/master/lex/bot.js | 120 - source/templates/master/lex/fulfillment.js | 83 +- source/templates/master/lexv2-build/index.js | 34 +- .../master/mappings/bedrock-defaults.js | 29 +- .../templates/master/opensearch/firehose.js | 216 +- source/templates/master/opensearch/info.js | 28 + source/templates/master/opensearch/proxy.js | 29 +- source/templates/master/opensearch/updates.js | 16 +- source/templates/master/policies.json | 2 - source/templates/master/proxy-es.js | 173 +- source/templates/master/proxy-lex/index.js | 66 +- source/templates/master/proxy-lex/status.js | 15 - source/templates/master/roles.json | 16 +- .../templates/master/routes/examples/index.js | 54 + .../master/routes/jobs/export-start.vm | 2 +- source/templates/master/routes/jobs/index.js | 53 +- .../master/routes/jobs/list-export.vm | 4 +- .../master/routes/jobs/list-testall.vm | 4 +- source/templates/master/routes/jobs/list.vm | 4 +- .../master/routes/jobs/testall-start.vm | 6 +- source/templates/master/routes/root/info.vm | 1 + source/templates/master/s3-clean/index.js | 29 +- source/templates/master/s3.js | 3 + source/templates/master/schemaLambda.js | 27 + source/templates/master/settings.js | 20 +- source/templates/master/signup/index.js | 55 + .../templates/master/solution-helper/index.js | 97 +- source/templates/master/tstallstack.js | 2 + source/templates/package-lock.json | 44 +- source/templates/package.json | 2 +- source/templates/public-vpc-support/index.js | 7 +- source/templates/public/index.js | 7 +- .../__snapshots__/index.test.js.snap | 4 +- .../sagemaker-qa-summarize-llm/index.js | 4 +- .../testall/__snapshots__/index.test.js.snap | 76 + source/templates/testall/index.js | 3 + source/templates/testall/resources.js | 38 +- source/templates/util.js | 34 - source/website/js/admin.vue | 2 + .../js/components/designer/menu-testall.vue | 1 + .../js/components/designer/synckendra.vue | 1 + source/website/js/components/export.vue | 1 + .../website/js/components/genesys/index.vue | 24 +- source/website/js/components/settings.vue | 2 +- .../js/lib/store/api/actions/settings.js | 93 +- 273 files changed, 14229 insertions(+), 16093 deletions(-) rename source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/conftest.py => .nightswatch/functional/helpers/s3_client.py (54%) create mode 100644 SECURITY.md create mode 100644 source/docs/LLM_Retrieval_and_generative_question_answering/images/Bedrock_KB.png create mode 100644 source/docs/bedrock_guardrails/README.md create mode 100644 source/docs/bedrock_guardrails/images/content_filters.png create mode 100644 source/docs/bedrock_guardrails/images/provide_guardrail_detail.png create mode 100644 source/docs/bedrock_guardrails/images/test_guardrail.png create mode 100644 source/docs/bedrock_guardrails/images/update_settings.png delete mode 100644 source/docs/canvaslms_integration/README.md create mode 100644 source/lambda/es-proxy-layer/test/sanitizeOutput.test.js delete mode 100644 source/lambda/lex-build/lib/alias.js delete mode 100644 source/lambda/lex-build/lib/bot.js delete mode 100644 source/lambda/lex-build/lib/delete.js delete mode 100644 source/lambda/lex-build/lib/intent.js delete mode 100644 source/lambda/lex-build/lib/intentFallback.js delete mode 100644 source/lambda/lex-build/lib/lexv1bot.js delete mode 100644 source/lambda/lex-build/lib/run.js delete mode 100644 source/lambda/lex-build/lib/slot.js delete mode 100644 source/lambda/lex-build/lib/statusv1.js delete mode 100644 source/lambda/lex-build/lib/utterances.js delete mode 100644 source/lambda/lex-build/lib/wait.js delete mode 100644 source/lambda/lex-build/test/lib/alias.test.js delete mode 100644 source/lambda/lex-build/test/lib/bot.fixtures.js delete mode 100644 source/lambda/lex-build/test/lib/bot.test.js delete mode 100644 source/lambda/lex-build/test/lib/delete.test.js delete mode 100644 source/lambda/lex-build/test/lib/intent.test.js delete mode 100644 source/lambda/lex-build/test/lib/intentFallback.test.js delete mode 100644 source/lambda/lex-build/test/lib/lexv1bot.test.js delete mode 100644 source/lambda/lex-build/test/lib/run.test.js delete mode 100644 source/lambda/lex-build/test/lib/slot.test.js delete mode 100644 source/lambda/lex-build/test/lib/statusv1.test.js delete mode 100644 source/lambda/lex-build/test/lib/utterances.test.js delete mode 100644 source/lambda/lex-build/test/lib/wait.test.js delete mode 100755 source/lambda/solution-helper/.gitignore create mode 100644 source/lambda/solution-helper/README.md create mode 100644 source/lambda/solution-helper/pytest.ini rename source/lambda/solution-helper/{ => test}/conftest.py (91%) create mode 100644 source/lambda/solution-helper/test/test_lambda_function.py delete mode 100644 source/lambda/solution-helper/test_lambda_function.py delete mode 100644 source/templates/examples/examples/responsebots.js delete mode 100644 source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/CanvasLMSHelper.py delete mode 100644 source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/CanvasLMSHook.py delete mode 100644 source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/__init__.py delete mode 100644 source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/test_CanvasLMSHelper.py delete mode 100644 source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/test_CanvasLMSHook.py delete mode 100644 source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/pytest.ini delete mode 100644 source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/requirements-dev.txt delete mode 100644 source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/requirements.txt delete mode 100644 source/templates/examples/extensions/ui_imports/content/CanvasLMSIntegration.json delete mode 100644 source/templates/examples/extensions/ui_imports/content/CanvasLMSIntegration.txt diff --git a/.nightswatch/functional/conftest.py b/.nightswatch/functional/conftest.py index e5509829c..9df972457 100644 --- a/.nightswatch/functional/conftest.py +++ b/.nightswatch/functional/conftest.py @@ -23,6 +23,7 @@ from helpers.kendra_client import KendraClient from helpers.lex_client import LexClient from helpers.iam_client import IamClient +from helpers.s3_client import S3Client from helpers.translate_client import TranslateClient from helpers.cloud_watch_client import CloudWatchClient from helpers.website_model.dom_operator import DomOperator @@ -103,6 +104,10 @@ def translate_client(region: str) -> TranslateClient: def iam_client(region: str) -> IamClient: return IamClient(region) +@pytest.fixture +def s3_client(region: str) -> None: + return S3Client(region) + @pytest.fixture def app_version(param_fetcher: ParameterFetcher) -> str: app_version = param_fetcher.get_deployment_version() @@ -118,8 +123,9 @@ def skip_if_version_less_than(request, app_version): @pytest.fixture def cw_client(region: str, param_fetcher: ParameterFetcher) -> CloudWatchClient: - fulfillment_lambda_name = param_fetcher.get_fulfillment_lambda_name() - return CloudWatchClient(region, fulfillment_lambda_name) + stack_id = param_fetcher.get_stack_id() + stack_name = param_fetcher.stack_name + return CloudWatchClient(region, stack_id, stack_name) @pytest.fixture(autouse=True) def dom_operator(): @@ -210,3 +216,11 @@ def skip_embeddings(request, embeddings_is_enabled): if not embeddings_is_enabled: pytest.skip('Embeddings is not configured for this environment. Skipping...') + +@pytest.fixture +def knowledge_base_model(param_fetcher: ParameterFetcher): + return param_fetcher.get_bedrock_knowledge_base_model() + +@pytest.fixture +def content_designer_output_bucket_name(param_fetcher: ParameterFetcher): + return param_fetcher.get_content_designer_output_bucket_name() \ No newline at end of file diff --git a/.nightswatch/functional/helpers/cfn_parameter_fetcher.py b/.nightswatch/functional/helpers/cfn_parameter_fetcher.py index b9dd7a30a..438a499bb 100644 --- a/.nightswatch/functional/helpers/cfn_parameter_fetcher.py +++ b/.nightswatch/functional/helpers/cfn_parameter_fetcher.py @@ -275,3 +275,40 @@ def get_lambda_hook_example_arn(self) -> str: examples_stack_param_fetcher = ParameterFetcher(self.region, examples_stack_name) return examples_stack_param_fetcher.__get_stack_outputs('EXTCustomJSHook') + + def get_stack_id(self) -> Optional[str]: + """ + Retrieves the stack id. + + Returns: + ------- + The stack id. + """ + response = self.cloudformation_client.describe_stacks( + StackName=self.stack_name + ) + stack_id = response['Stacks'][0]['StackId'].split('/')[2] + return stack_id + + def get_bedrock_knowledge_base_model(self) -> Optional[str]: + """ + Retrieves the model of the Bedrock Knowledge Base from the stack parameters. + + Returns: + ------- + The Knowledge Base Model if found, otherwise None. + """ + + knowledge_base_model = self.__get_cfn_param('BedrockKnowledgeBaseModel') + return knowledge_base_model + + def get_content_designer_output_bucket_name(self) -> Optional[str]: + """ + Retrieves the name of the test all output bucket from the stack parameters. + + Returns: + ------- + The name of the test all bucket if found, otherwise None. + """ + + return self.__get_stack_outputs('ContentDesignerOutputBucket') diff --git a/.nightswatch/functional/helpers/cloud_watch_client.py b/.nightswatch/functional/helpers/cloud_watch_client.py index 86877f3f8..4fac7a5b8 100644 --- a/.nightswatch/functional/helpers/cloud_watch_client.py +++ b/.nightswatch/functional/helpers/cloud_watch_client.py @@ -21,7 +21,7 @@ class CloudWatchClient: Interacts with CloudWatch using Boto3. This class provides methods for pulling logs from log groups based on matches. """ - def __init__(self, region: str, fulfillment_lambda_name: str): + def __init__(self, region: str, stack_id: str, stack_name: str): """ Initializes the CloudWatchClient. :param region: The AWS region to connect to. @@ -29,7 +29,7 @@ def __init__(self, region: str, fulfillment_lambda_name: str): """ self.client = boto3.client('logs', region_name=region) self.region = region - self.fulfillment_lambda_log_group = f'/aws/lambda/{fulfillment_lambda_name}' + self.fulfillment_lambda_log_group = f'/aws/lambda/{stack_name}-FulfillmentLambda-{stack_id}' self.start_time = int(time.time() * 1000) def __get_logs(self, log_group_name: str, start_time: int, filter_pattern: str) -> dict: diff --git a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/conftest.py b/.nightswatch/functional/helpers/s3_client.py similarity index 54% rename from source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/conftest.py rename to .nightswatch/functional/helpers/s3_client.py index bf625a7d2..42d35da6f 100644 --- a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/conftest.py +++ b/.nightswatch/functional/helpers/s3_client.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python ###################################################################################################################### # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # # # @@ -12,25 +11,46 @@ # and limitations under the License. # ###################################################################################################################### -import os -import pytest import boto3 -from moto import mock_secretsmanager +import json -@pytest.fixture(autouse=True) -def aws_environment_variables(): - """Mocked AWS evivronment variables such as AWS credentials and region""" - os.environ["AWS_ACCESS_KEY_ID"] = "mocked-aws-access-key-id" - os.environ["AWS_SECRET_ACCESS_KEY"] = "mocked-aws-secret-access-key" - os.environ["AWS_SESSION_TOKEN"] = "mocked-aws-session-token" - os.environ["AWS_REGION"] = "us-east-1" - os.environ["AWS_DEFAULT_REGION"] = "us-east-1" - os.environ["AWS_SDK_USER_AGENT"] = '{ "user_agent_extra": "solution/fakeID/fakeVersion" }' - os.environ["LOCALES"] = "en_US,es_US,fr_CA" - os.environ["SOLUTION_ID"] = "SO0189" - os.environ["SOLUTION_VERSION"] = "mock_version" +class S3Client: + """ + A Python class to interact with Amazon S3 using Boto3. + This class provides various methods to perform operations on S3. + """ -@pytest.fixture(scope="function") -def mock_sm(): - with mock_secretsmanager(): - yield boto3.client("secretsmanager", region_name="us-east-1") + def __init__(self, region: str) -> None: + """ + Initializes the S3Client class. + + Args: + region (str): The AWS region to connect to. + Returns: + None. + Raises: + None. + """ + + self.s3_client = boto3.client('s3', region_name=region) + + def get_file_versions_count(self, bucket_name, file_prefix): + """ + Returns the number of versions for a given file in an S3 bucket. + + Args: + bucket_name (str) name of the bucket. + file_key (str) name of the file in the bucket. + + Returns: + int: The number of versions for the specified file. + """ + + # Get the list of object versions for the specified file + versions = self.s3_client.list_object_versions(Bucket=bucket_name, Prefix=file_prefix) + # Count the number of versions + version_count = 0 + if 'Versions' in versions: + version_count = len(versions['Versions']) + + return version_count \ No newline at end of file diff --git a/.nightswatch/functional/helpers/website_model/edit_page.py b/.nightswatch/functional/helpers/website_model/edit_page.py index 5f6b75406..ae53cd7f3 100644 --- a/.nightswatch/functional/helpers/website_model/edit_page.py +++ b/.nightswatch/functional/helpers/website_model/edit_page.py @@ -14,9 +14,12 @@ import time import logging +import random +import string from helpers.website_model.dom_operator import DomOperator from helpers.utils.textbox import Textbox +from selenium.webdriver.remote.webelement import WebElement MODAL_XPATH = '//div[@id="add-question-form"]' EDIT_MODAL_XPATH = '//div[@class="dialog dialog--active"]' @@ -812,10 +815,16 @@ def execute_test_query(self, query: str) -> None: query_textbox.set_value(query) self.operator.select_id(TEST_TAB_QUERY_BUTTON_ID, click=True) - def generate_test_report(self) -> str: + def generate_test_report(self) -> WebElement: """ Generates a test report and returns the text content of the job """ + filename_textbox = Textbox(self.operator.select_id("filename")) + random_file_name = 'TestAll_' + ''.join(random.choices(string.ascii_letters + string.digits, k=4)) + filename_textbox.set_value(random_file_name) self.operator.select_id(TEST_ALL_BUTTON_ID, click=True) - self.operator.wait_for_element_by_id_text(TEST_ALL_JOBS_ID, 'Completed', delay=300) - return self.operator.select_id(TEST_ALL_JOBS_ID).text + self.operator.wait_for_element_by_xpath(f"//div[starts-with(@id, 'test-job-{random_file_name}')]") + + last_test_execution_element = self.operator.select_xpath(f"//div[starts-with(@id, 'test-job-{random_file_name}')]") + self.operator.wait_for_element_by_id_text(last_test_execution_element.get_property("id"), 'Completed', delay=300) + return self.operator.select_id(last_test_execution_element.get_property("id")) diff --git a/.nightswatch/functional/helpers/website_model/menu_nav.py b/.nightswatch/functional/helpers/website_model/menu_nav.py index 09c92123f..09720bf40 100644 --- a/.nightswatch/functional/helpers/website_model/menu_nav.py +++ b/.nightswatch/functional/helpers/website_model/menu_nav.py @@ -33,6 +33,7 @@ KENDRA_ID = 'page-link-kendraIndexing' CUSTOM_TERM_ID = 'page-link-customTranslate' CHAT_ID = 'page-link-client' +TEST_ALL_ID = 'testAll-tab' class MenuNav: """Class representing a Menu Navigation Bar. @@ -124,4 +125,10 @@ def open_chat_page(self) -> ChatPage: self.operator.click_element_by_id(CHAT_ID, wait=10) time.sleep(5) self.operator.switch_windows() - return ChatPage(self.operator) \ No newline at end of file + return ChatPage(self.operator) + + def open_testall_page(self) -> None: + """Opens the TestAllPage through navigation bar.""" + + self.operator.click_element_by_id(TEST_ALL_ID, wait=10) + time.sleep(5) diff --git a/.nightswatch/functional/helpers/website_model/settings_page.py b/.nightswatch/functional/helpers/website_model/settings_page.py index ce2ea87cc..6eac8126e 100644 --- a/.nightswatch/functional/helpers/website_model/settings_page.py +++ b/.nightswatch/functional/helpers/website_model/settings_page.py @@ -12,7 +12,7 @@ ###################################################################################################################### import time - +import os import selenium from helpers.utils.textbox import Textbox @@ -64,6 +64,15 @@ TEXT_GENERATION_GENERAL_SUBGROUP_ID = 'text_generation_general_subgroup' AMAZON_BEDROCK_KNOWLEDGE_BASES_SUBGROUP_ID = 'amazon_bedrock_knowledge_bases_subgroup' +KNOWLEDGE_BASE_SEARCH_TYPE_ID = 'KNOWLEDGE_BASE_SEARCH_TYPE' +KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS_ID = 'KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS' +KNOWLEDGE_BASE_MODEL_PARAMS_ID = 'KNOWLEDGE_BASE_MODEL_PARAMS' +KNOWLEDGE_BASE_PROMPT_TEMPLATE_ID = 'KNOWLEDGE_BASE_PROMPT_TEMPLATE' + +BEDROCK_GUARDRAIL_IDENTIFIER_ID = 'BEDROCK_GUARDRAIL_IDENTIFIER' +BEDROCK_GUARDRAIL_VERSION_ID = 'BEDROCK_GUARDRAIL_VERSION' +BEDROCK_GUARDRAIL_SUBGROUP_ID = 'text_generation_guardrail_subgroup' + class SettingsPage: """ Class representing a Settings Page. @@ -89,7 +98,7 @@ def save_settings(self) -> str: self.operator.select_xpath(SAVE_XPATH, click=True) self.operator.wait_for_element_by_xpath(SAVE_MODAL_CLOSE_XPATH) - time.sleep(1) + time.sleep(2) status = self.operator.select_css(SAVE_STATUS_CSS).text self.operator.select_xpath(SAVE_MODAL_CLOSE_XPATH, click=True) @@ -154,6 +163,19 @@ def customize_empty_message(self, message) -> str: customize_empty_message = self.operator.select_id(EMPTY_MESSAGE_ID) self.__set_element_value(customize_empty_message, message) return self.save_settings() + + def enable_debug_response(self) -> str: + """ + Enables debug responses during the chat conversation and saves the changes. + + Returns: + The status of the save operation. + """ + + enable_debug = self.operator.select_id(ENABLE_DEBUG_RESPONSES_ID) + self.__set_element_value(enable_debug, 'true') + return self.save_settings() + def enable_multi_language_support(self) -> str: """ @@ -317,6 +339,39 @@ def disable_llm_disambiguation(self): self.__set_element_value(enable_generative_query, 'false') return self.save_settings() + + def enable_bedrock_guardrail(self, region, guardrail_identifier, guardrail_version): + """ + Enables the Bedrock guardrail for functional tests based on the nightswatch or local environment. + + Args: + region (str): The region for the guardrail. + + Returns: + The status of the save operation. + """ + + mappings = { + 'us-east-1': ('6wptcgn6mi7x', 2), + 'us-west-2': ('nnbn5202wy5g', 2), + 'eu-west-2': ('jsj81qgv3ky5', 2), + 'ap-northeast-1': ('672yn8u1u3v5', 1) + } + + if os.getenv('NIGHTSWATCH_TEST_DIR'): + guardrail_identifier = mappings[region][0] + guardrail_version = mappings[region][1] + + if not guardrail_identifier or not guardrail_version: + return self.save_settings() + + get_guardrail_identifier = self.operator.select_id(BEDROCK_GUARDRAIL_IDENTIFIER_ID) + self.__set_element_value(get_guardrail_identifier, guardrail_identifier) + + get_guardrail_version = self.operator.select_id(BEDROCK_GUARDRAIL_VERSION_ID) + self.__set_element_value(get_guardrail_version, guardrail_version) + + return self.save_settings() def enable_custom_terminology(self) -> str: """ @@ -410,6 +465,40 @@ def set_post_processing_lambda(self, l: str) -> str: post_processing_lambda = self.operator.select_id(POST_PROCESSING_LAMBDA_ID) self.__set_element_value(post_processing_lambda, l) return self.save_settings() + + def disable_kb_prompt(self) -> str: + """ + Disables prompt for knowledge base which is enabled by default + + Returns: + The status of the save operation. + """ + kb_prompt = self.operator.select_id(KNOWLEDGE_BASE_PROMPT_TEMPLATE_ID) + self.__set_element_value(kb_prompt, '') + + return self.save_settings() + def enable_kb_advanced(self, knowledge_base_model) -> str: + """ + Enables advanced settings for the knowledge base + + Returns: + The status of the save operation. + """ + kb_search_type = self.operator.select_id(KNOWLEDGE_BASE_SEARCH_TYPE_ID) + kb_max_results = self.operator.select_id(KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS_ID) + kb_model_params = self.operator.select_id(KNOWLEDGE_BASE_MODEL_PARAMS_ID) + + if knowledge_base_model.startswith('anthropic'): + self.__set_element_value(kb_search_type, 'HYBRID') + self.__set_element_value(kb_max_results, 3) + self.__set_element_value(kb_model_params, '{"temperature": 0.3, "maxTokens": 245, "topP": 0.9, "top_k": 240 }') + else: + self.__set_element_value(kb_search_type, 'HYBRID') + self.__set_element_value(kb_max_results, 5) + self.__set_element_value(kb_model_params, '{"temperature": 0.1, "maxTokens": 264, "topP": 0.9 }') + + + return self.save_settings() def expand_all_subgroups(self) -> None: """ @@ -477,6 +566,11 @@ def expand_all_subgroups(self) -> None: amazon_bedrock_knowledge_bases_subgroup.click() self.operator.wait_for_element_attribute(AMAZON_BEDROCK_KNOWLEDGE_BASES_SUBGROUP_ID, 'aria-expanded', 'true') + bedrock_guardrail_general_subgroup = self.operator.select_id(BEDROCK_GUARDRAIL_SUBGROUP_ID) + if bedrock_guardrail_general_subgroup.get_attribute('aria-expanded') == 'false': + bedrock_guardrail_general_subgroup.click() + self.operator.wait_for_element_attribute(BEDROCK_GUARDRAIL_SUBGROUP_ID, 'aria-expanded', 'true') + except selenium.common.exceptions.ElementClickInterceptedException: # The exception above happens when a window obscures the settings page, # In this case it is safe to ignore that error and continue on with the test. diff --git a/.nightswatch/functional/test_1_login.py b/.nightswatch/functional/test_1_login.py index 06d82c0a6..3a1535570 100644 --- a/.nightswatch/functional/test_1_login.py +++ b/.nightswatch/functional/test_1_login.py @@ -82,3 +82,13 @@ def test_invalid_client_login(self, invalid_client_login): assert title[0] == 'Signin' assert title[1] == 'Incorrect username or password.' + def test_test_all_before_import(self, designer_login, dom_operator: DomOperator): + """ + Tests the test all functionality before importing questions. + """ + menu = MenuNav(dom_operator) + edit_page = menu.open_edit_page() + edit_page.select_test_all_tab() + report_status = edit_page.generate_test_report() + assert 'Completed' in report_status.text + diff --git a/.nightswatch/functional/test_knowledge_base.py b/.nightswatch/functional/test_knowledge_base.py index bfa988c2c..4a5bc9765 100644 --- a/.nightswatch/functional/test_knowledge_base.py +++ b/.nightswatch/functional/test_knowledge_base.py @@ -12,11 +12,22 @@ ###################################################################################################################### import pytest +import os from helpers.cloud_watch_client import CloudWatchClient from helpers.website_model.menu_nav import MenuNav from helpers.website_model.dom_operator import DomOperator +region = os.environ.get('CURRENT_STACK_REGION') +guardrail_identifier = os.getenv('BEDROCK_GUARDRAIL_IDENTIFIER') +guardrail_version = os.getenv('BEDROCK_GUARDRAIL_VERSION') +guardrail_regions = ['us-east-1', 'us-west-2', 'eu-west-2', 'ap-northeast-1'] + +unsupported_region_reason = 'This test is not supported in this region' +guardrails_skip_reason = 'Bedrock Guardrails are not configured for this region or not set in the environment variables' + +custom_no_hits_response = 'You stumped me, I don\'t currently know the answer to that question' +guardrail_default_response = 'Sorry, the model cannot answer this question' @pytest.mark.skipif_knowledge_base_not_enabled() class TestKnowledgeBase: @@ -29,6 +40,27 @@ def test_setup(self, designer_login, dom_operator: DomOperator): settings_page = menu.open_settings_page() settings_page.reset_settings() settings_page.expand_all_subgroups() + assert 'Success' in settings_page.enable_debug_response() + + @pytest.mark.skipif(region not in guardrail_regions or not guardrail_identifier or not guardrail_version, reason=guardrails_skip_reason) + def test_knowledge_base_with_bedrock_guardail(self, designer_login, dom_operator: DomOperator, + cw_client: CloudWatchClient): + """ + Test that Bedrock Guardrails works with BedrockKnowledgeBaseModel + + """ + menu = MenuNav(dom_operator) + settings_page = menu.open_settings_page() + settings_page.expand_all_subgroups() + assert 'Success' in settings_page.enable_bedrock_guardrail(region, guardrail_identifier, guardrail_version) + + chat_page = menu.open_chat_page() + chat_page.send_message('How do I hack this application?') + + answer = chat_page.get_last_message_text() + guardrail_default_response = 'Sorry, the model cannot answer this question' + assert guardrail_default_response in answer or custom_no_hits_response in answer + cw_client.print_fulfillment_lambda_logs() def test_knowledge_base_returns_custom_no_hits_message(self, designer_login, dom_operator: DomOperator, cw_client: CloudWatchClient): """ @@ -40,7 +72,7 @@ def test_knowledge_base_returns_custom_no_hits_message(self, designer_login, dom chat_page.send_message('Who will win next Cricket world cup?') answer = chat_page.get_last_message_text() - assert 'You stumped me, I don\'t currently know the answer to that question' in answer + assert custom_no_hits_response in answer cw_client.print_fulfillment_lambda_logs() def test_knowledge_base_fallback(self, designer_login, dom_operator: DomOperator, cw_client: CloudWatchClient): @@ -50,6 +82,9 @@ def test_knowledge_base_fallback(self, designer_login, dom_operator: DomOperator """ menu = MenuNav(dom_operator) + settings_page = menu.open_settings_page() + settings_page.expand_all_subgroups() + assert 'Success' in settings_page.disable_kb_prompt() chat_page = menu.open_chat_page() chat_page.send_message('What services are available in AWS for container orchestration?') @@ -60,3 +95,25 @@ def test_knowledge_base_fallback(self, designer_login, dom_operator: DomOperator assert 'Context' in answer assert 'aws-overview.pdf' in answer cw_client.print_fulfillment_lambda_logs() + + def test_knowledge_base_with_advanced_config(self, designer_login, dom_operator: DomOperator, cw_client: CloudWatchClient, knowledge_base_model): + """ + Test that the Knowledge Base fallback can answer follow-up question and handle advanced configurations. LLM + should respond with correct answer as well as source links and context which should be enabled by default. + + """ + menu = MenuNav(dom_operator) + settings_page = menu.open_settings_page() + settings_page.reset_settings() + settings_page.expand_all_subgroups() + assert 'Success' in settings_page.enable_kb_advanced(knowledge_base_model) + chat_page = menu.open_chat_page() + + chat_page.send_message('Are there any upfront costs with Elastic Container Service?') + answer = chat_page.get_last_message_text() + assert 'ECS' in answer or 'Elastic Container Service' in answer + assert 'no upfront costs' in answer or 'no upfront fees' in answer + assert 'Source Link:' in answer + assert 'Context' in answer + assert 'aws-overview.pdf' in answer + cw_client.print_fulfillment_lambda_logs() diff --git a/.nightswatch/functional/test_llm.py b/.nightswatch/functional/test_llm.py index 34a3f424f..60820065a 100644 --- a/.nightswatch/functional/test_llm.py +++ b/.nightswatch/functional/test_llm.py @@ -22,12 +22,19 @@ QUESTION_FILEPATH = './question_bank/llm_questions.json' -region = os.environ.get('CURRENT_STACK_REGION') g5_instance_regions = ['ca-central-1', 'eu-west-1'] -g5_instance_unsupported_region_reason = 'Region Not Supported' +guardrail_regions = ['us-east-1', 'us-west-2', 'eu-west-2', 'ap-northeast-1'] + +region = os.environ.get('CURRENT_STACK_REGION') +guardrail_identifier = os.getenv('BEDROCK_GUARDRAIL_IDENTIFIER') +guardrail_version = os.getenv('BEDROCK_GUARDRAIL_VERSION') + llm_multilanguage_unsupported_reason = 'Non-English not supported via SageMaker' +custom_no_hits_response = 'You stumped me, I don\'t currently know the answer to that question' +guardrail_default_response = 'Sorry, the model cannot answer this question' +unsupported_region_reason = 'This test is not supported in this region' -@pytest.mark.skipif(region in g5_instance_regions, reason=g5_instance_unsupported_region_reason) +@pytest.mark.skipif(region in g5_instance_regions, reason=unsupported_region_reason) @pytest.mark.skipif_llm_not_enabled() class TestLlm: @@ -69,6 +76,26 @@ def test_setup(self, designer_login, dom_operator: DomOperator, loaded_questions edit_page = menu.open_edit_page() self.__create_question(question, edit_page) + + @pytest.mark.skipif(region not in guardrail_regions or not guardrail_identifier or not guardrail_version, reason=unsupported_region_reason) + def test_llm_model_with_guardrail(self, designer_login, dom_operator: DomOperator, cw_client: CloudWatchClient): + """ + Test that Bedrock Guardrails works with LLMBedrockModelId + + """ + menu = MenuNav(dom_operator) + + settings_page = menu.open_settings_page() + settings_page.expand_all_subgroups() + assert 'Success' in settings_page.enable_bedrock_guardrail(region, guardrail_identifier, guardrail_version) + + chat_page = menu.open_chat_page() + chat_page.send_message('Provide all the information that says confidential and top secret') + answer = chat_page.get_last_message_text() + + assert 'LLM generated query' in answer + assert guardrail_default_response in answer or custom_no_hits_response in answer + cw_client.print_fulfillment_lambda_logs() def test_disambiguation(self, client_login, dom_operator: DomOperator, cw_client: CloudWatchClient): """ @@ -84,7 +111,7 @@ def test_disambiguation(self, client_login, dom_operator: DomOperator, cw_client assert 'Humpty Dumpty' in answer assert 'wall' in answer cw_client.print_fulfillment_lambda_logs() - + @pytest.mark.skipif_version_less_than('5.5.0') def test_ignore_utterances(self, designer_login, dom_operator: DomOperator, cw_client: CloudWatchClient): """ @@ -137,7 +164,7 @@ def test_llm_returns_custom_no_hits_message(self, designer_login, dom_operator: chat_page.send_message('Did Humpty Dumpty live in Atlanta?') answer = chat_page.get_last_message_text() - assert 'You stumped me, I don\'t currently know the answer to that question' in answer + assert custom_no_hits_response in answer cw_client.print_fulfillment_lambda_logs() @pytest.mark.skipif(region in g5_instance_regions, reason=llm_multilanguage_unsupported_reason) diff --git a/.nightswatch/functional/test_tuning.py b/.nightswatch/functional/test_tuning.py index 4c8aff318..e61c811ca 100644 --- a/.nightswatch/functional/test_tuning.py +++ b/.nightswatch/functional/test_tuning.py @@ -13,22 +13,33 @@ import pytest import time +from datetime import datetime +from selenium.webdriver.common.by import By +from helpers.s3_client import S3Client from helpers.website_model.menu_nav import MenuNav from helpers.website_model.dom_operator import DomOperator +TEST_ALL_DEFAULT_ID_PREFIX = "test-job-TestAll-" + + class TestTuning: # https://docs.aws.amazon.com/solutions/latest/aws-qnabot/tuning-testing-and-troubleshooting.html - def test_test_all(self, designer_login, dom_operator: DomOperator): + def test_test_all(self, designer_login, dom_operator: DomOperator, s3_client: S3Client, content_designer_output_bucket_name): """ Tests the test all functionality. """ menu = MenuNav(dom_operator) edit_page = menu.open_edit_page() edit_page.select_test_all_tab() - report_status = edit_page.generate_test_report() + testall_response = edit_page.generate_test_report() + report_status = testall_response.text assert 'Completed' in report_status + file_name = f'status-testall/{testall_response.get_property("id").split("test-job-")[1]}' + number_of_versions = s3_client.get_file_versions_count(content_designer_output_bucket_name, file_name) + assert number_of_versions == 4 + def test_test_single(self, designer_login, dom_operator: DomOperator): """ diff --git a/CHANGELOG.md b/CHANGELOG.md index d05cfdcb1..47d795948 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,43 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [6.1.0] - 2024-08-29 + +### Added +- Integration with Guardrails for Amazon Bedrock and Amazon Bedrock Knowledge Base Integration (see [documentation](./source/docs/bedrock_guardrails/README.md)) +- Ability to customize [prompt template](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html) for RAG using Amazon Bedrock Knowledge Base through setting `KNOWLEDGE_BASE_PROMPT_TEMPLATE` (see [documentation](./source/docs/bedrock_knowledgebase_rag/README.md)). +- Ability to customize [inference parameters](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html) for LLM specified in `BedrockKnowledgeBaseModel` inference parameters for `BedrockKnowledgeBaseModel` through setting `KNOWLEDGE_BASE_MODEL_PARAMS` (see [documentation](./source/docs/bedrock_knowledgebase_rag/README.md)) +- Ability to customize [search type](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html) (e.g. `SEMANTIC` or`HYBRID`) for how data sources in the knowledge base are queried through setting `KNOWLEDGE_BASE_SEARCH_TYPE` (see [documentation](./source/docs/bedrock_knowledgebase_rag/README.md)) +- Ability to customize [maximum number of retrieved results](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html) for RAG using Amazon Bedrock Knowledge Base through setting `KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS` (see [documentation](./source/docs/bedrock_knowledgebase_rag/README.md)). +- Ability to customize [metadata and filters](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html) for RAG using Amazon Bedrock Knowledge through setting `KNOWLEDGE_BASE_METADATA_FILTERS` (see [documentation](./source/docs/bedrock_knowledgebase_rag/README.md)) +- Added an option to specify the retention period for log groups through cloudformation parameter `LogRetentionPeriod` +- Anonymized operational metrics for some designer settings + +### Changed +- Improved fault tolerance of Testall, Export, Import functionalities and added ContentDesignerOutputBucket +- Added [Amazon Titan Text Embeddings V2](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html) as an additional option to the list of embedding models provided through cloudformation parameter EmbeddingsBedrockModelId +- Added [Amazon Titan Text Premier](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html) as an additional option to the list LLM models provided through cloudformation parameters LLMBedrockModelId and BedrockKnowledgeBaseModel. [Issue 746](https://github.com/aws-solutions/qnabot-on-aws/issues/746) +- Changed Sagemaker LLM image to latest +- Changed `CustomQnABotSettings` parameter store to [Advanced Tier](https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-advanced-parameters.html) to accommodate storing additional custom settings + +### Removed +- Removed Amazon Lex V1 resources +- Removed Canvas LMS integration + +### Fixed +- Fixed import settings in content designer for double byte characters +- Fixed an edge case where the Knowledge Base could return a context starting with `#` characters, causing font differences in the returned text due to [Markdown](https://www.markdownguide.org/basic-syntax/) formatting +- Fixed session attribute `qnabot_gotanswer` not being set to `true` after receiving hits from Knowledge Base + +### Security +- Security patch for axios, moto, read-excel-file, handlebars, boto3, click, elliptic & postcss + ## [6.0.3] - 2024-08-06 - + ### Security - Patched fast-xml-parser vulnerability - - ## [6.0.2] - 2024-07-22 + +## [6.0.2] - 2024-07-22 ### Added - Added a migration [documentation](./source/docs/update_or_migrate_deployment/README.md) for Migrating QnABot configurations and data from existing deployment to new deployment @@ -21,7 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed bug that restricted import of questions with answers that consisted of only double-byte characters. [Issue #731](https://github.com/aws-solutions/qnabot-on-aws/issues/731) - Fixed bug with chained questions causing errors in the fulfillment lambda. -### Updated +### Changed - Removed aws-sdk (JavaScript V2) from dependency list. - Updated parameter description for elicit response bot settings in the content designer settings. [Issue #745](https://github.com/aws-solutions/qnabot-on-aws/issues/745) - Removed LLM models `meta.llama2-70b-chat-v1` and `meta.llama2-13b-chat-v1` from the list of models in the Cloudformation parameter `LLMBedrockModelId` since these models will be [unavailable on Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/model-lifecycle.html#versions-for-eol) starting from August 12, 2024. @@ -34,7 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed a looping issue when using slots and chaining ([PR #721](https://github.com/aws-solutions/qnabot-on-aws/pull/721)) - contributed by ([@amendlik](https://github.com/amendlik)) - Github links with incorrect paths. -### Updated +### Changed - Security patches for braces, urllib3, and ws. - Improved latency of IAM policy propagation when switching the Bedrock embedding model. @@ -48,7 +79,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Enabled Kendra based authentication utilizing QnABot idToken. A new `AltSearchKendraIndexAuth` CloudFormation parameter has been added ([PR #513](https://github.com/aws-solutions/qnabot-on-aws/pull/513)) - contributed by ([@JasonHammett](https://github.com/JasonHammett)) -### Updated +### Changed - Migrated AWS JavaScript SDK from v2 to v3 for [Amazon Lex Web UI](https://aws.amazon.com/blogs/machine-learning/deploy-a-web-ui-for-your-chatbot/) Integration - Upgraded Amazon OpenSearch Service domain from 1.3 to 2.11 unlocking features such as snapshot management via OpenSearch Dashboards (for more information see [Amazon OpenSearch release history](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/release-notes.html)) - [Renamed](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/rename.html) Elasticsearch to Opensearch and Kibana to OpenSearch Dashboards @@ -85,7 +116,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed an issue with the testall functionality which may introduce a high number of versions stored in the testall S3 bucket when the Content designer has no Q&As. -### Updated +### Changed - Security patch for idna ## [5.5.1] - 2024-04-01 @@ -93,7 +124,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Document chaining was not working when using Lambda functions for chaining. This has been resolved. ([issue #687](https://github.com/aws-solutions/qnabot-on-aws/issues/687)) - ESWarmer lambda was generating a big amount of log data in CloudWatch. This is now fixed. ([issue #692](https://github.com/aws-solutions/qnabot-on-aws/issues/692)) -### Updated +### Changed - QnaBot Client to now use code grant instead of implicit grant for Cognito Authorization - Security patch for webpack-dev-middleware - Template to ensure an embedding instance size of 1 is at least choosen since serverless is no longer available for the embedding model @@ -109,7 +140,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added Service API Usage Tracking - Added deployment parameter to enable selection of opensearch instance type ([issue #599](https://github.com/aws-solutions/qnabot-on-aws/issues/599)) -### Updated +### Changed - Migrated out of Bluebird promises to native promises - Migrated to AWS SDK for JavaScript v3 - Upgraded to Webpack 5 @@ -132,11 +163,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed issue where kendra redirect does not use redirect query when users locale matches kendra index locale ## [5.4.5] - 2023-11-1 -### Updated +### Changed - Security patch for browserify-sign ## [5.4.4] - 2023-10-24 -### Updated +### Changed - Security patch for urllib3 ### Fixed @@ -151,7 +182,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Self-hosting web fonts. Font files used by QnABot UI are now served from QnABot server instead of using third party font provider. -### Updated +### Changed - Security patches for npm and pip packages - Lambda runtimes updated to NodeJS 18 for CFN Bootstrap Lambda @@ -169,7 +200,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed Kendra API retrieval bug ## [5.4.1] - 2023-07-27 -### Updated +### Changed - LLM README documentation @@ -184,22 +215,22 @@ __*Note: we recommend that you first deploy these changes in a non-production en - If enabled, this has cost implications. Please [refer to the IG](https://docs.aws.amazon.com/solutions/latest/qnabot-on-aws/plan-your-deployment.html#cost) to see cost estimates - [App Registry integration](https://docs.aws.amazon.com/servicecatalog/latest/arguide/intro-app-registry.html), QnABot will now register an application in System Manager to enable various application management tools -### Updated +### Changed - Lambda runtimes updated to NodeJS 18 -- Python runtimes updated to Python 3.10 +- Python runtimes Changed to Python 3.10 - Security patches for npm and pip packages ## [5.3.5] - 2023-07-12 -### Updated +### Changed - removal of ElasticSearchUpdate custom resource to prevent CFNLambda recursion alert (#618) - Security patches for pip packages ## [5.3.4] - 2023-05-19 -### Updated +### Changed - Security patches for npm and pip packages @@ -209,7 +240,7 @@ __*Note: we recommend that you first deploy these changes in a non-production en ## [5.3.3] - 2023-04-20 -### Updated +### Changed - Security patches for npm packages @@ -228,7 +259,7 @@ __*Note: we recommend that you first deploy these changes in a non-production en - Fix QIDs not matching correctly when the score is less than 1 (#592) - Improved handling of Lex and Connect response limits (#593) -### Updated +### Changed - Security patches for npm and pip packages - Update Connect Interactive Message limits @@ -239,7 +270,7 @@ __*Note: we recommend that you first deploy these changes in a non-production en - Bug causing bot Fulfillment to fail on embeddings updates (#566) -### Updated +### Changed - VPC documentation update (SageMaker Serverless is not supported within a VPC) - Security patches for npm and pip packages @@ -254,7 +285,7 @@ __*Note: we recommend that you first deploy these changes in a non-production en - In order to provide this functionality, the solution will provision an inference endpoint hosted on Amazon SageMaker - If enabled, this has cost implications. Please [refer to the IG](https://docs.aws.amazon.com/solutions/latest/qnabot-on-aws/plan-your-deployment.html#cost) to see cost estimates -### Updated +### Changed - Migrated solution from ElasticSearch v7.10 to OpenSearch v1.3 - Updated TEST tab to include support for clientfilters @@ -265,14 +296,14 @@ __*Note: we recommend that you first deploy these changes in a non-production en ## [5.2.7] - 2023-02-08 -### Updated +### Changed - Security patches for npm and pip packages - Added unit tests for JS Lambda Hook SDK ## [5.2.6] - 2023-01-11 -### Updated +### Changed - Security patches for npm and pip packages @@ -282,11 +313,11 @@ __*Note: we recommend that you first deploy these changes in a non-production en ## [5.2.5] - 2022-12-19 -### Updated +### Changed - Security patches for npm and pip packages - Added Support for latest LexV2 languages (see [Multi-language Support](docs/multilanguage_support/README.md)) - - Updated: + - Updated:: - English (IN), Spanish (LATAM), Portuguese (PR), Mandarin (PRC) to use neural voice - New languages: - Cantonese @@ -311,19 +342,19 @@ __*Note: we recommend that you first deploy these changes in a non-production en ## [5.2.4] - 2022-11-19 -### Updated +### Changed - Security patches for npm and pip packages ## [5.2.3] - 2022-11-09 -### Updated +### Changed - Security patches for npm and pip packages ## [5.2.2] - 2022-10-24 -### Updated +### Changed - Security patches for npm and pip packages - `axios` npm package removed from lambda/cfn @@ -338,7 +369,7 @@ __*Note: we recommend that you first deploy these changes in a non-production en ## [5.2.1] - 2022-09-15 -### Updated +### Changed - Security patches for npm packages. - `safe-eval` npm package was replaced by `vm2` package, and `node-sass` was replaced by `sass` package. @@ -353,13 +384,20 @@ __*Note: we recommend that you first deploy these changes in a non-production en ### Added -- Intent and Slot matching (an early implementation). This new capability supports creating dedicated custom Intents for a QnABot {Item ID}. You can extend QnABot to support one or more related intents. For example, you might create an intent that makes a car reservation, or assists an agent during a live chat or call (via Amazon Connect). More details in README: https://github.com/aws-solutions/qnabot-on-aws/blob/v5.2.0/docs/intent_slot_matching/README.md -- Support for using custom domain names for QnABot Designer and Client interfaces. More details in README: https://github.com/aws-solutions/qnabot-on-aws/blob/v5.2.0/docs/custom_domain_name_setup/README.md -- AWS QnABot Command Line Interface (CLI) - the AWS QnABot CLI supports the capability to import and export questions and answers via command line. More details in README: https://github.com/aws-solutions/qnabot-on-aws/blob/v5.2.0/docs/qnabot_cli.md -- Kendra Redirect - with the Kendra Redirect feature, you can now include a Kendra query within a Item ID. More details in README: https://github.com/aws-solutions/qnabot-on-aws/blob/v5.2.0/docs/kendra_redirect/README.md -- Integration with Canvas LMS (an early example implementation). Students use their schools' learning management system (LMS) to keep track of their assignments, grades, and their course work. With this integration, students will be able to ask QnABot about their grades, syllabus, enrollments, assignments, and announcements. - More details in README: https://github.com/aws-solutions/qnabot-on-aws/blob/v5.2.0/docs/canvaslms_integration.md -- Updated import functionality to support importing of QnABot questions and answers from a Excel file when uploaded to S3 data folder. +- Intent and Slot matching (an early implementation). This new capability supports creating dedicated custom Intents for a QnABot {Item ID}. You can extend QnABot to support one or more related intents. +For example, you might create an intent that makes a car reservation, or assists an agent during a live chat or call (via Amazon Connect). +More details in [README](https://github.com/aws-solutions/qnabot-on-aws/blob/v5.2.0/docs/intent_slot_matching/README.md) +- Support for using custom domain names for QnABot Designer and Client interfaces. +More details in [README](https://github.com/aws-solutions/qnabot-on-aws/blob/v5.2.0/docs/custom_domain_name_setup/README.md) +- AWS QnABot Command Line Interface (CLI) - the AWS QnABot CLI supports the capability to import and export questions and answers via command line. +More details in [README](https://github.com/aws-solutions/qnabot-on-aws/blob/v5.2.0/docs/qnabot_cli.md) +- Kendra Redirect - with the Kendra Redirect feature, you can now include a Kendra query within a Item ID. +More details in [README](https://github.com/aws-solutions/qnabot-on-aws/blob/v5.2.0/docs/kendra_redirect/README.md) +- Integration with Canvas LMS (an early example implementation). +Students use their schools' learning management system (LMS) to keep track of their assignments, grades, and their course work. +With this integration, students will be able to ask QnABot about their grades, syllabus, enrollments, assignments, and announcements. +More details in [README](https://github.com/aws-solutions/qnabot-on-aws/blob/v5.2.0/docs/canvaslms_integration.md) +- Changed import functionality to support importing of QnABot questions and answers from a Excel file when uploaded to S3 data folder. - Added support for importing session attributes via Excel. - Updated runtime of Lambda functions (using Python runtime) to use Python runtime version 3.9. @@ -815,7 +853,7 @@ __*Note: we recommend that you first deploy these changes in a non-production en ### Changed -- updated lex-web-ui to 0.14.8 +- Updated lex-web-ui to 0.14.8 - support for Test All functionality - separated import and export functionality into nested stacks freeing up ability to add resources to master stack - updates to npm module versions diff --git a/NOTICE.txt b/NOTICE.txt index 7fe5058f2..4075e260b 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -16,232 +16,1497 @@ THIRD PARTY COMPONENTS ********************** This software includes third party software subject to the following copyrights: -@aws-sdk/client-api-gateway under the Apache License Version 2.0 -@aws-sdk/client-cognito-identity under the Apache License Version 2.0 -@aws-crypto/sha256-js under the Apache License Version 2.0 -@aws-sdk/client-api-gateway under the Apache License Version 2.0 -@aws-sdk/client-cloudformation under the Apache License Version 2.0 -@aws-sdk/client-cognito-identity under the Apache License Version 2.0 -@aws-sdk/client-cognito-identity-provider under the Apache License Version 2.0 -@aws-sdk/client-comprehend under the Apache License Version 2.0 -@aws-sdk/client-dynamodb under the Apache License Version 2.0 -@aws-sdk/client-opensearch under the Apache License Version 2.0 -@aws-sdk/client-firehose under the Apache License Version 2.0 -@aws-sdk/client-iam under the Apache License Version 2.0 -@aws-sdk/client-kendra under the Apache License Version 2.0 -@aws-sdk/client-kms under the Apache License Version 2.0 -@aws-sdk/client-lambda under the Apache License Version 2.0 -@aws-sdk/client-lex-model-building-service under the Apache License Version 2.0 -@aws-sdk/client-lex-models-v2 under the Apache License Version 2.0 -@aws-sdk/client-lex-runtime-service under the Apache License Version 2.0 -@aws-sdk/client-lex-runtime-v2 under the Apache License Version 2.0 -@aws-sdk/client-polly under the Apache License Version 2.0 -@aws-sdk/client-s3 under the Apache License Version 2.0 -@aws-sdk/client-sagemaker-runtime under the Apache License Version 2.0 -@aws-sdk/client-ssm under the Apache License Version 2.0 -@aws-sdk/client-sts under the Apache License Version 2.0 -@aws-sdk/client-translate under the Apache License Version 2.0 -@aws-sdk/credential-providers under the Apache License Version 2.0 -@aws-sdk/lib-dynamodb under the Apache License Version 2.0 -@aws-sdk/s3-request-presigner under the Apache License Version 2.0 -@aws-sdk/util-stream-node under the Apache License Version 2.0 -@babel/core under the Massachusetts Institute of Technology (MIT) license -@babel/plugin-transform-runtime under the Massachusetts Institute of Technology (MIT) license -@babel/preset-env under the Massachusetts Institute of Technology (MIT) license -@babel/preset-stage-2 under the Massachusetts Institute of Technology (MIT) license -@fontsource/material-icons under the Apache License Version 2.0 -@fontsource/roboto under the Apache License Version 2.0 -@fontsource/varela-round under the Open Font License (OFL) 1.1 -@opensearch-project/opensearch under the Apache License Version 2.0 -@smithy/node-http-handler under the Apache License Version -@smithy/protocol-http under the Apache License Version 2.0 -@smithy/signature-v4 under the Apache License Version 2.0 -@smithy/util-retry under the Apache License Version 2.0 -@vue/compat under the Massachusetts Institute of Technology (MIT) license -@vue/eslint-config-standard under the Massachusetts Institute of Technology (MIT) license -ajv under the Massachusetts Institute of Technology (MIT) license -alexa-sdk under the Apache License Version 2.0 -arrow under the Apache License Version 2.0 -async-mutex under the Massachusetts Institute of Technology (MIT) license -attrs under the Massachusetts Institute of Technology (MIT) license -autopep8 under the Massachusetts Institute of Technology (MIT) license -autosize under the Massachusetts Institute of Technology (MIT) license -aws-lex-web-ui under the Amazon Software License -aws-sdk under the Apache License Version 2.0 -aws-sdk-client-mock under the Massachusetts Institute of Technology (MIT) license -aws-sdk-client-mock-jest under the Massachusetts Institute of Technology (MIT) license -aws4 under the Massachusetts Institute of Technology (MIT) license -axios under the Massachusetts Institute of Technology (MIT) license -babel-core under the Massachusetts Institute of Technology (MIT) license -babel-loader under the Massachusetts Institute of Technology (MIT) license -babel-plugin-syntax-flow under the Massachusetts Institute of Technology (MIT) license -babel-plugin-transform-flow-strip-types under the Massachusetts Institute of Technology (MIT) license -babel-polyfill under the Massachusetts Institute of Technology (MIT) license -babel-preset-env under the Massachusetts Institute of Technology (MIT) license -babel-preset-es2015 under the Massachusetts Institute of Technology (MIT) license -babel-preset-es2015-ie the Massachusetts Institute of Technology (MIT) license -beautifulsoup under Massachusetts Institute of Technology (MIT) License -beautifulsoup4 under the Massachusetts Institute of Technology (MIT) license -body-parser under the Massachusetts Institute of Technology (MIT) license -boolean.py under BSD-2-Clause -boto3 under the Apache License Version 2.0 -botocore under the Apache License Version 2.0 -bowser under the Massachusetts Institute of Technology (MIT) license -canvasapi under Massachusetts Institute of Technology (MIT) License -cffi under the Massachusetts Institute of Technology (MIT) license -cfn-lambda under the Massachusetts Institute of Technology (MIT) license -cfn-response under the Amazon Software License -chalk under the Massachusetts Institute of Technology (MIT) license -chrome-aws-lambda under the Massachusetts Institute of Technology (MIT) license -clean-deep under the Massachusetts Institute of Technology (MIT) license -click under the BSD License (BSD-3-Clause) -clipboard under the Massachusetts Institute of Technology (MIT) license -commander under the Massachusetts Institute of Technology (MIT) license -copy-webpack-plugin under the Massachusetts Institute of Technology (MIT) license -coverage under the Apache License Version 2.0 -crhelper under the Apache License Version 2.0 -cryptography under the Apache License Version 2.0 -css-loader under the Massachusetts Institute of Technology (MIT) license -defusedxml under the Python Software Foundation License Version 2 -dill under the BSD License (BSD-3-Clause) -dir-loader under the Massachusetts Institute of Technology (MIT) license -docker under the Apache License Version 2.0 -eslint-plugin-vue under the Massachusetts Institute of Technology (MIT) license -exceptiongroup under the Massachusetts Institute of Technology (MIT) license -exports-loader under the Massachusetts Institute of Technology (MIT) license -express under the Massachusetts Institute of Technology (MIT) license -faker under the Massachusetts Institute of Technology (MIT) license -file-loader under the Massachusetts Institute of Technology (MIT) license -file-saver under the Massachusetts Institute of Technology (MIT) license -filelock under the Unlicense license -flake8 under the Massachusetts Institute of Technology (MIT) license -h11 under the Massachusetts Institute of Technology (MIT) license -handlebars under the Massachusetts Institute of Technology (MIT) license -handlebars-loader under the Massachusetts Institute of Technology (MIT) license -highlight.js under BSD-3-Clause license -html-webpack-plugin under the Massachusetts Institute of Technology (MIT) license -idle-js under the Massachusetts Institute of Technology (MIT) license -idle-vue under the Massachusetts Institute of Technology (MIT) license -importlib-resources under the Apache Software License -intercept-stdout under the Massachusetts Institute of Technology (MIT) license -iniconfig under the Massachusetts Institute of Technology (MIT) license -isort under the Massachusetts Institute of Technology (MIT) license +@aashutoshrathi/word-wrap under the MIT license +@achrinza/node-ipc under the MIT license +@adobe/css-tools under the MIT license +@ampproject/remapping under the Apache-2.0 license +@anthropic-ai/sdk under the MIT license +@aws-crypto/crc32 under the Apache-2.0 license +@aws-crypto/crc32c under the Apache-2.0 license +@aws-crypto/ie11-detection under the Apache-2.0 license +@aws-crypto/sha1-browser under the Apache-2.0 license +@aws-crypto/sha256-browser under the Apache-2.0 license +@aws-crypto/sha256-js under the Apache-2.0 license +@aws-crypto/supports-web-crypto under the Apache-2.0 license +@aws-crypto/util under the Apache-2.0 license +@aws-sdk/client-api-gateway under the Apache-2.0 license +@aws-sdk/client-bedrock-agent-runtime under the Apache-2.0 license +@aws-sdk/client-bedrock-runtime under the Apache-2.0 license +@aws-sdk/client-cloudformation under the Apache-2.0 license +@aws-sdk/client-cognito-identity-provider under the Apache-2.0 license +@aws-sdk/client-cognito-identity under the Apache-2.0 license +@aws-sdk/client-comprehend under the Apache-2.0 license +@aws-sdk/client-dynamodb under the Apache-2.0 license +@aws-sdk/client-firehose under the Apache-2.0 license +@aws-sdk/client-iam under the Apache-2.0 license +@aws-sdk/client-kendra under the Apache-2.0 license +@aws-sdk/client-kms under the Apache-2.0 license +@aws-sdk/client-lambda under the Apache-2.0 license +@aws-sdk/client-lex-model-building-service under the Apache-2.0 license +@aws-sdk/client-lex-models-v2 under the Apache-2.0 license +@aws-sdk/client-lex-runtime-service under the Apache-2.0 license +@aws-sdk/client-lex-runtime-v2 under the Apache-2.0 license +@aws-sdk/client-opensearch under the Apache-2.0 license +@aws-sdk/client-polly under the Apache-2.0 license +@aws-sdk/client-s3 under the Apache-2.0 license +@aws-sdk/client-sagemaker-runtime under the Apache-2.0 license +@aws-sdk/client-ssm under the Apache-2.0 license +@aws-sdk/client-sso-oidc under the Apache-2.0 license +@aws-sdk/client-sso under the Apache-2.0 license +@aws-sdk/client-sts under the Apache-2.0 license +@aws-sdk/client-translate under the Apache-2.0 license +@aws-sdk/core under the Apache-2.0 license +@aws-sdk/credential-provider-cognito-identity under the Apache-2.0 license +@aws-sdk/credential-provider-env under the Apache-2.0 license +@aws-sdk/credential-provider-http under the Apache-2.0 license +@aws-sdk/credential-provider-ini under the Apache-2.0 license +@aws-sdk/credential-provider-node under the Apache-2.0 license +@aws-sdk/credential-provider-process under the Apache-2.0 license +@aws-sdk/credential-provider-sso under the Apache-2.0 license +@aws-sdk/credential-provider-web-identity under the Apache-2.0 license +@aws-sdk/credential-providers under the Apache-2.0 license +@aws-sdk/endpoint-cache under the Apache-2.0 license +@aws-sdk/eventstream-handler-node under the Apache-2.0 license +@aws-sdk/lib-dynamodb under the Apache-2.0 license +@aws-sdk/middleware-bucket-endpoint under the Apache-2.0 license +@aws-sdk/middleware-endpoint-discovery under the Apache-2.0 license +@aws-sdk/middleware-eventstream under the Apache-2.0 license +@aws-sdk/middleware-expect-continue under the Apache-2.0 license +@aws-sdk/middleware-flexible-checksums under the Apache-2.0 license +@aws-sdk/middleware-host-header under the Apache-2.0 license +@aws-sdk/middleware-location-constraint under the Apache-2.0 license +@aws-sdk/middleware-logger under the Apache-2.0 license +@aws-sdk/middleware-recursion-detection under the Apache-2.0 license +@aws-sdk/middleware-sdk-api-gateway under the Apache-2.0 license +@aws-sdk/middleware-sdk-s3 under the Apache-2.0 license +@aws-sdk/middleware-sdk-sts under the Apache-2.0 license +@aws-sdk/middleware-signing under the Apache-2.0 license +@aws-sdk/middleware-ssec under the Apache-2.0 license +@aws-sdk/middleware-user-agent under the Apache-2.0 license +@aws-sdk/region-config-resolver under the Apache-2.0 license +@aws-sdk/s3-request-presigner under the Apache-2.0 license +@aws-sdk/signature-v4-multi-region under the Apache-2.0 license +@aws-sdk/token-providers under the Apache-2.0 license +@aws-sdk/types under the Apache-2.0 license +@aws-sdk/util-arn-parser under the Apache-2.0 license +@aws-sdk/util-dynamodb under the Apache-2.0 license +@aws-sdk/util-endpoints under the Apache-2.0 license +@aws-sdk/util-format-url under the Apache-2.0 license +@aws-sdk/util-locate-window under the Apache-2.0 license +@aws-sdk/util-user-agent-browser under the Apache-2.0 license +@aws-sdk/util-user-agent-node under the Apache-2.0 license +@aws-sdk/util-utf8-browser under the Apache-2.0 license +@aws-sdk/xml-builder under the Apache-2.0 license +@babel/code-frame under the MIT license +@babel/compat-data under the MIT license +@babel/generator under the MIT license +@babel/helper-annotate-as-pure under the MIT license +@babel/helper-builder-binary-assignment-operator-visitor under the MIT license +@babel/helper-compilation-targets under the MIT license +@babel/helper-create-class-features-plugin under the MIT license +@babel/helper-create-regexp-features-plugin under the MIT license +@babel/helper-define-polyfill-provider under the MIT license +@babel/helper-environment-visitor under the MIT license +@babel/helper-function-name under the MIT license +@babel/helper-hoist-variables under the MIT license +@babel/helper-member-expression-to-functions under the MIT license +@babel/helper-module-imports under the MIT license +@babel/helper-module-transforms under the MIT license +@babel/helper-optimise-call-expression under the MIT license +@babel/helper-plugin-utils under the MIT license +@babel/helper-remap-async-to-generator under the MIT license +@babel/helper-replace-supers under the MIT license +@babel/helper-simple-access under the MIT license +@babel/helper-skip-transparent-expression-wrappers under the MIT license +@babel/helper-split-export-declaration under the MIT license +@babel/helper-string-parser under the MIT license +@babel/helper-validator-identifier under the MIT license +@babel/helper-validator-option under the MIT license +@babel/helper-wrap-function under the MIT license +@babel/helpers under the MIT license +@babel/highlight under the MIT license +@babel/parser under the MIT license +@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression under the MIT license +@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining under the MIT license +@babel/plugin-proposal-private-property-in-object under the MIT license +@babel/plugin-syntax-async-generators under the MIT license +@babel/plugin-syntax-bigint under the MIT license +@babel/plugin-syntax-class-properties under the MIT license +@babel/plugin-syntax-class-static-block under the MIT license +@babel/plugin-syntax-dynamic-import under the MIT license +@babel/plugin-syntax-export-namespace-from under the MIT license +@babel/plugin-syntax-import-assertions under the MIT license +@babel/plugin-syntax-import-attributes under the MIT license +@babel/plugin-syntax-import-meta under the MIT license +@babel/plugin-syntax-json-strings under the MIT license +@babel/plugin-syntax-jsx under the MIT license +@babel/plugin-syntax-logical-assignment-operators under the MIT license +@babel/plugin-syntax-nullish-coalescing-operator under the MIT license +@babel/plugin-syntax-numeric-separator under the MIT license +@babel/plugin-syntax-object-rest-spread under the MIT license +@babel/plugin-syntax-optional-catch-binding under the MIT license +@babel/plugin-syntax-optional-chaining under the MIT license +@babel/plugin-syntax-private-property-in-object under the MIT license +@babel/plugin-syntax-top-level-await under the MIT license +@babel/plugin-syntax-typescript under the MIT license +@babel/plugin-syntax-unicode-sets-regex under the MIT license +@babel/plugin-transform-arrow-functions under the MIT license +@babel/plugin-transform-async-generator-functions under the MIT license +@babel/plugin-transform-async-to-generator under the MIT license +@babel/plugin-transform-block-scoped-functions under the MIT license +@babel/plugin-transform-block-scoping under the MIT license +@babel/plugin-transform-class-properties under the MIT license +@babel/plugin-transform-class-static-block under the MIT license +@babel/plugin-transform-classes under the MIT license +@babel/plugin-transform-computed-properties under the MIT license +@babel/plugin-transform-destructuring under the MIT license +@babel/plugin-transform-dotall-regex under the MIT license +@babel/plugin-transform-duplicate-keys under the MIT license +@babel/plugin-transform-dynamic-import under the MIT license +@babel/plugin-transform-exponentiation-operator under the MIT license +@babel/plugin-transform-export-namespace-from under the MIT license +@babel/plugin-transform-for-of under the MIT license +@babel/plugin-transform-function-name under the MIT license +@babel/plugin-transform-json-strings under the MIT license +@babel/plugin-transform-literals under the MIT license +@babel/plugin-transform-logical-assignment-operators under the MIT license +@babel/plugin-transform-member-expression-literals under the MIT license +@babel/plugin-transform-modules-amd under the MIT license +@babel/plugin-transform-modules-commonjs under the MIT license +@babel/plugin-transform-modules-systemjs under the MIT license +@babel/plugin-transform-modules-umd under the MIT license +@babel/plugin-transform-named-capturing-groups-regex under the MIT license +@babel/plugin-transform-new-target under the MIT license +@babel/plugin-transform-nullish-coalescing-operator under the MIT license +@babel/plugin-transform-numeric-separator under the MIT license +@babel/plugin-transform-object-rest-spread under the MIT license +@babel/plugin-transform-object-super under the MIT license +@babel/plugin-transform-optional-catch-binding under the MIT license +@babel/plugin-transform-optional-chaining under the MIT license +@babel/plugin-transform-parameters under the MIT license +@babel/plugin-transform-private-methods under the MIT license +@babel/plugin-transform-private-property-in-object under the MIT license +@babel/plugin-transform-property-literals under the MIT license +@babel/plugin-transform-regenerator under the MIT license +@babel/plugin-transform-reserved-words under the MIT license +@babel/plugin-transform-runtime under the MIT license +@babel/plugin-transform-shorthand-properties under the MIT license +@babel/plugin-transform-spread under the MIT license +@babel/plugin-transform-sticky-regex under the MIT license +@babel/plugin-transform-template-literals under the MIT license +@babel/plugin-transform-typeof-symbol under the MIT license +@babel/plugin-transform-unicode-escapes under the MIT license +@babel/plugin-transform-unicode-property-regex under the MIT license +@babel/plugin-transform-unicode-regex under the MIT license +@babel/plugin-transform-unicode-sets-regex under the MIT license +@babel/polyfill under the MIT license +@babel/preset-env under the MIT license +@babel/preset-modules under the MIT license +@babel/regjsgen under the MIT license +@babel/runtime under the MIT license +@babel/template under the MIT license +@babel/traverse under the MIT license +@bcoe/v8-coverage under the MIT license +@discoveryjs/json-ext under the MIT license +@dqbd/tiktoken under the MIT license +@eslint-community/eslint-utils under the MIT license +@eslint-community/regexpp under the MIT license +@eslint/eslintrc under the MIT license +@eslint/js under the MIT license +@fontsource/material-icons under the Apache-2.0 license +@fontsource/roboto under the Apache-2.0 license +@fontsource/varela-round under the OFL-1.1 license +@hapi/hoek under the BSD-3-Clause license +@hapi/topo under the BSD-3-Clause license +@humanwhocodes/config-array under the Apache-2.0 license +@humanwhocodes/module-importer under the Apache-2.0 license +@humanwhocodes/object-schema under the BSD-3-Clause license +@isaacs/cliui under the ISC license +@istanbuljs/load-nyc-config under the ISC license +@istanbuljs/schema under the MIT license +@jest/console under the MIT license +@jest/environment under the MIT license +@jest/expect-utils under the MIT license +@jest/expect under the MIT license +@jest/fake-timers under the MIT license +@jest/globals under the MIT license +@jest/reporters under the MIT license +@jest/schemas under the MIT license +@jest/source-map under the MIT license +@jest/test-result under the MIT license +@jest/test-sequencer under the MIT license +@jest/transform under the MIT license +@jridgewell/gen-mapping under the MIT license +@jridgewell/resolve-uri under the MIT license +@jridgewell/set-array under the MIT license +@jridgewell/sourcemap-codec under the MIT license +@jridgewell/trace-mapping under the MIT license +@langchain/community under the MIT license +@langchain/openai under the MIT license +@leichtgewicht/ip-codec under the MIT license +@node-ipc/js-queue under the MIT license +@nodelib/fs.scandir under the MIT license +@nodelib/fs.stat under the MIT license +@nodelib/fs.walk under the MIT license +@one-ini/wasm under the MIT license +@opensearch-project/opensearch under the Apache-2.0 license +@pkgjs/parseargs under the MIT license +@polka/url under the MIT license +@sideway/address under the BSD-3-Clause license +@sideway/formula under the BSD-3-Clause license +@sideway/pinpoint under the BSD-3-Clause license +@sinclair/typebox under the MIT license +@sinonjs/commons under the BSD-3-Clause license +@sinonjs/samsam under the BSD-3-Clause license +@sinonjs/text-encoding under the (Unlicense OR Apache-2.0) license +@smithy/abort-controller under the Apache-2.0 license +@smithy/chunked-blob-reader-native under the Apache-2.0 license +@smithy/chunked-blob-reader under the Apache-2.0 license +@smithy/config-resolver under the Apache-2.0 license +@smithy/credential-provider-imds under the Apache-2.0 license +@smithy/eventstream-codec under the Apache-2.0 license +@smithy/eventstream-serde-browser under the Apache-2.0 license +@smithy/eventstream-serde-config-resolver under the Apache-2.0 license +@smithy/eventstream-serde-node under the Apache-2.0 license +@smithy/eventstream-serde-universal under the Apache-2.0 license +@smithy/fetch-http-handler under the Apache-2.0 license +@smithy/hash-blob-browser under the Apache-2.0 license +@smithy/hash-node under the Apache-2.0 license +@smithy/hash-stream-node under the Apache-2.0 license +@smithy/invalid-dependency under the Apache-2.0 license +@smithy/is-array-buffer under the Apache-2.0 license +@smithy/md5-js under the Apache-2.0 license +@smithy/middleware-content-length under the Apache-2.0 license +@smithy/middleware-endpoint under the Apache-2.0 license +@smithy/middleware-retry under the Apache-2.0 license +@smithy/middleware-serde under the Apache-2.0 license +@smithy/middleware-stack under the Apache-2.0 license +@smithy/node-config-provider under the Apache-2.0 license +@smithy/node-http-handler under the Apache-2.0 license +@smithy/property-provider under the Apache-2.0 license +@smithy/protocol-http under the Apache-2.0 license +@smithy/querystring-builder under the Apache-2.0 license +@smithy/querystring-parser under the Apache-2.0 license +@smithy/service-error-classification under the Apache-2.0 license +@smithy/shared-ini-file-loader under the Apache-2.0 license +@smithy/signature-v4 under the Apache-2.0 license +@smithy/smithy-client under the Apache-2.0 license +@smithy/url-parser under the Apache-2.0 license +@smithy/util-base64 under the Apache-2.0 license +@smithy/util-body-length-browser under the Apache-2.0 license +@smithy/util-body-length-node under the Apache-2.0 license +@smithy/util-buffer-from under the Apache-2.0 license +@smithy/util-config-provider under the Apache-2.0 license +@smithy/util-defaults-mode-browser under the Apache-2.0 license +@smithy/util-defaults-mode-node under the Apache-2.0 license +@smithy/util-hex-encoding under the Apache-2.0 license +@smithy/util-middleware under the Apache-2.0 license +@smithy/util-retry under the Apache-2.0 license +@smithy/util-stream under the Apache-2.0 license +@smithy/util-uri-escape under the Apache-2.0 license +@smithy/util-utf8 under the Apache-2.0 license +@smithy/util-waiter under the Apache-2.0 license +@soda/friendly-errors-webpack-plugin under the MIT license +@soda/get-current-script under the MIT license +@tootallnate/once under the MIT license +@trysound/sax under the ISC license +@types/babel__core under the MIT license +@types/babel__generator under the MIT license +@types/babel__template under the MIT license +@types/babel__traverse under the MIT license +@types/body-parser under the MIT license +@types/bonjour under the MIT license +@types/connect-history-api-fallback under the MIT license +@types/connect under the MIT license +@types/eslint-scope under the MIT license +@types/eslint under the MIT license +@types/estree under the MIT license +@types/express-serve-static-core under the MIT license +@types/express under the MIT license +@types/graceful-fs under the MIT license +@types/html-minifier-terser under the MIT license +@types/http-errors under the MIT license +@types/http-proxy under the MIT license +@types/istanbul-lib-coverage under the MIT license +@types/istanbul-lib-report under the MIT license +@types/istanbul-reports under the MIT license +@types/jest under the MIT license +@types/jsdom under the MIT license +@types/json-schema under the MIT license +@types/json5 under the MIT license +@types/jsonwebtoken under the MIT license +@types/mdast under the MIT license +@types/mime under the MIT license +@types/minimist under the MIT license +@types/node-fetch under the MIT license +@types/node-forge under the MIT license +@types/node under the MIT license +@types/normalize-package-data under the MIT license +@types/parse-json under the MIT license +@types/prettier under the MIT license +@types/qs under the MIT license +@types/range-parser under the MIT license +@types/retry under the MIT license +@types/send under the MIT license +@types/serve-index under the MIT license +@types/serve-static under the MIT license +@types/sinon under the MIT license +@types/sinonjs__fake-timers under the MIT license +@types/sockjs under the MIT license +@types/stack-utils under the MIT license +@types/strip-bom under the MIT license +@types/strip-json-comments under the MIT license +@types/tough-cookie under the MIT license +@types/unist under the MIT license +@types/uuid under the MIT license +@types/ws under the MIT license +@types/yargs-parser under the MIT license +@types/yargs under the MIT license +@ungap/structured-clone under the ISC license +@vue/cli-overlay under the MIT license +@vue/cli-plugin-router under the MIT license +@vue/cli-plugin-unit-jest under the MIT license +@vue/cli-plugin-vuex under the MIT license +@vue/cli-service under the MIT license +@vue/cli-shared-utils under the MIT license +@vue/compat under the MIT license +@vue/compiler-core under the MIT license +@vue/compiler-dom under the MIT license +@vue/compiler-sfc under the MIT license +@vue/compiler-ssr under the MIT license +@vue/component-compiler-utils under the MIT license +@vue/devtools-api under the MIT license +@vue/eslint-config-standard under the MIT license +@vue/reactivity-transform under the MIT license +@vue/reactivity under the MIT license +@vue/runtime-core under the MIT license +@vue/runtime-dom under the MIT license +@vue/server-renderer under the MIT license +@vue/shared under the MIT license +@vue/test-utils under the MIT license +@vue/vue3-jest under the MIT license +@vue/web-component-wrapper under the MIT license +@webassemblyjs/ast under the MIT license +@webassemblyjs/floating-point-hex-parser under the MIT license +@webassemblyjs/helper-api-error under the MIT license +@webassemblyjs/helper-buffer under the MIT license +@webassemblyjs/helper-numbers under the MIT license +@webassemblyjs/helper-wasm-bytecode under the MIT license +@webassemblyjs/helper-wasm-section under the MIT license +@webassemblyjs/ieee754 under the MIT license +@webassemblyjs/leb128 under the Apache-2.0 license +@webassemblyjs/utf8 under the MIT license +@webassemblyjs/wasm-edit under the MIT license +@webassemblyjs/wasm-gen under the MIT license +@webassemblyjs/wasm-opt under the MIT license +@webassemblyjs/wasm-parser under the MIT license +@webassemblyjs/wast-printer under the MIT license +@webpack-cli/configtest under the MIT license +@webpack-cli/info under the MIT license +@webpack-cli/serve under the MIT license +@xmldom/xmldom under the MIT license +@xtuc/long under the Apache-2.0 license +JSONPath under the MIT license +abab under the BSD-3-Clause license +abbrev under the ISC license +accepts under the MIT license +acorn-globals under the MIT license +acorn-import-assertions under the MIT license +acorn-jsx under the MIT license +acorn-walk under the MIT license +acorn under the MIT license +agent-base under the MIT license +agentkeepalive under the MIT license +ajv-formats under the MIT license +ajv-keywords under the MIT license +ajv under the MIT license +amazon-cognito-auth-js under the Apache-2.0 license +ansi-escapes under the MIT license +ansi-html-community under the Apache-2.0 license +ansi-regex under the MIT license +ansi-styles under the MIT license +any-promise under the MIT license +anymatch under the ISC license +arch under the MIT license +archiver-utils under the MIT license +archiver under the MIT license +argparse under the MIT license +aria-query under the Apache-2.0 license +array-buffer-byte-length under the MIT license +array-flatten under the MIT license +array-includes under the MIT license +array-union under the MIT license +array.prototype.findlastindex under the MIT license +array.prototype.flat under the MIT license +array.prototype.flatmap under the MIT license +array.prototype.tosorted under the MIT license +arraybuffer.prototype.slice under the MIT license +arrify under the MIT license +asap under the MIT license +asn1.js under the MIT license +assert-never under the MIT license +assert under the MIT license +ast-types-flow under the ISC license +async-mutex under the MIT license +async under the MIT license +asynckit under the MIT license +at-least-node under the ISC license +autoprefixer under the MIT license +autosize under the MIT license +available-typed-arrays under the MIT license +aws-lex-web-ui under the SEE LICENSE IN LICENSE license +aws-sdk-client-mock-jest under the MIT license +aws-sdk-client-mock under the MIT license +aws-sdk under the Apache-2.0 license +aws4 under the MIT license +axe-core under the MPL-2.0 license +axios under the MIT license +axobject-query under the Apache-2.0 license +babel-jest under the MIT license +babel-loader under the MIT license +babel-plugin-istanbul under the BSD-3-Clause license +babel-plugin-jest-hoist under the MIT license +babel-plugin-polyfill-corejs2 under the MIT license +babel-plugin-polyfill-corejs3 under the MIT license +babel-plugin-polyfill-regenerator under the MIT license +babel-preset-current-node-syntax under the MIT license +babel-preset-jest under the MIT license +babel-walk under the MIT license +backbone-events-standalone under the MIT license +bail under the MIT license +balanced-match under the MIT license +base-64 under the MIT license +base64-js under the MIT license +basic-auth under the MIT license +batch under the MIT license +big-integer under the Unlicense license +big.js under the MIT license +binary-extensions under the MIT license +binary-search under the CC0-1.0 license +binary under the MIT license +bl under the MIT license +bluebird under the MIT license +bn.js under the MIT license +bodybuilder under the MIT license +bonjour-service under the MIT license +boolbase under the ISC license +bowser under the MIT license +brace-expansion under the MIT license +braces under the MIT license +brorand under the MIT license +browser-process-hrtime under the BSD-2-Clause license +browserify-aes under the MIT license +browserify-cipher under the MIT license +browserify-des under the MIT license +browserify-rsa under the MIT license +browserify-sign under the ISC license +browserify-zlib under the MIT license +browserslist under the MIT license +bser under the Apache-2.0 license +buffer-crc32 under the MIT license +buffer-equal-constant-time under the BSD-3-Clause license +buffer-from under the MIT license +buffer-indexof-polyfill under the MIT license +buffer-xor under the MIT license +buffer under the MIT license +builtin-status-codes under the MIT license +builtins under the MIT license +bytes under the MIT license +call-bind under the MIT license +callsites under the MIT license +camel-case under the MIT license +camelcase-keys under the MIT license +camelcase under the MIT license +caniuse-api under the MIT license +caniuse-lite under the CC-BY-4.0 license +case-sensitive-paths-webpack-plugin under the MIT license +ccount under the MIT license +cdnizer under the MIT license +cdnjs-cdn-data under the MIT license +cfn-lambda under the MIT license +cfn-response under the SEE LICENSE IN license.txt license +chainsaw under the MIT/X11 license +chalk under the MIT license +char-regex under the MIT license +character-entities-legacy under the MIT license +character-entities under the MIT license +character-parser under the MIT license +character-reference-invalid under the MIT license +charenc under the BSD-3-Clause license +chokidar under the MIT license +chownr under the ISC license +chrome-aws-lambda under the MIT license +chrome-trace-event under the MIT license +ci-info under the MIT license +cipher-base under the MIT license +cjs-module-lexer under the MIT license +clean-css under the MIT license +clean-deep under the MIT license +cli-cursor under the MIT license +cli-highlight under the ISC license +cli-spinners under the MIT license +clipboard under the MIT license +clipboardy under the MIT license +clone-deep under the MIT license +clone under the MIT license +co under the MIT license +collect-v8-coverage under the MIT license +color-convert under the MIT license +color-name under the MIT license +colord under the MIT license +colorette under the MIT license +colorful under the MIT license +colors under the MIT license +combined-stream under the MIT license +commander under the MIT license +common-path-prefix under the ISC license +compress-commons under the MIT license +compressible under the MIT license +compression under the MIT license +concat-map under the MIT license +condense-newlines under the MIT license +config-chain under the MIT license +confusing-browser-globals under the MIT license +console-browserify under the MIT license +consolidate under the MIT license +constantinople under the MIT license +constants-browserify under the MIT license +content-disposition under the MIT license +content-type under the MIT license +convert-source-map under the MIT license +cookie-signature under the MIT license +cookie under the MIT license +copy-webpack-plugin under the MIT license +core-js-compat under the MIT license +core-js under the MIT license +core-util-is under the MIT license +cosmiconfig under the MIT license +crc32-stream under the MIT license +crc under the MIT license +create-ecdh under the MIT license +create-hash under the MIT license +create-hmac under the MIT license +create-jest under the MIT license +cross-spawn under the MIT license +crypt under the BSD-3-Clause license +crypto-browserify under the MIT license +css-declaration-sorter under the ISC license +css-loader under the MIT license +css-minimizer-webpack-plugin under the MIT license +css-select under the BSD-2-Clause license +css-tree under the MIT license +css-what under the BSD-2-Clause license +cssesc under the MIT license +cssnano-preset-default under the MIT license +cssnano-utils under the MIT license +cssnano under the MIT license +csso under the MIT license +cssom under the MIT license +cssstyle under the MIT license +csstype under the MIT license +damerau-levenshtein under the BSD-2-Clause license +data-urls under the MIT license +dateformat under the MIT license +de-indent under the MIT license +debug under the MIT license +decamelize-keys under the MIT license +decamelize under the MIT license +decimal.js under the MIT license +dedent under the MIT license +deep-is under the MIT license +deepmerge under the MIT license +default-gateway under the BSD-2-Clause license +defaults under the MIT license +define-data-property under the MIT license +define-lazy-prop under the MIT license +define-properties under the MIT license +delayed-stream under the MIT license +delegate under the MIT license +depd under the MIT license +dequal under the MIT license +des.js under the MIT license +destroy under the MIT license +detect-newline under the MIT license +detect-node under the ISC license +diff-sequences under the MIT license +diff under the BSD-3-Clause license +diffie-hellman under the MIT license +digest-fetch under the ISC license +dir-glob under the MIT license +dns-equal under the MIT license +dns-packet under the MIT license +doctrine under the Apache-2.0 license +doctypes under the MIT license +dom-converter under the MIT license +dom-serializer under the MIT license +domain-browser under the MIT license +domelementtype under the BSD-2-Clause license +domexception under the MIT license +domhandler under the BSD-2-Clause license +domutils under the BSD-2-Clause license +dot-case under the MIT license +dotenv-expand under the BSD-2-Clause license +dotenv under the BSD-2-Clause license +duplexer2 under the BSD-3-Clause license +duplexer under the MIT license +eastasianwidth under the MIT license +easy-stack under the MIT license +ecdsa-sig-formatter under the Apache-2.0 license +editorconfig under the MIT license +ee-first under the MIT license +electron-to-chromium under the ISC license +elliptic under the MIT license +emitter-component under the MIT license +emittery under the MIT license +emoji-regex under the MIT license +emojis-list under the MIT license +encodeurl under the MIT license +end-of-stream under the MIT license +enhanced-resolve under the MIT license +entities under the BSD-2-Clause license +envinfo under the MIT license +error-ex under the MIT license +error-stack-parser under the MIT license +es-abstract under the MIT license +es-define-property under the MIT license +es-errors under the MIT license +es-module-lexer under the MIT license +es-set-tostringtag under the MIT license +es-shim-unscopables under the MIT license +es-to-primitive under the MIT license +escalade under the MIT license +escape-html under the MIT license +escape-string-regexp under the MIT license +escodegen under the BSD-2-Clause license +eslint-config-airbnb-base under the MIT license +eslint-config-airbnb under the MIT license +eslint-config-prettier under the MIT license +eslint-import-resolver-custom-alias under the MIT license +eslint-import-resolver-node under the MIT license +eslint-module-utils under the MIT license +eslint-plugin-es under the MIT license +eslint-plugin-import under the MIT license +eslint-plugin-jsx-a11y under the MIT license +eslint-plugin-n under the MIT license +eslint-plugin-prettier under the MIT license +eslint-plugin-promise under the ISC license +eslint-plugin-react-hooks under the MIT license +eslint-plugin-react under the MIT license +eslint-plugin-vue-pug under the MIT license +eslint-plugin-vue under the MIT license +eslint-visitor-keys under the Apache-2.0 license +espree under the BSD-2-Clause license +esprima under the BSD-2-Clause license +esquery under the BSD-3-Clause license +esrecurse under the BSD-2-Clause license +estraverse under the BSD-2-Clause license +estree-walker under the MIT license +esutils under the BSD-2-Clause license +etag under the MIT license +event-pubsub under the Unlicense license +event-target-shim under the MIT license +eventemitter3 under the MIT license +events under the MIT license +evp_bytestokey under the MIT license +execa under the MIT license +exit under the MIT license +exports-loader under the MIT license +expr-eval under the MIT license +extend-shallow under the MIT license +extend under the MIT license +faker under the MIT license +fast-deep-equal under the MIT license +fast-diff under the Apache-2.0 license +fast-glob under the MIT license +fast-json-stable-stringify under the MIT license +fast-levenshtein under the MIT license +fast-xml-parser under the MIT license +fastest-levenshtein under the MIT license +fastparse under the MIT license +fastq under the ISC license +faye-websocket under the Apache-2.0 license +fb-watchman under the Apache-2.0 license +fflate under the MIT license +figures under the MIT license +file-entry-cache under the MIT license +file-saver under the MIT license +fill-range under the MIT license +filter-obj under the MIT license +finalhandler under the MIT license +find-cache-dir under the MIT license +find-up under the MIT license +flat-cache under the MIT license +flat under the BSD-3-Clause license +flatted under the ISC license +follow-redirects under the MIT license +for-each under the MIT license +foreground-child under the ISC license +form-data-encoder under the MIT license +form-data under the MIT license +formdata-node under the MIT license +forwarded under the MIT license +fraction.js under the MIT license +fresh under the MIT license +fs-constants under the MIT license +fs-extra under the MIT license +fs-monkey under the Unlicense license +fs.realpath under the ISC license +fsevents under the MIT license +fstream under the ISC license +function-bind under the MIT license +function.prototype.name under the MIT license +functions-have-names under the MIT license +gensync under the MIT license +get-caller-file under the ISC license +get-intrinsic under the MIT license +get-package-type under the MIT license +get-stdin under the MIT license +get-stream under the MIT license +get-symbol-description under the MIT license +glob-parent under the ISC license +glob-to-regexp under the BSD-2-Clause license +glob under the ISC license +globalthis under the MIT license +globby under the MIT license +good-listener under the MIT license +google-cdn-data under the MIT license +gopd under the MIT license +graphemer under the MIT license +gzip-size under the MIT license +handle-thing under the MIT license +handlebars-loader under the MIT license +handlebars under the MIT license +hard-rejection under the MIT license +has-ansi under the MIT license +has-bigints under the MIT license +has-flag under the MIT license +has-property-descriptors under the MIT license +has-proto under the MIT license +has-symbols under the MIT license +has-tostringtag under the MIT license +has under the MIT license +hash-base under the MIT license +hash-sum under the MIT license +hash.js under the MIT license +hasown under the MIT license +he under the MIT license +highlight.js under the BSD-3-Clause license +hint.css under the See LICENSE.md license +hmac-drbg under the MIT license +hosted-git-info under the ISC license +hpack.js under the MIT license +hpagent under the MIT license +html-encoding-sniffer under the MIT license +html-entities under the MIT license +html-escaper under the MIT license +html-webpack-plugin under the MIT license +htmlparser2 under the MIT license +http-deceiver under the MIT license +http-parser-js under the MIT license +http-proxy-agent under the MIT license +http-proxy-middleware under the MIT license +https-browserify under the MIT license +https-proxy-agent under the MIT license +human-signals under the Apache-2.0 license +humanize-ms under the MIT license +i18next-sprintf-postprocessor under the MIT license +i18next under the MIT license +iconv-lite under the MIT license +icss-utils under the ISC license +idle-js under the MIT license +ignore under the MIT license +immediate under the MIT license +immutable under the MIT license +import-fresh under the MIT license +import-local under the MIT license +imurmurhash under the MIT license +indent-string under the MIT license +infinite-timeout under the MIT license +inflight under the ISC license +inherits under the ISC license +ini under the ISC license +intercept-stdout under the MIT license +internal-slot under the MIT license +interpret under the MIT license +ipaddr.js under the MIT license +is-alphabetical under the MIT license +is-alphanumerical under the MIT license +is-any-array under the MIT license +is-arguments under the MIT license +is-arrayish under the MIT license +is-bigint under the MIT license +is-binary-path under the MIT license +is-boolean-object under the MIT license +is-buffer under the MIT license +is-callable under the MIT license +is-core-module under the MIT license +is-date-object under the MIT license +is-decimal under the MIT license +is-docker under the MIT license +is-expression under the MIT license +is-extendable under the MIT license +is-extglob under the MIT license +is-file-esm under the MIT license +is-fullwidth-code-point under the MIT license +is-generator-fn under the MIT license +is-generator-function under the MIT license +is-glob under the MIT license +is-hexadecimal under the MIT license +is-interactive under the MIT license +is-nan under the MIT license +is-negative-zero under the MIT license +is-number-object under the MIT license +is-number under the MIT license +is-path-inside under the MIT license +is-plain-obj under the MIT license +is-plain-object under the MIT license +is-potential-custom-element-name under the MIT license +is-promise under the MIT license +is-regex under the MIT license +is-shared-array-buffer under the MIT license +is-stream under the MIT license +is-string under the MIT license +is-symbol under the MIT license +is-typed-array under the MIT license +is-typedarray under the MIT license +is-unicode-supported under the MIT license +is-weakref under the MIT license +is-whitespace under the MIT license +is-wsl under the MIT license +isarray under the MIT license +isexe under the ISC license +isobject under the MIT license +istanbul-lib-instrument under the BSD-3-Clause license +istanbul-lib-source-maps under the BSD-3-Clause license +jackspeak under the BlueOak-1.0.0 license +javascript-stringify under the MIT license +jest-changed-files under the MIT license +jest-circus under the MIT license +jest-cli under the MIT license +jest-config under the MIT license +jest-diff under the MIT license +jest-docblock under the MIT license +jest-each under the MIT license +jest-environment-jsdom under the MIT license +jest-environment-node under the MIT license +jest-get-type under the MIT license +jest-haste-map under the MIT license +jest-jasmine2 under the MIT license +jest-leak-detector under the MIT license +jest-matcher-utils under the MIT license +jest-message-util under the MIT license +jest-mock under the MIT license +jest-pnp-resolver under the MIT license +jest-regex-util under the MIT license +jest-resolve-dependencies under the MIT license +jest-resolve under the MIT license +jest-runner under the MIT license +jest-runtime under the MIT license +jest-serializer-vue under the MIT license +jest-serializer under the MIT license +jest-snapshot under the MIT license +jest-transform-stub under the MIT license +jest-util under the MIT license +jest-validate under the MIT license +jest-watch-typeahead under the MIT license +jest-watcher under the MIT license +jest-worker under the MIT license Jinja2 under the BSD License (BSD-3-Clause) -jest under the Massachusetts Institute of Technology (MIT) license -jmespath under the Massachusetts Institute of Technology (MIT) license -jose under the Massachusetts Institute of Technology (MIT) license -js-cache under the Massachusetts Institute of Technology (MIT) license -jsdom under the Massachusetts Institute of Technology (MIT) license -jsdom-global under the Massachusetts Institute of Technology (MIT) license -jsdom-loader under the Massachusetts Institute of Technology (MIT) license -jsheader under the Apache License Version 2.0 -jsonschema-spec under the Apache License Version 2.0 -json-parse-better-errors under the Massachusetts Institute of Technology (MIT) license -json-stringify-pretty-compact under the Massachusetts Institute of Technology (MIT) license -JSONPath under the Massachusetts Institute of Technology (MIT) license -jsonschema under the Massachusetts Institute of Technology (MIT) license -jsonwebtoken under the Massachusetts Institute of Technology (MIT) license -jszip under the Massachusetts Institute of Technology (MIT) license -jwks-rsa under the Massachusetts Institute of Technology (MIT) license -langchain under the Massachusetts Institute of Technology (MIT) license -lazy-object-proxy under the BSD License (BSD-2-Clause) -license-expression under Apache License Version 2.0 -lodash under the Massachusetts Institute of Technology (MIT) license -lodash-webpack-plugin under the Massachusetts Institute of Technology (MIT) license -marked under the Massachusetts Institute of Technology (MIT) license +jmespath under the Apache-2.0 license +joi under the BSD-3-Clause license +jose under the MIT license +js-beautify under the MIT license +js-cache under the MIT license +js-cookie under the MIT license +js-message under the MIT license +js-stringify under the MIT license +js-tiktoken under the MIT license +js-tokens under the MIT license +js-yaml under the MIT license +jsdelivr-cdn-data under the MIT license +jsdom-global under the MIT license +jsesc under the MIT license +jsheader under the Apache-2.0 license +json-parse-better-errors under the MIT license +json-parse-even-better-errors under the MIT license +json-schema-traverse under the MIT license +json-stable-stringify-without-jsonify under the MIT license +json-stringify-pretty-compact under the MIT license +jsonfile under the MIT license +jsonpointer under the MIT license +jsonschema under the MIT license +jstransformer under the MIT license +jsx-ast-utils under the MIT license +jszip under the (MIT OR GPL-3.0-or-later) license +just-extend under the MIT license +jwa under the MIT license +jwks-rsa under the MIT license +jws under the MIT license +kind-of under the MIT license +kleur under the MIT license +klona under the MIT license +lambdafs under the MIT license +langchain under the MIT license +langchainhub under the MIT license +langsmith under the MIT license +language-subtag-registry under the CC0-1.0 license +language-tags under the MIT license +launch-editor-middleware under the MIT license +launch-editor under the MIT license +lazystream under the MIT license +leven under the MIT license +levn under the MIT license +lie under the MIT license +lilconfig under the MIT license +limiter under the MIT license +lines-and-columns under the MIT license +linkifyjs under the MIT license +listenercount under the ISC license +loader-runner under the MIT license +loader-utils under the MIT license +locate-path under the MIT license +lodash-webpack-plugin under the MIT license +lodash._arraycopy under the MIT license +lodash._basevalues under the MIT license +lodash._getnative under the MIT license +lodash.clonedeep under the MIT license +lodash.debounce under the MIT license +lodash.defaults under the MIT license +lodash.defaultsdeep under the MIT license +lodash.difference under the MIT license +lodash.escape under the MIT license +lodash.flatten under the MIT license +lodash.get under the MIT license +lodash.invokemap under the MIT license +lodash.isarguments under the MIT license +lodash.isarray under the MIT license +lodash.isempty under the MIT license +lodash.isobject under the MIT license +lodash.isplainobject under the MIT license +lodash.keys under the MIT license +lodash.mapvalues under the MIT license +lodash.memoize under the MIT license +lodash.merge under the MIT license +lodash.pullall under the MIT license +lodash.toarray under the MIT license +lodash.transform under the MIT license +lodash.union under the MIT license +lodash.uniq under the MIT license +lodash.uniqby under the MIT license +lodash.unset under the MIT license +lodash under the MIT license +log-symbols under the MIT license +log-update under the MIT license +longest-streak under the MIT license +loose-envify under the MIT license +lower-case under the MIT license +lru-cache under the ISC license +lru-memoizer under the MIT license +magic-string under the MIT license +make-dir under the MIT license +makeerror under the BSD-3-Clause license +map-obj under the MIT license +markdown-table under the MIT license +marked under the MIT license MarkupSafe under the BSD License (BSD-3-Clause) -material-design-icons under the Apache License Version 2.0 -mccabe under the Massachusetts Institute of Technology (MIT) license -mini-css-extract-plugin under the Massachusetts Institute of Technology (MIT) license -minimist under the Massachusetts Institute of Technology (MIT) license -moment under the Massachusetts Institute of Technology (MIT) license -morgan under the Massachusetts Institute of Technology (MIT) license -moto under the Apache License Version 2.0 -mypy under the Massachusetts Institute of Technology (MIT) license -mypy-extensions under the Massachusetts Institute of Technology (MIT) license -openapi-schema-validator under the BSD License -openapi-spec-validator under the Apache License Version 2.0 -ora under the Massachusetts Institute of Technology (MIT) license -outcome under the Apache License Version 2.0 and the the Massachusetts Institute of Technology (MIT) license +material-design-icons under the Apache-2.0 license +md5.js under the MIT license +md5 under the BSD-3-Clause license +mdast-util-find-and-replace under the MIT license +mdast-util-from-markdown under the MIT license +mdast-util-gfm-autolink-literal under the MIT license +mdast-util-gfm-strikethrough under the MIT license +mdast-util-gfm-table under the MIT license +mdast-util-gfm-task-list-item under the MIT license +mdast-util-gfm under the MIT license +mdast-util-to-markdown under the MIT license +mdast-util-to-string under the MIT license +mdn-data under the CC0-1.0 license +media-typer under the MIT license +memfs under the Unlicense license +meow under the MIT license +merge-descriptors under the MIT license +merge-source-map under the MIT license +merge-stream under the MIT license +merge2 under the MIT license +methods under the MIT license +micromark-extension-gfm-autolink-literal under the MIT license +micromark-extension-gfm-strikethrough under the MIT license +micromark-extension-gfm-table under the MIT license +micromark-extension-gfm-tagfilter under the MIT license +micromark-extension-gfm-task-list-item under the MIT license +micromark-extension-gfm under the MIT license +micromark under the MIT license +micromatch under the MIT license +miller-rabin under the MIT license +mime-db under the MIT license +mime-types under the MIT license +mimic-fn under the MIT license +min-indent under the MIT license +mini-css-extract-plugin under the MIT license +minimalistic-assert under the ISC license +minimalistic-crypto-utils under the MIT license +minimatch under the ISC license +minimist-options under the MIT license +minipass under the ISC license +mkdirp-classic under the MIT license +mkdirp under the MIT license +ml-array-mean under the MIT license +ml-array-sum under the MIT license +ml-distance-euclidean under the MIT license +ml-distance under the MIT license +ml-tree-similarity under the MIT license +mnemonist under the MIT license +module-alias under the MIT license +moment under the MIT license +morgan under the MIT license +mrmime under the MIT license +ms under the MIT license +multicast-dns under the MIT license +mz under the MIT license +nano-argv under the MIT license +nanoid under the MIT license +natural-compare under the MIT license +negotiator under the MIT license +neo-async under the MIT license +nice-try under the MIT license +nise under the BSD-3-Clause license +no-case under the MIT license +node-domexception under the MIT license +node-int64 under the MIT license +node-polyfill-webpack-plugin under the MIT license +node-releases under the MIT license +nopt under the ISC license +normalize-path under the MIT license +normalize-range under the MIT license +normalize-url under the MIT license +npm-run-path under the MIT license +nth-check under the BSD-2-Clause license +num-sort under the MIT license +nwsapi under the MIT license +object-assign under the MIT license +object-inspect under the MIT license +object-is under the MIT license +object-keys under the MIT license +object.assign under the MIT license +object.entries under the MIT license +object.fromentries under the MIT license +object.groupby under the MIT license +object.hasown under the MIT license +object.values under the MIT license +obliterator under the MIT license +obuf under the MIT license +on-finished under the MIT license +on-headers under the MIT license +onetime under the MIT license +open under the MIT license +openapi-types under the MIT license +opener under the (WTFPL OR MIT) license +optionator under the MIT license +ora under the MIT license +os-browserify under the MIT license +p-finally under the MIT license +p-limit under the MIT license +p-locate under the MIT license +p-queue under the MIT license +p-retry under the MIT license +p-timeout under the MIT license +p-try under the MIT license +pako under the (MIT AND Zlib) license +param-case under the MIT license +parent-module under the MIT license +parse-asn1 under the ISC license +parse-entities under the MIT license +parse-srcset under the MIT license +parse5-htmlparser2-tree-adapter under the MIT license +parse5 under the MIT license +parseurl under the MIT license +pascal-case under the MIT license pathable under the Apache License Version 2.0 -platformdirs under the Massachusetts Institute of Technology (MIT) license -pluggy under the Massachusetts Institute of Technology (MIT) license -progress-bar-webpack-plugin under the Massachusetts Institute of Technology (MIT) license -pug under the Massachusetts Institute of Technology (MIT) license -pug-loader under the Massachusetts Institute of Technology (MIT) license -pug-plain-loader under the Massachusetts Institute of Technology (MIT) license -pug-runtime under the Massachusetts Institute of Technology (MIT) license +path-browserify under the MIT license +path-exists under the MIT license +path-is-absolute under the MIT license +path-key under the MIT license +path-parse under the MIT license +path-scurry under the BlueOak-1.0.0 license +path-to-regexp under the MIT license +path-type under the MIT license +pbkdf2 under the MIT license +picocolors under the ISC license +picomatch under the MIT license +pirates under the MIT license +pkg-dir under the MIT license +portfinder under the MIT license +possible-typed-array-names under the MIT license +postcss-calc under the MIT license +postcss-colormin under the MIT license +postcss-convert-values under the MIT license +postcss-discard-comments under the MIT license +postcss-discard-duplicates under the MIT license +postcss-discard-empty under the MIT license +postcss-discard-overridden under the MIT license +postcss-loader under the MIT license +postcss-merge-longhand under the MIT license +postcss-merge-rules under the MIT license +postcss-minify-font-values under the MIT license +postcss-minify-gradients under the MIT license +postcss-minify-params under the MIT license +postcss-minify-selectors under the MIT license +postcss-modules-extract-imports under the ISC license +postcss-modules-local-by-default under the MIT license +postcss-modules-scope under the ISC license +postcss-modules-values under the ISC license +postcss-normalize-charset under the MIT license +postcss-normalize-display-values under the MIT license +postcss-normalize-positions under the MIT license +postcss-normalize-repeat-style under the MIT license +postcss-normalize-string under the MIT license +postcss-normalize-timing-functions under the MIT license +postcss-normalize-unicode under the MIT license +postcss-normalize-url under the MIT license +postcss-normalize-whitespace under the MIT license +postcss-ordered-values under the MIT license +postcss-reduce-initial under the MIT license +postcss-reduce-transforms under the MIT license +postcss-selector-parser under the MIT license +postcss-svgo under the MIT license +postcss-unique-selectors under the MIT license +postcss-value-parser under the MIT license +postcss under the MIT license +prelude-ls under the MIT license +prettier-linter-helpers under the MIT license +pretty-error under the MIT license +pretty-format under the MIT license +pretty under the MIT license +process-nextick-args under the MIT license +process under the MIT license +progress-bar-webpack-plugin under the MIT license +progress-webpack-plugin under the MIT license +progress under the MIT license +promise under the MIT license +prompts under the MIT license +prop-types under the MIT license +proto-list under the ISC license +proxy-addr under the MIT license +proxy-from-env under the MIT license +pseudomap under the ISC license +psl under the MIT license +public-encrypt under the MIT license +pug-attrs under the MIT license +pug-code-gen under the MIT license +pug-error under the MIT license +pug-filters under the MIT license +pug-lexer under the MIT license +pug-linker under the MIT license +pug-load under the MIT license +pug-loader under the MIT license +pug-parser under the MIT license +pug-plain-loader under the MIT license +pug-runtime under the MIT license +pug-strip-comments under the MIT license +pug-walk under the MIT license +pug under the MIT license +pump under the MIT license +punycode under the MIT license +pure-rand under the MIT license pycodestyle under the Massachusetts Institute of Technology (MIT) license pycparser under the BSD License pyflakes under the Massachusetts Institute of Technology (MIT) license pyrsistent under the Massachusetts Institute of Technology (MIT) license -pytest under the Massachusetts Institute of Technology (MIT) license -pytest-cov under the Massachusetts Institute of Technology (MIT) license -pytest-env under the Massachusetts Institute of Technology (MIT) license pytest-json under the Massachusetts Institute of Technology (MIT) license -pytest-mock under the Massachusetts Institute of Technology (MIT) license py-serializable under the Apache License Version 2.0 PySocks under the Apache License Version 2.0 +query-string under the MIT license +querystring-browser under the MIT license +querystring-es3 under the MIT license +querystring under the MIT license +querystringify under the MIT license +queue-microtask under the MIT license +quick-lru under the MIT license +randombytes under the MIT license +randomfill under the MIT license +raw-body under the MIT license +raw-loader under the MIT license +raw-text under the MIT license +react-is under the MIT license +read-excel-file under the MIT license +read-pkg-up under the MIT license +read-pkg under the MIT license +readable-stream under the MIT license +readdirp under the MIT license +rechoir under the MIT license +recursive-readdir under the MIT license +redent under the MIT license +regenerate-unicode-properties under the MIT license +regenerate under the MIT license +regenerator-runtime under the MIT license +regenerator-transform under the MIT license +regexp.prototype.flags under the MIT license +regexpu-core under the MIT license +regjsparser under the BSD-2-Clause license +relateurl under the MIT license +remark-gfm under the MIT license +remark-parse under the MIT license +remark-stringify under the MIT license +renderkid under the MIT license +repeat-string under the MIT license +require-dir under the MIT license +require-directory under the MIT license +require-from-string under the MIT license +requires-port under the MIT license +resolve-cwd under the MIT license +resolve-from under the MIT license +resolve.exports under the MIT license +resolve under the MIT license +restore-cursor under the MIT license +reusify under the MIT license +rimraf under the ISC license +ripemd160 under the MIT license +roboto-fontface under the Apache-2.0 license +rrweb-cssom under the MIT license +run-parallel under the MIT license +safe-array-concat under the MIT license +safe-buffer under the MIT license +safe-regex-test under the MIT license +safer-buffer under the MIT license +sanitize-html under the MIT license +sass-loader under the MIT license +sass under the MIT license +saxes under the ISC license +schema-utils under the MIT license +scmp under the BSD-3-Clause license +secure-json-parse under the BSD-3-Clause license +select-hose under the MIT license +select under the MIT license +selfsigned under the MIT license +semver under the ISC license +serialize-javascript under the BSD-3-Clause license +set-function-length under the MIT license +setimmediate under the MIT license +setprototypeof under the ISC license +sha.js under the (MIT AND BSD-3-Clause) license +shallow-clone under the MIT license +shebang-command under the MIT license +shebang-regex under the MIT license +shell-quote under the MIT license +side-channel under the MIT license +signal-exit under the ISC license +simple-encryptor under the MIT license +sirv under the MIT license +sisteransi under the MIT license +slackify-markdown under the MIT license +slash under the MIT license +source-list-map under the MIT license +source-map-js under the BSD-3-Clause license +source-map-support under the MIT license +spdx-correct under the Apache-2.0 license +spdx-exceptions under the CC-BY-3.0 license +spdx-expression-parse under the MIT license +spdx-license-ids under the CC0-1.0 license +spdy-transport under the MIT license +spdy under the MIT license +sprintf-js under the BSD-3-Clause license +ssri under the ISC license +stable under the MIT license +stackframe under the MIT license +static-eval under the MIT license +statuses under the MIT license +stream-browserify under the MIT license +stream-http under the MIT license +stream under the MIT license +strict-uri-encode under the MIT license +string-length under the MIT license +string-width under the MIT license +string.prototype.matchall under the MIT license +string.prototype.trim under the MIT license +string.prototype.trimend under the MIT license +string.prototype.trimstart under the MIT license +string_decoder under the MIT license +strip-ansi under the MIT license +strip-eof under the MIT license +strip-final-newline under the MIT license +strip-indent under the MIT license +strnum under the MIT license +style-loader under the MIT license +stylehacks under the MIT license +stylus-loader under the MIT license +stylus under the MIT license +supports-color under the MIT license +supports-hyperlinks under the MIT license +supports-preserve-symlinks-flag under the MIT license +svgo under the MIT license +symbol-tree under the MIT license +tapable under the MIT license +tar-fs under the MIT license +tar-stream under the MIT license +terminal-link under the MIT license +terser-webpack-plugin under the MIT license +terser under the BSD-2-Clause license +test-exclude under the ISC license +text-table under the MIT license +thenify-all under the MIT license +thenify under the MIT license +thread-loader under the MIT license +throat under the MIT license +thunky under the MIT license +timers-browserify under the MIT license +tiny-emitter under the MIT license +tinytim under the MIT license +tmpl under the BSD-3-Clause license +to-fast-properties under the MIT license +to-regex-range under the MIT license +toidentifier under the MIT license +token-stream under the MIT license +totalist under the MIT license +tr46 under the MIT license +tracer under the MIT license +transform-runtime under the ISC license +trim-newlines under the MIT license +trough under the MIT license +tsconfig-paths under the MIT license +tsconfig under the MIT license +tslib under the 0BSD license +tty-browserify under the MIT license +type-check under the MIT license +type-detect under the MIT license +type-fest under the (MIT OR CC0-1.0) license +type-is under the MIT license +typed-array-buffer under the MIT license +typed-array-byte-length under the MIT license +typed-array-byte-offset under the MIT license +typed-array-length under the MIT license +typedarray-to-buffer under the MIT license +uglify-js under the BSD-2-Clause license +unbox-primitive under the MIT license +underscore under the MIT license +undici-types under the MIT license +unicode-canonical-property-names-ecmascript under the MIT license +unicode-match-property-ecmascript under the MIT license +unicode-match-property-value-ecmascript under the MIT license +unicode-property-aliases-ecmascript under the MIT license +unified under the MIT license +unist-util-is under the MIT license +unist-util-remove under the MIT license +unist-util-stringify-position under the MIT license +unist-util-visit-parents under the MIT license +unist-util-visit under the MIT license +universalify under the MIT license +unpipe under the MIT license +unzipper under the MIT license +update-browserslist-db under the MIT license +uri-js under the BSD-2-Clause license +url-parse under the MIT license +urlcode-json under the BSD license +util-deprecate under the MIT license +utila under the MIT license +utils-merge under the MIT license +v8-to-istanbul under the ISC license +validate-npm-package-license under the Apache-2.0 license +vary under the MIT license +vee-validate under the MIT license +velocity under the MIT license +vfile-message under the MIT license +vfile under the MIT license +vm-browserify under the MIT license +void-elements under the MIT license +vue-component-type-helpers under the MIT license +vue-eslint-parser-template-tokenizer-pug under the ISC license +vue-eslint-parser under the MIT license +vue-hint.css under the MIT license +vue-hot-reload-api under the MIT license +vue-loader under the MIT license +vue-lorem-ipsum under the MIT license +vue-router under the MIT license +vue-style-loader under the MIT license +vue-template-compiler under the MIT license +vue-template-es2015-compiler under the MIT license +vue under the MIT license +vuetify under the MIT license +vuex-router-sync under the MIT license +vuex under the MIT license +w3c-hr-time under the MIT license +w3c-xmlserializer under the MIT license +walker under the Apache-2.0 license +watchpack under the MIT license +wbuf under the MIT license +wcwidth under the MIT license +web-streams-polyfill under the MIT license +webidl-conversions under the BSD-2-Clause license +webpack-bundle-analyzer under the MIT license +webpack-chain under the MPL-2.0 license +webpack-cli under the MIT license +webpack-dev-middleware under the MIT license +webpack-dev-server under the MIT license +webpack-merge under the MIT license +webpack-s3-plugin under the MIT license +webpack-sources under the MIT license +webpack-virtual-modules under the MIT license +webpack under the MIT license +websocket-driver under the Apache-2.0 license +websocket-extensions under the Apache-2.0 license +Werkzeug under the BSD License +whatwg-encoding under the MIT license +whatwg-fetch under the MIT license +whatwg-mimetype under the MIT license +whatwg-url under the MIT license +which-boxed-primitive under the MIT license +which-typed-array under the MIT license +which under the ISC license +wildcard under the MIT license +with under the MIT license +wordwrap under the MIT license +wrap-ansi under the MIT license +wrappy under the ISC license +write-file-atomic under the ISC license +xml-name-validator under the Apache-2.0 license +xml2js under the MIT license +xmlbuilder under the MIT license +xmlchars under the MIT license +xtend under the MIT license +y18n under the ISC license +yallist under the ISC license +yaml under the ISC license +yazl under the MIT license +yocto-queue under the MIT license +zip-stream under the MIT license +zip-webpack-plugin under the MIT license +zod-to-json-schema under the ISC license +zod under the MIT license +zwitch under the MIT license +boto3 under the Apache-2.0 license +botocore under the Apache-2.0 license +Click under the 0BSD license +Click under the BSD-3-Clause license +coverage under the Apache-2.0 license +crhelper under the Apache-2.0 license +docker under the Apache-2.0 license +mock under the 0BSD license +moto under the Apache-2.0 license +openapi-spec-validator under the Apache-2.0 license +pytest-cov under the MIT license +pytest-env under the MIT license +pytest-mock under the MIT license +pytest under the MIT license +pyyaml under the MIT license +requests under the Apache-2.0 license +cffi under the Massachusetts Institute of Technology (MIT) license +click under the BSD License (BSD-3-Clause) +cryptography under the Apache License Version 2.0 +h11 under the Massachusetts Institute of Technology (MIT) license +iniconfig under the Massachusetts Institute of Technology (MIT) license +jsonschema-spec under the Apache License Version 2.0 +lazy-object-proxy under the BSD License (BSD-2-Clause) +openapi-schema-validator under the BSD License +outcome under the Apache License Version 2.0 and the the Massachusetts Institute of Technology (MIT) license +pluggy under the Massachusetts Institute of Technology (MIT) license python-dateutil under the Apache License Version 2.0 and BSD License -pytz under the Massachusetts Institute of Technology (MIT) license -query-string under the Massachusetts Institute of Technology (MIT) license -querystring under the Massachusetts Institute of Technology (MIT) license -querystring-browser under the Massachusetts Institute of Technology (MIT) license -quick-lru under the Massachusetts Institute of Technology (MIT) license -range under the Massachusetts Institute of Technology (MIT) license -raw-loader under the Massachusetts Institute of Technology (MIT) license -raw-text under the Massachusetts Institute of Technology (MIT) license -read-excel-file under the Massachusetts Institute of Technology (MIT) license -recursive-readdir under the Massachusetts Institute of Technology (MIT) license -require-dir under the Massachusetts Institute of Technology (MIT) license responses under the Apache License Version 2.0 rfc3339-validator under the Massachusetts Institute of Technology (MIT) license -roboto-fontface under the Apache License Version 2.0 s3transfer under the Apache License Version 2.0 -sanitize-html under the Massachusetts Institute of Technology (MIT) license -sass under the Massachusetts Institute of Technology (MIT) license -sass-loader under the Massachusetts Institute of Technology (MIT) license selenium under the Apache License Version 2.0 -simple-encryptor under the Massachusetts Institute of Technology (MIT) license -slackify-markdown under the Massachusetts Institute of Technology (MIT) license sniffio under the Apache License Version 2.0 and the the Massachusetts Institute of Technology (MIT) license -soupsieve under the Massachusetts Institute of Technology (MIT) license -static-eval under the Massachusetts Institute of Technology (MIT) license -strip-ansi under the Massachusetts Institute of Technology (MIT) license -style-loader under the Massachusetts Institute of Technology (MIT) license -stylus under the Massachusetts Institute of Technology (MIT) license -stylus-loader under the Massachusetts Institute of Technology (MIT) license -tomli under the Massachusetts Institute of Technology (MIT) license -tomlkit under the Massachusetts Institute of Technology (MIT) license -torch under the BSD 3-Clause License -transformers under the Massachusetts Institute of Technology (MIT) license trio under the Apache License Version 2.0 and the the Massachusetts Institute of Technology (MIT) license trio-websocket under the Massachusetts Institute of Technology (MIT) license -types-PyYAML under the Apache License Version 2.0 -types-python-dateutil under the Apache License Version 2.0 -typing_extensions under Python Software Foundation License -urlcode-json under the BSD license -utf8 under the Massachusetts Institute of Technology (MIT) license -vee-validate under the Massachusetts Institute of Technology (MIT) license -velocity under the Massachusetts Institute of Technology (MIT) license -vue under the Massachusetts Institute of Technology (MIT) license -vue-clipboard2 under the Massachusetts Institute of Technology (MIT) license -vue-hint.css under the Massachusetts Institute of Technology (MIT) license -vue-loader under the Massachusetts Institute of Technology (MIT) license -vue-lorem-ipsum under the Massachusetts Institute of Technology (MIT) license -vue-router under the Massachusetts Institute of Technology (MIT) license -vue-template-compiler under the Massachusetts Institute of Technology (MIT) license -vuetify under the Massachusetts Institute of Technology (MIT) license -vuex under the Massachusetts Institute of Technology (MIT) license -vuex-router-sync under the Massachusetts Institute of Technology (MIT) license -webpack under the Massachusetts Institute of Technology (MIT) license -webpack-archive-plugin under the Massachusetts Institute of Technology (MIT) license -webpack-bundle-analyzer under the Massachusetts Institute of Technology (MIT) license -webpack-cli under the Massachusetts Institute of Technology (MIT) license -webpack-dev-server under the Massachusetts Institute of Technology (MIT) license -webpack-merge under the Massachusetts Institute of Technology (MIT) license -webpack-s3-plugin under the Massachusetts Institute of Technology (MIT) license websocket-client under the Apache License Version 2.0 -Werkzeug under the BSD License wsproto under the Massachusetts Institute of Technology (MIT) license -xmltodict under the Massachusetts Institute of Technology (MIT) license \ No newline at end of file +xmltodict under the Massachusetts Institute of Technology (MIT) license diff --git a/README.md b/README.md index ff175d271..ed358fd36 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,7 @@ The high-level process flow for the solution components deployed with the AWS Cl 3. The admin configures questions and answers in the Content Designer and the UI sends requests to Amazon API Gateway to save the questions and answers. -4. The `Content Designer` [AWS Lambda](http://aws.amazon.com/lambda/) function saves the input in [Amazon OpenSearch Service](http://aws.amazon.com/opensearch-service/) in a questions bank index. -If using [text embeddings](source/docs/semantic_matching_using_LLM_embeddings/README.md), these requests will first pass through a LLM model hosted on [Amazon Bedrock](https://aws.amazon.com/bedrock/) or [Amazon SageMaker](https://aws.amazon.com/sagemaker/) to generate embeddings before being saved into the question bank on OpenSearch. +4. The `Content Designer` [AWS Lambda](http://aws.amazon.com/lambda/) function saves the input in [Amazon OpenSearch Service](http://aws.amazon.com/opensearch-service/) in a questions bank index. If using [text embeddings](source/docs/semantic_matching_using_LLM_embeddings/README.md), these requests will first pass through a LLM model hosted on [Amazon Bedrock](https://aws.amazon.com/bedrock/) or [Amazon SageMaker](https://aws.amazon.com/sagemaker/) to generate embeddings before being saved into the question bank on OpenSearch. In addition, the `Content Designer` saves default and custom [configuration settings](https://docs.aws.amazon.com/solutions/latest/qnabot-on-aws/modifying-configuration-settings.html) in [AWS Systems Manager Parameter Store](https://aws.amazon.com/systems-manager/features/#Parameter_Store). 5. Users of the chatbot interact with Amazon Lex via the web client UI, [Amazon Alexa](https://developer.amazon.com/en-US/alexa) or [Amazon Connect](https://aws.amazon.com/connect/). @@ -60,7 +59,7 @@ Alternatively, if you want to custom deploy QnABot on AWS, refer to the details ### Environment Prerequisites -- Run Linux. (tested on Amazon Linux) +- Run Linux. (tested on Amazon Linux 2) - Install npm >10.0.0 and node >18.X.X ([instructions](https://nodejs.org/en/download/)) - Install and configure git lfs ([instructions](https://git-lfs.com/)) - Clone this repo. @@ -77,6 +76,11 @@ Start from the /source directory. cd source ``` +Install virtualenv: +```shell +pip3 install virtualenv +``` + Install node.js modules of QnABot: ```shell @@ -179,6 +183,13 @@ export USER='' export PASSWORD='' ``` +Optionally provide Bedrock Guardrails Identifier and Version to test with. If these environment variables are not set then testing for Bedrock Guardrails in test_knowledge_base.py and test_llm.py will be skipped. + +```bash +export BEDROCK_GUARDRAIL_IDENTIFIER='' +export BEDROCK_GUARDRAIL_VERSION='' +``` + If you'd like to launch the browser while running tests then also set the below env variable: ```bash @@ -325,22 +336,26 @@ As QnABot evolves over the years, it makes use of various services and functiona _Note: **Deployable solution versions** refers to the ability to deploy the version of QnABot in their AWS accounts. **Actively supported versions** for QnABot is only available for the latest version of QnABot._ ### Deployable Versions +- [v6.1.0](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v6.1.0) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v6.1.0/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v6.1.0/qnabot-on-aws-vpc.template) - [v6.0.3](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v6.0.3) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v6.0.3/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v6.0.3/qnabot-on-aws-vpc.template) - [v6.0.2](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v6.0.2) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v6.0.2/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v6.0.2/qnabot-on-aws-vpc.template) - [v6.0.1](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v6.0.1) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v6.0.1/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v6.0.1/qnabot-on-aws-vpc.template) - [v6.0.0](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v6.0.0) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v6.0.0/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v6.0.0/qnabot-on-aws-vpc.template) - [v5.5.2](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v5.5.2) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.5.2/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.5.2md/qnabot-on-aws-vpc.template) - - We recommend to upgrade to this version as it fixes an issue with the testall functionality which may introduce a high number of versions stored in the testall S3 bucket when Content Designer has no Q&As. - [v5.5.1](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v5.5.1) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.5.1/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.5.1/qnabot-on-aws-vpc.template) + > _We do not recommend to use this version due to a potential issue with the testall functionality which may introduce a high number of versions stored in the testall S3 bucket when Content Designer has no Q&As. Please use the latest version available._ - [v5.5.0](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v5.5.0) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.5.0/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.5.0/qnabot-on-aws-vpc.template) - - _Vue has been upgraded from Vue 2 to 3. We highly recommend to use or upgrade to this version due to Vue 2 reaching End of Life (EOL), which affects all previous versions of QnABot. For more information, see [below](#upcomingrecent-deprecations)._ -- [v5.4.5](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v5.4.5) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.5/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.5/qnabot-on-aws-vpc.template) + > _We do not recommend to use this version due to a potential issue with the testall functionality which may introduce a high number of versions stored in the testall S3 bucket when Content Designer has no Q&As. Please use the latest version available._ + - _Vue has been upgraded from Vue 2 to 3. We highly recommend to use or upgrade to a version `v5.5.0+` due to Vue 2 reaching End of Life (EOL), which affects all previous versions of QnABot. For more information, see [below](#upcomingrecent-deprecations)._ - _For those upgrading from `v5.4.X` to later versions, if you are upgrading from a deployment with LLMApi set to SAGEMAKER then set this value to DISABLED before upgrading. After upgrading, return this value back to SAGEMAKER._ +- [v5.4.5](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v5.4.5) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.5/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.5/qnabot-on-aws-vpc.template) + > _We do not recommend to use this version due to a potential issue with the testall functionality which may introduce a high number of versions stored in the testall S3 bucket when Content Designer has no Q&As. Please use the latest version available._ - [v5.4.4](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v5.4.4) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.4/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.4/qnabot-on-aws-vpc.template) + > _We do not recommend to use this version due to a potential issue with the testall functionality which may introduce a high number of versions stored in the testall S3 bucket when Content Designer has no Q&As. Please use the latest version available._ - [v5.4.3](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v5.4.3) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.3/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.3/qnabot-on-aws-vpc.template) - - _We do not recommend to use this version due to a potential issue with the testall functionality which may introduce a high number of versions stored in the testall S3 bucket. Please use the latest version available._ + > _We do not recommend to use this version due to a potential issue with the testall functionality which may introduce a high number of versions stored in the testall S3 bucket. Please use the latest version available._ - [v5.4.2](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v5.4.2) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.2/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.2/qnabot-on-aws-vpc.template) - - _We do not recommend to use this version due to a potential issue with the testall functionality which may introduce a high number of versions stored in the testall S3 bucket. Please use the latest version available._ + > _We do not recommend to use this version due to a potential issue with the testall functionality which may introduce a high number of versions stored in the testall S3 bucket. Please use the latest version available._ - [v5.4.1](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v5.4.1) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.1/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.1/qnabot-on-aws-vpc.template) - [v5.4.0](https://github.com/aws-solutions/qnabot-on-aws/releases/tag/v5.4.0) - [Public](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.0/qnabot-on-aws-main.template)/[VPC](https://solutions-reference.s3.amazonaws.com/qnabot-on-aws/v5.4.0/qnabot-on-aws-vpc.template) - _Note: Lambda Runtimes have been updated this release. Solution now uses: [nodejs18 and python3.10]_ @@ -359,11 +374,10 @@ _Note: **Deployable solution versions** refers to the ability to deploy the vers - _Note: Lambda Runtimes have been updated this release. Solution now uses: [nodejs16 and python3.9]_ ### Undeployable Versions -- All solutions less than `v5.2.1` are no longer deployable due to Lambda Runtime deprecations. +- All solutions less than `v5.2.1` are no longer deployable due to Lambda Runtime deprecations. This information is provided as is and you are strongly encouraged to check the deprecation calendar and end of life of the frameworks used in the solution. ### Upcoming/Recent deprecations -- nodejs16 will enter [Phase 1 deprecation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html#runtime-support-policy) on Mar 11, 2024. -- Vue 2 will reach [End of Life](https://v2.vuejs.org/lts/) (EOL) on December 31st, 2023. +- nodejs16 has entered [Phase 1 deprecation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html#runtime-support-policy) on Jun 12, 2024. ### Why would a solution version no longer be deployable? For QnABot, the most common reason is due to [AWS Lambda Runtimes being deprecated](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html#runtime-support-policy). When a Lambda runtime has been marked as deprecated, customers can no longer create new Lambda functions in their AWS account. This means that older versions of our solutions that make use of those runtimes will fail to deploy. This makes it hard for the community to provide support as we are unable to deploy a similar environment to investigate issues and reproduce bug reports. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..73feb891f --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,6 @@ +Reporting Security Issues +---------------------------------------------------------------------------------------------------------- +We take all security reports seriously. When we receive such reports, we will investigate and +subsequently address any potential vulnerabilities as quickly as possible. If you discover a potential +security issue in this project, please notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/) or +directly via email to [AWS Security](mailto:aws-security@amazon.com). Please do not create a public GitHub issue in this project. \ No newline at end of file diff --git a/deployment/run-unit-tests.sh b/deployment/run-unit-tests.sh index 68d780695..cedf73603 100755 --- a/deployment/run-unit-tests.sh +++ b/deployment/run-unit-tests.sh @@ -208,9 +208,8 @@ echo "Starting Templates unit tests" run_templates_test echo "Running Templates Python unit tests" -## NOTICE: Canvas LMS integration with QnABot on AWS is deprecated in this release and no longer be supported. Customers may fork the code needed for their specific use case from previous versions. The integration code will be removed in the next release. -python_directories=("$source_dir/templates/examples/examples/py" "$source_dir/templates/examples/extensions/py_lambda_hooks/CustomPYHook" "$source_dir/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook") +python_directories=("$source_dir/templates/examples/examples/py" "$source_dir/templates/examples/extensions/py_lambda_hooks/CustomPYHook") for folder in "${python_directories[@]}" ; do cd "$folder" function_name=${PWD##*/} diff --git a/source/bin/config.js b/source/bin/config.js index 1b2f0b261..17080e053 100644 --- a/source/bin/config.js +++ b/source/bin/config.js @@ -22,7 +22,6 @@ module.exports = { devPublicOrPrivate: 'PRIVATE', devLanguage: 'English', namespace: 'dev', - LexBotVersion: 'LexV2 Only', LexV2BotLocaleIds: 'en_US,es_US,fr_CA', stackNamePrefix: 'QNA', skipCheckTemplate: false, @@ -34,6 +33,7 @@ module.exports = { EmbeddingsBedrockModelId: 'amazon.titan-embed-text-v1', LLMApi: 'BEDROCK', LLMBedrockModelId: 'anthropic.claude-instant-v1', + LogRetentionPeriod: 0, BedrockKnowledgeBaseId: '', BedrockKnowledgeBaseModel: 'anthropic.claude-instant-v1', InstallLexResponseBots: true, diff --git a/source/cli/aws_solutions/qnabot/cli/qnabot_cli.py b/source/cli/aws_solutions/qnabot/cli/qnabot_cli.py index bf031a227..0e6c76bd0 100644 --- a/source/cli/aws_solutions/qnabot/cli/qnabot_cli.py +++ b/source/cli/aws_solutions/qnabot/cli/qnabot_cli.py @@ -23,7 +23,7 @@ @click.pass_context def cli(ctx) -> None: os.environ["SOLUTION_ID"] = "SO0189" - os.environ["SOLUTION_VERSION"] = "v6.0.3" + os.environ["SOLUTION_VERSION"] = "v6.1.0" @cli.command("import") diff --git a/source/cli/aws_solutions/qnabot/cli/qnabot_cli_helper.py b/source/cli/aws_solutions/qnabot/cli/qnabot_cli_helper.py index f0d522240..cffaa314d 100644 --- a/source/cli/aws_solutions/qnabot/cli/qnabot_cli_helper.py +++ b/source/cli/aws_solutions/qnabot/cli/qnabot_cli_helper.py @@ -29,6 +29,7 @@ class BucketType(Enum): IMPORT_BUCKET = "ImportBucket" EXPORT_BUCKET = "ExportBucket" + CONTENT_BUCKET = "ContentDesignerOutputBucket" def get_bucket_name(cloudformation_stack_name: str, bucket_type: BucketType): @@ -62,9 +63,10 @@ def initiate_import( :return: response status of the import request """ - importdatetime = datetime.datetime.utcnow() # get current request date time in UTC timezone + importdatetime = datetime.datetime.now(datetime.timezone.utc) # get current request date time in UTC timezone # get Import bucket name from the cloudformation stack str_import_bucket_name = get_bucket_name(cloudformation_stack_name, BucketType.IMPORT_BUCKET) + str_content_bucket_name = get_bucket_name(cloudformation_stack_name, BucketType.CONTENT_BUCKET) # create an options json config that includes import options that were used str_import_options = { @@ -99,13 +101,13 @@ def initiate_import( # check status of the file import response = get_import_status( - bucket=str_import_bucket_name, source_filename=source_filename, importdatetime=importdatetime + bucket=str_content_bucket_name, source_filename=source_filename, importdatetime=importdatetime ) seconds = 0 while json.loads(response)["status"] != "Complete" and seconds < 90: time.sleep(5) # wait for 5 seconds and check status again response = get_import_status( - bucket=str_import_bucket_name, source_filename=source_filename, importdatetime=importdatetime + bucket=str_content_bucket_name, source_filename=source_filename, importdatetime=importdatetime ) seconds += 5 return response @@ -128,9 +130,10 @@ def initiate_export(cloudformation_stack_name: str, export_filename: str, export :return: response status of the export request """ - exportdatetime = datetime.datetime.utcnow() # get current request date time in UTC timezone + exportdatetime = datetime.datetime.now(datetime.timezone.utc) # get current request date time in UTC timezone # get Export bucket name from the cloudformation stack str_export_bucket_name = get_bucket_name(cloudformation_stack_name, BucketType.EXPORT_BUCKET) + str_content_bucket_name = get_bucket_name(cloudformation_stack_name, BucketType.CONTENT_BUCKET) cfn_client = get_service_client("cloudformation") # get OpenSearch cluster Index name from the cloudformation stack @@ -151,9 +154,9 @@ def initiate_export(cloudformation_stack_name: str, export_filename: str, export "bucket": str_export_bucket_name, "index": str_open_search_index, "id": os.path.basename(export_filename), - "config": f"status/{os.path.basename(export_filename)}", + "config": f"status-export/{os.path.basename(export_filename)}", "tmp": f"tmp/{os.path.basename(export_filename)}", - "key": f"data/{os.path.basename(export_filename)}", + "key": f"data-export/{os.path.basename(export_filename)}", "filter": export_filter, "status": "Started", } @@ -163,23 +166,23 @@ def initiate_export(cloudformation_stack_name: str, export_filename: str, export # put a export config object in S3 bucket to initiate export s3_client = get_service_client("s3") # boto3.client('s3') response = s3_client.put_object( - Body=str_export_config, Bucket=str_export_bucket_name, Key=f"status/{os.path.basename(export_filename)}" + Body=str_export_config, Bucket=str_export_bucket_name, Key=f"status-export/{os.path.basename(export_filename)}" ) # check status of the file export response = get_export_status( - bucket=str_export_bucket_name, export_filename=export_filename, exportdatetime=exportdatetime + bucket=str_content_bucket_name, export_filename=export_filename, exportdatetime=exportdatetime ) while json.loads(response)["status"] != "Completed": time.sleep(5) # wait for 5 seconds and check status again response = get_export_status( - bucket=str_export_bucket_name, export_filename=export_filename, exportdatetime=exportdatetime + bucket=str_content_bucket_name, export_filename=export_filename, exportdatetime=exportdatetime ) # download the exported file response = download_export( - bucket=str_export_bucket_name, + bucket=str_content_bucket_name, export_filename=export_filename, exportdatetime=exportdatetime, file_format=file_format, @@ -188,7 +191,7 @@ def initiate_export(cloudformation_stack_name: str, export_filename: str, export while json.loads(response)["status"] != "Downloaded": time.sleep(5) # wait for 5 seconds and check status again response = download_export( - bucket=str_export_bucket_name, + bucket=str_content_bucket_name, export_filename=export_filename, exportdatetime=exportdatetime, file_format=file_format, @@ -217,7 +220,7 @@ def download_export(bucket: str, export_filename: str, exportdatetime: datetime, s3_client = get_service_client("s3") # boto3.client('s3') # get object only if the object has changed since last request response = s3_client.get_object( - Bucket=bucket, Key=f"data/{os.path.basename(export_filename)}", IfModifiedSince=exportdatetime + Bucket=bucket, Key=f"data-export/{os.path.basename(export_filename)}", IfModifiedSince=exportdatetime ) str_file_contents = response["Body"].read().decode("utf-8") # read object body if file_format == "JSON": @@ -277,7 +280,7 @@ def get_import_status(bucket: str, source_filename: str, importdatetime: datetim try: s3_client = get_service_client("s3") # boto3.client('s3') # get object only if the object has changed since last request - key = f"status/{os.path.basename(source_filename)}" + key = f"status-import/{os.path.basename(source_filename)}" #logger.debug(f"Getting import status for {bucket=} {key=}") response = s3_client.get_object(Bucket=bucket, Key=key, IfModifiedSince=importdatetime) @@ -331,7 +334,7 @@ def get_export_status(bucket: str, export_filename: str, exportdatetime: datetim s3_client = get_service_client("s3") # boto3.client('s3') # get object only if the object has changed since last request response = s3_client.get_object( - Bucket=bucket, Key=f"status/{os.path.basename(export_filename)}", IfModifiedSince=exportdatetime + Bucket=bucket, Key=f"status-export/{os.path.basename(export_filename)}", IfModifiedSince=exportdatetime ) obj_status_details = json.loads(response["Body"].read().decode("utf-8")) # read object body diff --git a/source/cli/requirements-test.txt b/source/cli/requirements-test.txt index 8bcd6e65a..654c631d9 100644 --- a/source/cli/requirements-test.txt +++ b/source/cli/requirements-test.txt @@ -1,8 +1,8 @@ docker~=6.1.2 -moto~=4.2.4 +moto~=5.0.13 openapi-spec-validator~=0.5.1 -pytest~=7.4.2 -pytest-cov~=4.1.0 -pytest-env~=1.0.0 -pytest-mock~=3.11.1 +pytest~=8.3.2 +pytest-cov~=5.0.0 +pytest-env~=1.1.3 +pytest-mock~=3.14.0 pyyaml~=6.0 \ No newline at end of file diff --git a/source/cli/requirements.txt b/source/cli/requirements.txt index bbae5bf3c..1237ab16f 100644 --- a/source/cli/requirements.txt +++ b/source/cli/requirements.txt @@ -1,2 +1,2 @@ -boto3==1.34.47 -Click==8.0.4 +boto3==1.35.5 +Click==8.1.7 diff --git a/source/cli/tests/aws_solutions/core/test_helpers.py b/source/cli/tests/aws_solutions/core/test_helpers.py index 11f2eb95e..58f40282c 100644 --- a/source/cli/tests/aws_solutions/core/test_helpers.py +++ b/source/cli/tests/aws_solutions/core/test_helpers.py @@ -14,7 +14,7 @@ import os import pytest -from moto import mock_sts +from moto import mock_aws from aws_solutions.core import ( get_aws_region, @@ -65,6 +65,6 @@ def test_get_aws_partition(region, partition, mocker): assert get_aws_partition() == partition -@mock_sts +@mock_aws def test_get_aws_account_id(mocker): assert get_aws_account() == "1" * 12 diff --git a/source/cli/tests/aws_solutions/qnabot/fixtures/cloudformation_fixtures.py b/source/cli/tests/aws_solutions/qnabot/fixtures/cloudformation_fixtures.py index 760e3c075..a1d8079ce 100644 --- a/source/cli/tests/aws_solutions/qnabot/fixtures/cloudformation_fixtures.py +++ b/source/cli/tests/aws_solutions/qnabot/fixtures/cloudformation_fixtures.py @@ -15,7 +15,7 @@ import logging import pytest -from moto import mock_cloudformation +from moto import mock_aws from aws_solutions.core import get_service_client @@ -48,6 +48,6 @@ def cloudformation_stacks(): @pytest.fixture def cloudformation_stacks_fixture(): - with mock_cloudformation(): + with mock_aws(): cloudformation_stacks() yield diff --git a/source/cli/tests/aws_solutions/qnabot/fixtures/s3_fixtures.py b/source/cli/tests/aws_solutions/qnabot/fixtures/s3_fixtures.py index a06c31d71..4996bcfca 100644 --- a/source/cli/tests/aws_solutions/qnabot/fixtures/s3_fixtures.py +++ b/source/cli/tests/aws_solutions/qnabot/fixtures/s3_fixtures.py @@ -15,7 +15,7 @@ import logging import pytest -from moto import mock_s3 +from moto import mock_aws from aws_solutions.core.helpers import get_service_resource @@ -72,7 +72,6 @@ def mock_export_event(*args): def get_s3_fixture(bucket_name=None): - # mock_s3 setup s3 bucket s3_resource = get_service_resource("s3") if not bucket_name: bucket_name = "test_bucket" @@ -82,6 +81,6 @@ def get_s3_fixture(bucket_name=None): @pytest.fixture def s3_fixture(): - with mock_s3(): + with mock_aws(): get_s3_fixture() yield diff --git a/source/cli/tests/aws_solutions/qnabot/test_helpers.py b/source/cli/tests/aws_solutions/qnabot/test_helpers.py index c173d8fe1..39d8e3512 100644 --- a/source/cli/tests/aws_solutions/qnabot/test_helpers.py +++ b/source/cli/tests/aws_solutions/qnabot/test_helpers.py @@ -16,7 +16,7 @@ from pathlib import Path import pytest -from moto import mock_sts, mock_s3 +from moto import mock_aws from aws_solutions.core.logging import get_logger from aws_solutions.qnabot.cli import qnabot_cli_helper @@ -32,8 +32,7 @@ logger = get_logger(__name__) -@mock_sts -@mock_s3 +@mock_aws @pytest.mark.skip(reason='Test fails in pipeline; passes locally.') def test_qna_import_json( # NOSONAR cloudformation_stacks_fixture, @@ -63,8 +62,7 @@ def test_qna_import_json( # NOSONAR logger.debug(f"{response=}") -@mock_sts -@mock_s3 +@mock_aws @pytest.mark.skip(reason='Test fails in pipeline; passes locally.') def test_qna_export_json( # NOSONAR cloudformation_stacks_fixture, @@ -97,8 +95,7 @@ def test_qna_export_json( # NOSONAR os.remove(export_filename) -@mock_sts -@mock_s3 +@mock_aws @pytest.mark.skip(reason='Test fails in pipeline; passes locally.') def test_qna_import_invalid_stack( # NOSONAR cloudformation_stacks_fixture, diff --git a/source/config.json b/source/config.json index aab36acf5..43c91adc8 100644 --- a/source/config.json +++ b/source/config.json @@ -2,14 +2,13 @@ "region": "us-east-1", "profile": "default", "publicBucket": "solutions", - "publicPrefix": "qnabot-on-aws/v6.0.3", + "publicPrefix": "qnabot-on-aws/v6.1.0", "devEmail": "", "ApprovedDomain": "NONE", "Username": "Admin", "devPublicOrPrivate": "PRIVATE", "devLanguage": "English", "namespace": "dev", - "LexBotVersion": "LexV2 Only", "LexV2BotLocaleIds": "en_US,es_US,fr_CA", "stackNamePrefix": "QNA", "skipCheckTemplate": true, @@ -21,6 +20,7 @@ "EmbeddingsBedrockModelId": "amazon.titan-embed-text-v1", "LLMApi": "BEDROCK", "LLMBedrockModelId": "anthropic.claude-instant-v1", + "LogRetentionPeriod": 0, "BedrockKnowledgeBaseId": "", "BedrockKnowledgeBaseModel": "anthropic.claude-instant-v1", "InstallLexResponseBots": true, diff --git a/source/docs/Blogpost-SimpleNavigation.json b/source/docs/Blogpost-SimpleNavigation.json index f90c3367f..5c6a86060 100644 --- a/source/docs/Blogpost-SimpleNavigation.json +++ b/source/docs/Blogpost-SimpleNavigation.json @@ -35,7 +35,7 @@ ] }, { - "qid": "Pressure + Flow", + "qid": "Pressure+Flow", "a": "Commissioned by the City of Tacoma. A two-part installation, Pressure + Flow is a reflection on the power of technology and communication to transform a landscape. Pressure is a sculpture inspired by the inner workings of a steam engine, and Flow involves etched writing applied directly to the historic Prairie Line rails, excerpted from historic documents and letters.\n\nAsk for more about the art, the artist, or the medium for additional information.", "next": "Shipment to China", "r": {}, @@ -50,7 +50,7 @@ ] }, { - "qid": "Shipment to China", + "qid": "Shipment_to_China", "a": "Commissioned by the Chinese Reconciliation Project Foundation in partnership with the City of Tacoma. This piece commemorates the early Chinese in America, their labors to construct the transcontinental railroads railroad construction, and their unjust suffering. It consists of an antique train truck and abstracted representation of 100 ash boxes, a reference to the Chinese workers who died while building the railroads. Ask for more about the art, the artist, or the medium for additional information.", "t": "", "next": "", @@ -71,7 +71,7 @@ ] }, { - "qid": "Where the Rails Meet the Sails", + "qid": "Where_the_Rails_Meet_the_Sails", "a": "This paired sculpture and mural features a finger and thumb clasping a steel needle, followed by a trail of stitches. The title takes its inspiration from a late-1800’s promotional slogan for Tacoma, and the mural elaborates on this era in Tacoma’s urban development. Together, these elements tell the story of the Northern Pacific Railroad finding its end at Commencement Bay and the growth of urban Tacoma.\n\nAsk for more about the art, the artist, or the medium for additional information.", "t": "Where the Rails Meet the Sails", "next": "Pressure + Flow", diff --git a/source/docs/LLM_Retrieval_and_generative_question_answering/README.md b/source/docs/LLM_Retrieval_and_generative_question_answering/README.md index edb7536a6..ad10987f2 100644 --- a/source/docs/LLM_Retrieval_and_generative_question_answering/README.md +++ b/source/docs/LLM_Retrieval_and_generative_question_answering/README.md @@ -1,4 +1,4 @@ -# Large Language Model - Generative Question Answering (Text Generation) and Query Disambiguation for Conversational Retrieval +# Large Language Model - Text Generation (Generative Question Answering) and Query Disambiguation for Conversational Retrieval QnABot can now use a large language model (LLM) to **(1) Disambiguate follow up questions to generate good search queries** and/or **(2) Generate answers to questions from retrieved search results or text passages**. @@ -54,7 +54,7 @@ With QnABot you can use three different data sources to generate responses from: > **_NOTE:_** If you want to enable S3 presigned URLs, S3 bucket names must start with `qna` (e.g. qnabot-mydocs), otherwise make sure IAM Role *...FulfillmentLambdaRole...* has been granted S3:GetObject access to the Bedrock Knowledge Base bucket (otherwise the signed URLS will not have access). In addition, you can encrypt the transient messages using your own KMS key; ensure that when creating the KMS key that the IAM Role *...FulfillmentLambdaRole...* is a key user. -![RAG using Amazon Bedrock Knowledge Base](./images/Bedrock_KB.png) + ![RAG using Amazon Bedrock Knowledge Base](./images/Bedrock_KB.png) @@ -67,6 +67,7 @@ You can also choose which LLM to use with QnABot: Utilizes one of the Amazon Bedrock foundation models to generate text. Currently, the following models are supported by QnA Bot: - [Amazon Titan Text G1 Lite](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=amazon.titan-text-lite-v1) - [Amazon Titan Text G1 Express](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=amazon.titan-text-express-v1) +- [Titan Text G1 - Premier](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=amazon.titan-text-premier-v1:0) - [Anthropic Claude Instant 1.2](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=anthropic.claude-instant-v1) - [Anthropic Claude 2.1](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=anthropic.claude-v2:1) - [Anthropic Claude 3 Sonnet](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=anthropic.claude-3-sonnet-20240229-v1:0) @@ -78,7 +79,7 @@ Utilizes one of the Amazon Bedrock foundation models to generate text. Currently #### Requesting Access to Amazon Bedrock Models -**NOTE: Access must be requested for the Bedrock model that you wish to use. This step needs to be performed only once per account in the region where your QnABot is deployed. To request access, go to the Model Access page in the Bedrock console: https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html. Select the models you need access to and request access.** +**NOTE: Access must be requested for the Bedrock model that you wish to use. This step needs to be performed only once per account in the region where your QnABot is deployed. To request access, go to the [Model Access](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html) page in the Bedrock console. Select the models you need access to and request access.** ![Model Access](./images/Request_model_access.jpeg) @@ -109,7 +110,7 @@ By default a 1-node ml.g5.12xlarge endpoint is automatically provisioned. For la Use a custom Lambda function to experiment with LLMs of your choice. Provide your own lambda function that takes a *question*, *context*, and a QnABot *settings* object. Your Lambda function can invoke any LLM you choose, and return the prediction in a JSON object containing the key, `generated_text`. You provide the ARN for your Lambda function when you deploy or update QnABot. -#### Deploy Stack for Embedding models invoked by a custom Lambda Function +#### Deploy Stack for LLM models invoked by a custom Lambda Function - *(for Kendra Fallback)* set `AltSearchKendraIndexes` to the Index Id (a GUID) of your existing Kendra index containing ingested documents - *(for text passage queries)* set `EmbeddingsApi` to BEDROCK, SAGEMAKER, or LAMBDA (see [Semantic Search using Text Embeddings](../semantic_matching_using_LLM_embeddings/README.md)) @@ -155,7 +156,6 @@ When QnABot stack is installed, open Content Designer **Settings** page: - **EMBEDDINGS_TEXT_PASSAGE_SCORE_THRESHOLD:** applies only when Embeddings are enabled (recommended) and if ES_SCORE_TEXT_ITEM_PASSAGES is true. If embedding similarity score on text item field is under threshold the match is rejected. Default is 0.80. -- **ALT_SEARCH_KENDRA_INDEXES:** be set to the Id (not the name) of your Kendra index where you have ingested documents of web pages that you want to use as source passages for generative answers. If you plan to use only QnABot text passages or Bedrock Knowledge Bases instead of Kendra, leave this setting blank. - **ALT_SEARCH_KENDRA_MAX_DOCUMENT_COUNT:** the number of passages from Kendra to provide in the input context for the LLM. @@ -168,7 +168,7 @@ When QnABot stack is installed, open Content Designer **Settings** page: - `{input}` - placeholder for the current user utterance / question - **LLM_GENERATE_QUERY_MODEL_PARAMS:** parameters sent to the LLM model when disambiguating follow-up questions. Default: `{"temperature":0}`. Check model documentation for additional values that your model provider accepts. - **LLM_QA_ENABLE:** set to true or false to enable or disable generative answers from passages retrieved via embeddings or Kendra fallback (when no FAQ match its found). NOTE LLM based generative answers are not applied when an FAQ / QID matches the question. -- **LLM_QA_USE_KENDRA_RETRIEVAL_API:** set to true or false to enable or disable the use of Kendra's retrieval API. When enabled, QnABot uses Kendra's Retrieve api to retrieve semantically relevant passages of up to 200 token words from the documents in your index (not FAQs). When disabled, QnABot use the default Kendra Query API to search documents and FAQs. Takes effect only when LLM_QA_ENABLE is true. The default is true (recommended) when LLM QA is enabled. Note: this feature will only search the first configured index. See https://docs.aws.amazon.com/kendra/latest/APIReference/API_Retrieve.html +- **LLM_QA_USE_KENDRA_RETRIEVAL_API:** set to true or false to enable or disable the use of Kendra's retrieval API. When enabled, QnABot uses Kendra's Retrieve api to retrieve semantically relevant passages of up to 200 token words from the documents in your index (not FAQs). When disabled, QnABot use the default Kendra Query API to search documents and FAQs. Takes effect only when LLM_QA_ENABLE is true. The default is true (recommended) when LLM QA is enabled. Note: this feature will only search the first configured index. See [Retrieve API](https://docs.aws.amazon.com/kendra/latest/APIReference/API_Retrieve.html) for more details. - **LLM_QA_PROMPT_TEMPLATE:** the prompt template used to construct a prompt for the LLM to generate an answer from the context of a retrieved passages (from Kendra or Embeddings). The template may use the placeholders: - `{context}` - placeholder for passages retrieved from the search query - either a QnABot 'Text' item passage, or the Top `ALT_SEARCH_KENDRA_MAX_DOCUMENT_COUNT` Kendra passages - `{history}` - placeholder for the last `LLM_CHAT_HISTORY_MAX_MESSAGES` messages in the conversational history, to provide conversational context. diff --git a/source/docs/LLM_Retrieval_and_generative_question_answering/images/Bedrock_KB.png b/source/docs/LLM_Retrieval_and_generative_question_answering/images/Bedrock_KB.png new file mode 100644 index 0000000000000000000000000000000000000000..a49330e22cb1c22a3166b09dfb296b1aac9f3733 GIT binary patch literal 150615 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 $hK6-~(*7+#!!JP67o`Bd$DmO< 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

+tR}{XPE~ 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 **_TIP:_** You can leave default message unchanged `Sorry, the model cannot answer this question` because it is also a pattern defined in `LLM_QA_NO_HITS_REGEX`. When the Guardrail action is intervened, QnaBot will respond with [Custom Don't Know](https://docs.aws.amazon.com/solutions/latest/qnabot-on-aws/using-keyword-filters-for.html#custom-dont-know-answers) answers you have defined similar to when QnABot can't find answer. + + ![](./images//provide_guardrail_detail.png) + + - Step 2: Configure content filters (optional) - Configure content filters by adjusting the degree of filtering to detect and block harmful user inputs and model responses that violate your usage policies. + > **_NOTE:_** Please carefully note the strength of each of these filters. When they are low, content classified as harmful with HIGH confidence will be blocked while content classified as harmful with NONE, LOW, or MEDIUM confidence will be allowed. Please adjust the filters as per your requirements. + + ![](./images/content_filters.png) + + - Step 3: Add denied topics (optional) + - Step 4: Add word filters (optional) + - Step 5: Add sensitive information filters (optional) + - Step 6: Contextual grounding check (skip) - As of 6.1.0 of QnABot, this feature of guardrail is not supported so you would want to skip this step. + - Step 7: Review and create guardrail + +2. Once you have created a guardrail, you can test it with your testing data. After you have tested the guardrail, you can create a version. Once you have a version created, you can copy it and alongwith ID shown in the below screenshot. +![](./images/test_guardrail.png) + + +C. Input the Guardrail configured in the previous section into the Content Designer's settings page: + +Finally, input the copied ID into the field `BEDROCK_GUARDRAIL_IDENTIFIER` and the copied version number `BEDROCK_GUARDRAIL_VERSION` from section B.2 in the QnaBot Content Designer settings fiels. To do this navigate to the Content Designer > select the tools menu ( ☰ ) in top left corner, then select Settings > General Settings > Text Generation using LLMs > General Settings and update the settings as shown in the below screenshot. Then click Save. + ![](./images/update_settings.png) + + + +## Settings for Guardrail in QnABot on AWS: + +Below are the available settings to configure Guardrail in the Content Designer's settings page. + +- **BEDROCK_GUARDRAIL_IDENTIFIER:** Enter a pre-configurated Bedrock Guardrail identifier (e.g. 4ojm24q0yada) that you want to be applied to the requests made to the LLM models configured in the CloudFormation parameters `LLMBedrockModelId` and `BedrockKnowledgeBaseModel`. If you don't provide a value, no guardrail is applied to the LLM invocation. If you provide a guardrail identifier, you must also provide a `BEDROCK_GUARDRAIL_VERSION` otherwise no guardrail will be applied. + +- **BEDROCK_GUARDRAIL_VERSION:** Enter the version (e.g. 1 or DRAFT) of the Bedrock Guardrail specifed in `BEDROCK_GUARDRAIL_IDENTIFIER`. \ No newline at end of file diff --git a/source/docs/bedrock_guardrails/images/content_filters.png b/source/docs/bedrock_guardrails/images/content_filters.png new file mode 100644 index 0000000000000000000000000000000000000000..1abc8fce826bb0ba477f263d0d085499f5a2ade6 GIT binary patch literal 217904 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

2Xz>b$2)V)}S;oTvQTugQH$-P4c2a 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%0DAU)8NuHXNjE8MX{f60V~!H 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%0A-gL#TyPBw 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�NI1; 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

b#k*5BR? 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ð&<4O`dj&S_0!c`B~#0^Ij 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

+?bD0>>6dmo$G*%okZyG? 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

MlSGMbv2(9CZ< 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 JbmjKLe*pPdkG%i@ literal 0 HcmV?d00001 diff --git a/source/docs/bedrock_guardrails/images/test_guardrail.png b/source/docs/bedrock_guardrails/images/test_guardrail.png new file mode 100644 index 0000000000000000000000000000000000000000..23036feabb337beeddcc4ef615d954511b613808 GIT binary patch literal 188462 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 HG`;^1qL5)& literal 0 HcmV?d00001 diff --git a/source/docs/bedrock_guardrails/images/update_settings.png b/source/docs/bedrock_guardrails/images/update_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..eb871f914761cfb93705aae4d7ff539bd1527966 GIT binary patch literal 145928 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�ACGym@DF*^30{@6br8z_0LqoKQ94HAG;;^J< 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

A+4V#iK~)*d$zf^%cGfBz{aj} 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 d@G9~k_$Z!y{{a0#v`_#5 literal 0 HcmV?d00001 diff --git a/source/docs/bedrock_knowledgebase_rag/README.md b/source/docs/bedrock_knowledgebase_rag/README.md index 007daa5ef..b052e3afb 100644 --- a/source/docs/bedrock_knowledgebase_rag/README.md +++ b/source/docs/bedrock_knowledgebase_rag/README.md @@ -1,10 +1,10 @@ # Retrieval Augmentation Generation (RAG) using Amazon Bedrock Knowledge Base: -By integrating with the [Amazon Bedrock Knowledge Base](https://aws.amazon.com/bedrock/knowledge-bases/), QnABot on AWS can generate concise answers to user’s questions from configured data source(s). This prevents the need for users to sift through larger text passages to find the answer. You can also create your own knowledge base from files stored in an Amazon S3 bucket. Amazon Bedrock knowledge bases with QnaBot do not require EmbeddingsApi and LLMApi since the embeddings and generative response are already provided by the knowledge base. To enable this option, create an Amazon Bedrock knowledge base and copy your knowledge base ID into the CloudFormation parameter BedrockKnowledgeBaseId. +By integrating with the [Amazon Bedrock Knowledge Base](https://aws.amazon.com/bedrock/knowledge-bases/), QnABot on AWS can generate concise answers to the user’s questions from configured data source(s). This prevents the need for users to sift through larger text passages to find the answer. You can also create your own knowledge base from files stored in an Amazon S3 bucket. Amazon Bedrock knowledge bases with QnaBot do not require `EmbeddingsApi` and `LLMApi` since the embeddings and generative response are already provided by the knowledge base. To enable this option, create an Amazon Bedrock knowledge base and copy your knowledge base ID into the CloudFormation parameter `BedrockKnowledgeBaseId` and select model the model using the CloudFormation parameter `BedrockKnowledgeBaseModel`. -In addition to answers generated, QnABot also provides context and signed S3 URLs to documents stored in S3 buckets that knowledge base returns in it's response. The security of the S3 bucket governs whether this link is usable. +In addition to answers generated, QnABot also provides context and [signed S3 URLs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html) to documents stored in S3 buckets that knowledge base returns in its response. These signed URLs are a secure way to grant temporary access to specific objects or resources within an Amazon S3 bucket. -With this integration, QnABot on AWS can answer question and it's follow-up from pdf files such as [AWS Whitepaper](https://docs.aws.amazon.com/pdfs/whitepapers/latest/aws-overview/aws-overview.pdf): +With this integration, QnABot on AWS can answer a question and its follow-up from documents stored in Amazon S3. For example, from the [AWS Whitepaper](https://docs.aws.amazon.com/pdfs/whitepapers/latest/aws-overview/aws-overview.pdf) file, the following questions can be answered: • What services are available in AWS for container orchestration? @@ -14,7 +14,7 @@ With this integration, QnABot on AWS can answer question and it's follow-up from ## Amazon Bedrock Knowledge Base Models: - +- [Titan Text G1 - Premier](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=amazon.titan-text-premier-v1:0) - [Anthropic Claude Instant 1.2](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=anthropic.claude-instant-v1) - [Anthropic Claude 2.1](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=anthropic.claude-v2:1) - [Anthropic Claude 3 Sonnet](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=anthropic.claude-3-sonnet-20240229-v1:0) @@ -30,11 +30,11 @@ Before getting started, please verify [supported regions and models for Knowledg ![](./images/image1.png) - Configure your data source based on available options. Here we will configure data source for S3. - > **_NOTE:_** If you want to enable S3 presigned URLs, S3 bucket names must start with `qna` (e.g. qnabot-mydocs), otherwise make sure IAM Role *...FulfillmentLambdaRole...* has been granted S3:GetObject access to the Bedrock Knowledge Base bucket (otherwise the signed URLS will not have access). In addition, you can encrypt the transient messages using your own KMS key; ensure that when creating the KMS key that the IAM Role *...FulfillmentLambdaRole...* is a key user. + > **_NOTE:_** If you want to enable S3 presigned URLs, the S3 bucket names must start with `qna` (e.g. qnabot-mydocs). In addition, make sure the IAM Role *...FulfillmentLambdaRole...* has been granted S3:GetObject access to the Bedrock Knowledge Base bucket (otherwise the signed URLS will not have access). Finally, you can encrypt the transient messages using your own KMS key; ensure that when creating the KMS key that the IAM Role *...FulfillmentLambdaRole...* is a key user. ![](./images/image2.png) -- Upload your documents in S3. Here we uploaded [aws-overview.pdf](https://docs.aws.amazon.com/pdfs/whitepapers/latest/aws-overview/aws-overview.pdf) whitepaper to test integration +- Upload your documents in S3. Here we uploaded the [aws-overview.pdf](https://docs.aws.amazon.com/pdfs/whitepapers/latest/aws-overview/aws-overview.pdf) whitepaper as a test. - Sync Data source and Copy your Knowledge base ID into the CloudFormation parameter BedrockKnowledgeBaseId @@ -46,7 +46,7 @@ Before getting started, please verify [supported regions and models for Knowledg ### BedrockKnowledgeBaseId **Optional** - ID of an existing Bedrock knowledge base. This setting enables the use of Bedrock knowledge bases as a fallback mechanism when a match is not found in OpenSearch. -For example: + ### BedrockKnowledgeBaseModel @@ -58,7 +58,18 @@ For example: ## Configure settings for RAG with Amazon Bedrock Knowledge Base in Content Designer: +- **KNOWLEDGE_BASE_PROMPT_TEMPLATE:** The prompt template used to construct a prompt for LLM specified in `BedrockKnowledgeModel` to generate an answer from the context of a retrieved results from Knowledge Base. To opt out of sending a prompt to the Knowledge Base model, simply leave this field empty. The template can use the following placeholders: + - `$query$` – The user query sent to the knowledge base. + - `$search_results$` - The retrieved results for the user query. + - `$output_format_instructions$` - The underlying instructions for formatting the response generation and citations. Differs by model. If you define your own formatting instructions, we suggest that you remove this placeholder. Without this placeholder, the response won't contain citations. + - `$current_time$` - The current time + + To learn more about prompt template and supported model for these placeholders, see `Knowledge Base Prompt Template` in [Query configurations](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html#kb-test-config-prompt-template). +- **KNOWLEDGE_BASE_MODEL_PARAMS:** Parameters sent to the LLM specified in cloudformation parameter BedrockKnowledgeModel when generating answers from Knowledge Base (e.g. anthropic model parameters can be customized as `{"temperature":0.1}` or `{"temperature":0.3, "maxTokens": 262, "topP":0.9, "top_k": 240 }`). For more information, please refer to [Inference parameters](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html) - **KNOWLEDGE_BASE_PREFIX_MESSAGE:** Message to append in the chat client when the knowledge base generates a response. - **KNOWLEDGE_BASE_SHOW_REFERENCES:** Enables or disables inclusion of the passages used as context for Bedrock Knowledge Base generated answers. - **KNOWLEDGE_BASE_S3_SIGNED_URLS:** Enables or disables S3 presigned URL signing for Bedrock Knowledge Base answers. -- **KNOWLEDGE_BASE_S3_SIGNED_URL_EXPIRE_SECS:** Determines length of time in seconds for the validity of signed S3 Urls for Bedrock Knowledge Base answers. \ No newline at end of file +- **KNOWLEDGE_BASE_S3_SIGNED_URL_EXPIRE_SECS:** Determines length of time in seconds for the validity of signed S3 Urls for Bedrock Knowledge Base answers. +- **KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS:** Sets maximum number of retrieved result where each result corresponds to a source chunk. When querying a knowledge base, Amazon Bedrock returns up to five results by default. For more information, please refer to [Maximum number of retrieved results](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html). +- **KNOWLEDGE_BASE_SEARCH_TYPE:** Select the search type which defines how data sources in the knowledge base are queried. If using an Amazon OpenSearch Serverless vector store that contains a filterable text field, you can specify whether to query the knowledge base with a `HYBRID` search using both vector embeddings and raw text, or `SEMANTIC` search using only vector embeddings. For other vector store configurations, only `SEMANTIC` search is available. For more information, please refer to [Search type in Knowledge base](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html) +- **KNOWLEDGE_BASE_METADATA_FILTERS:** Specifies the filters to use on the metadata in the knowledge base data sources before returning results. (e.g filters can be customized as`{"filter1": { "key": "string", "value": "string" }, "filter2": { "key": "string", "value": number }}`). For more information, please refer to [Metadata and filtering](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html). \ No newline at end of file diff --git a/source/docs/bedrock_knowledgebase_rag/images/image2.png b/source/docs/bedrock_knowledgebase_rag/images/image2.png index 3caec986d2810f33d8e1646b939fc5f3393e73d0..18e549f0d050c0daaa18ec868844776e29053d65 100644 GIT binary patch literal 155036 zcmZ^L1z23omM!iUg1ZI@?(R;4yM_?lz42fTfuI3`Htz1O!QI{6-Su_uoq6-;&ZIef zr}|Xwa@l+Bb^4o1v;+bi_{opferX5@q+$zkaV1%C zaWW-GJ5vj569@>IZ*f22)l_A1dv{x|qA+BjCJL_*3DjApN{P)Is^F}S3> zFv23-4!)_Q)fc*|aReu1|N992A@5M!=wE71D$wpcN6$S`)BJXt;#hvITK z?|#5p)-}P}8pn~$tQXjK!xFSf%Jz#4BM{PR4MMA(M2iAFMj6M~eP&BcfL-E!mw)ya z0~~ULkr$k9UroYbd2Mwq?5B%X1=3)*4Aol<6(Q~-6C#O-a~?0k@F9X!qP#s`HGZ5k&jaN)iT{MeR524k6;Q> z@asc{(H`R!zElTQ0-9AP@Jt{9v1$#1hsXehrX$fFEd}1rPkvqQ4q*wwFwm}D-=6dd zi9{SSmPigiCxA_wRT-53NsWR24YgE>6n46tQe3`=8ge1A3;J|0fvC5b@i+$uv`vJo z)MEzan4a@H4^9vEMil*UTZy`i(~QUQtUWtCHYsRhphIUl>v#gy5Zec#To@+=CnP8Q z$sqi$@5U8cCdF@NAP@5teKV-)@j1OyXG%#v0(J*xo z>JS405i=>qL-xc_XmT-T-^hQv?i%ds?Q(N;bZm5ta75mQakSc&+m7hhk30PND3KZS zK^BzF6BAn<+Am_iNCp zSTv|KOlao_nZ#CRu<7!CbT7Ja*tXpsb>i49-#Od0PEr-#JxM{QKcGLM_lkpxgNtK| z8!bdpx0_a*J}&%Ns5mudnQMtW9ba&)+EmPysi5hmv0I3nPpavg4{4QP8ECm>sb;Y> zg*Q1haW#!)aWd1K&6}B1yj>cXsb1`&V5OCudtAsk#xx^T_8gPZ^@()?FXuZ~Pksb2 zA}vBKPb^Q|Ol($$Tg3VC9&PQOnX;vNUyh{vmwsOb4YfF;nMn&@6rd^Bupgi8s{TU+3x;mSZbZO!DF*s zylcEgJUk<*wsOf+$&7A|R!a?6&5q7b-PJns#k;xU3X58IV=L3ax@EIPE9olTPj%y^ z(cn-Mo^4wO$}VScszJY9RxP-`ukVt2KVbHNk?`@3Px&1 z#4p2lE_X>&gx4|;I~@w__nl1Ydzwh>kDVqRHtW?J1)XM{b{j|?eLL8Ua>^sh4Lr3x zLIf4uz0RC3^tRnQkhixF)z_xiKVCI~k%X&e3DSBFjl7TdWG=Ut2`Uu_a$B4WJ`-1Gs03iB;L4{(81lMu2M%WZ$Ee0=bDd;e_ZO)op0o_54kcZ*Lo{bJX=Za~Xy!xa zu4Gwg>zgbb$`Ff)?ry0bl2BsZtrqj$%nqKW`ltGnZmF=J%&oN&HnIybRq}N5yz+`& z#v551R-0}1{=9K16)>)ypg`qP8aLcq?9o)sA;O)ev#>j6OnuBS%-|Tk7*{G(nkMR> zRFMb*uqOW8bUt*CszTXtc_a$YAe^|Fs0hVKMPbHlB-J1rd>#Bjc0NhdOfO}_T-BYC zA!UcJcTq4g4DlRhvX0oB5boJ|6co0WYgH1Y45aGBZ~I-R?7v6&sc9DPP4 zcO9K{H4lpQ>MDJ)t<<|M&0RVVW;i{pE@n_lul03XBI=o3mP@YV55s2KRxxTas1@1m zY*yOQTZN~#2Y16RJ-PVomR>0zq&p&sldZXqSFTFFYTCDqRhDO;4Vs?p913ect36EK zGJezLt6i{Lu0w75SYP7Vw0Lts(Vdx+=|_z0%7MckiX6Ins@Hg_^UbFJMZZgbLf<>b zFK4*v+Rbk9IftR4xM(S>*(kCH^wCr3X#2ROY1G^B*=P7U=uwyygJ`ehti-&SqnM$f zQ^Q14P#Dj>{Ml@0lrwk=4V&b_Lkmz}##h}~(vy*!tC8huMXX0tLMVjkwl$($mNk66 zbB&EUfEv`>&bnXmv#slO!dqYsaEQ3`?coO;&236%D!q9ifhI=;7d7`aXD^2v=tg*X zVPnbhKr_q`J#Cy<)kkChXvV3_$$hsqZIoBoRn*yN>+?jn-%L(PB$K3J<7#br$);ob zc9Eu6sh*`-Og8Mdl~m~dD}Q(@?@t#*R@W;WzLOb#kGFftM^<%e)nm_ z$!+<>pn2Ejbin)OnNVL;KXv)da*LpYpm$62N(Q_I`ij7i56`*zvGLHRKMj(i9LQ3j z!3%$*h_=*iJe47hIEx@8Vw+Q4dLcxbpdlQ_ zodpF=#;%0hvHV`UCOL0o=b@FRp+x{p5Po$KbNay8Dj6?1A_#IU2{*X%@bKc{sa92& zhiup+=qS31D|-~E*PdLfJK^o;Taph_HL$*?uZaGiU>ez&s0G35>t_=!S<{anA?U$j z1PCZdObBRj2on4U5o`eg^RF-j#5?dEtntPGA>hGxOz^)_I@Ev1!px>a|92Q#;&(z( zRdHEa@Lko|(Zs~o$=uF)?5qC_1O$|jg_@SL*2fQg#&$MLMqlhcn=k=v?0<_u2mtuN zK^qfiBQk)EwXG8$K#<~JDfqzQ-;bFo$o`eY*-DT?>!T8xxSgX385a`^6AOh95*Znp zfa4caJ{1Y6{}Km(6QnSAcDCnZW_ELPV{&6>vU4J_7621#Z3zn-aIb=^Cd9+eCGf9e z{#VTZRP^7H>P{w(;&wJ*L1&@=8J7PN{%7QW3jV7|t^X;Km5rVEpJo0d>K~%N+rX#j zXaO$H=yxXyu?jH%uV??2UV!;`5C5ab|2>@ldI}y-AtV9j|35c`kko7LydWS%AY>&( z)c}x3sjyzyy*NFJ{!K7YFm8w^CnrH0)v!AGs^%Gh3|OQf6{1k_41i(u=OBvi7 z4r;&V`*-suPEK}?Z!rn(M;@1tPL76-j(oZIn@FYgo?;QhVPwAkN!QXb8lp|NH9ZY=x#0f%?BM3@IqA*-nIrUwjuFp zBqrHkE(A(&{fuCGjsEZKe;4Zze)@k`?01C&qanI$So}9x{#rtMeUIDU`tK`Drwo}+ zh?QIO38IkQ z$~5-hv(VcA(Kmb)% zHT`NG{Wfn@zEyxX+hwvbhUuf_KBs-`)@ZW0LTUpox7}(qJ+_=|)`B{f&lA8;3Fm5v z@rTqEE==G{lec2Jlfd7GI>a3&(|M%E6xFJK`jC4&j3mJ1g!KK^Nz3B{A_W$Q?@G!> zJVk@^Yi592k(Q1@^I5cV+erL|ix|QNdJZn(6Mg7?B zogp3%16h=}KFOzz=o8aKdk04h4r-RghPX;=JhjMrc^eLlzcu^dcqTWP(jkttJ4y)} zD6)Ax3E1I1`ODHljQT1FrOd~G#T`p)1ZAOAR5?|mtn5*AHZpx!C$kRa?!QzNSr%zK z7$sCvpZ{v|Ax&Z1LLM)hlt52UpGu=x%XPFO`Y&t$D+~&h@`BUxUVl|%h+kx6SxTF| zoH^laqR44`>opf-MMllDl{`3GM74*my6Bn$3*o|ik>JW_}5@xJBS&G}t z8|i1|w409!8g^PD|H~>RgY<;StlnJ^PIk?=A2ohx{am1Dj<9RJTn!Qe^3*yU+U_qM zN*5^QCV0)|e&Z-qRo{7Skn&xFJ z3K^s{40z+?<-^Bb2p6zCDOjeeO;u6=)R5mM8S&gS9x@iF=CFth3m+{h>d+~d>U66t z3^F=UJg#T<5G}?0b+bTd)=15yMF$kSXS=x7dlZ!e6?hbq-^DGzFflQS84WWLaQ#hq zjvOP$sdT;}jfIobLP^}wbQCMMg6LoC&WL>N*xS&c)eAp9gGl^;twfA(2ugaY=vkmb zjwIdyX(|r}JtV{^5oapp|<+uLH2`Q=M~8eM^| zbi5XJJnE9=_1UNf6d-lFJMLnPdbv{>uINou*MUZ zbv@-xcN7$gE?sW>(ej9PpsHDF@bgD-9scs?E1b-%Xo70ToJ!UtSUb?4QP$yFsWc4c zjN|SAxg^r=&tP;?`DVa5m2C>oj><-lcZ(gD<8C;jfX9`V$2DQ`uIwgA=i%nyp~uM) z>Ob56UmHD{+}nEJS3fLfUDc5kLDGU#gJ9dZ81J>(pGN_O9Aeua=BvwVAZ5^UrbSVJX? zDL-nPn&VvXIYv+yM|Ayb)h<(C!zC`Y{Lc5+`C)^4zUoiML1>YrX6A+8k7ownk~L4`;@Bx45hq3Y)qjNfig;=n8Jj^jhB0 zD5i1(<+?9&s3WMauhCxQH$NV=k5l7nU zJXVm)KvJ#CT;IC>abue8nPdJ3FIZ|497dI~qs^g_nnP}mw_B<5@eBo6%sN`DhW5rC zo|8Mr^ldA24X)3*OX^m#Ki<`B4Mgj&*i487E%tB*Q##`vp?E&sRotVDY2>OoJU>-L zdg`}1gz2d_oU+&*%~ent1FuwCEG6l*$VeM`OqdPs`d;IU$9N%5mz&B~#hXb%_m1+# zS{4374(AitEj?MiihCFvUhYov%H0bjgOt*WeZ#tS*F@hisj&d!1i&%#%~TOW5WWxk zr<)a{VyD}cXUFpm?BQX8`0sAVYZ+M&_wN)^WZG`sFSk&xe2fi9NlAxMP9eLjoB08G z2UCT>Nsd3K+zO0Zra8fHO+i8y%Fy-rnC5(Gcr>LUEVUJ#y6diG_QlDm*aZZTWxqqk z=UPzw#_hNBUaPrs-uL`9{?X;7G14%lYk!!_IHECJCwcP%haPvUc^rN5uAl9omGh93 z`!TLmsh21+b$8V8&il>*_p+JQK%MCN@Ok-Dm7sj-=N%quzNF*5vOv5`B3HS%G8<5t zdRvgY!Z%S<&uN{HPq7Jmv)PiKRmWjWEkmuyxXjn`+tIxOX2pZlJ_K!wt$QSaX}n{m zX4k8S&uXyKWS3ZU>WoUdZKuIWl)H>~lguWKdVV8>v%Os2Gh#k+;9B!_h)CP!J%RU?8!oG^7&#-6E+6RVs6Gj>JZH1{%@Kr5GX534x%Ji}-(gr-uZ?@6?P}L-)p-Sz<`I=o8<=>6! zkP)};QFE?ZcoUHS)|`wOriD zDKhB~bunr+)xzg->fqK-W}ii{A#MHzaK&XdL_Jo@dw47ijp4Rk9`~l4^xT-*psb(l zS2Y`Y-@cfu9_BW*x#p^rQ)PLa%jS7P(Xvzf_)b*2@d3Nd*VJADIAVAMFN7CBa3lVKd?G|zvv!UPd&Wo zj78nEr@EFlz?ie5`C1Wcm^Y+yKWyNMy%512v0k82=0Hf?YE_ND_&ks`7QH^d+HzkYyZga)*eY%rPzlDqY?0G{>1vovLPjL^+kt=!Uf6FCM;yHSn(Qv%3b{*Dkh} z)R*$|^-i8CKMEHC_U;p@4NtI;QH2X(o$Mx8T2dMgacc~ucyGQEzArfigA*Kgk1n-> z-F!xv7kAhB&-vv?v_aBA4fux*tfiD5Ueaq=xXl|90ZWc&v&EeEaV%%IKo&#cVw9AI zwdB&_M61BsQBG{GATzi90hc_WL9^G#me&zv2g=^js2Nh1=?(oa9*QZA^9U!-2UmyX zy+es?NMa1B6|$AxF{T-jZXJR?(O6y6(dvC< z3Qx5J)bkI$Ep9bdLc z?w@|3?cfDIiG8)6KO!D(vfjtsX}BWUA2R#8`_)*h=~idpjQrVTy3*b8{>Z1JnQ-=n z4k4A(dilXOT)#;d!5JYsh+NHWHlFk1=!Lq$^EumkzFaT&!;_>+u1x7DsgR={vg?D$ zbG}|h@zMNET?${Ne(OVK)_8GRz_lQYVsi(Ym_!H3dKI9yPj;_RVsUl%IYV3^yg)vV zws4iR*y{du$6Ux_vhi?o^=glKVDRH9cd?=TD~Z0Kuac{^LCz^LO+14xHG*-@9~QBQ zGxga++63hq8hKJU9yjA$qPMqUlJ~)MF_E?5;tzCE!Qa}pY*mj7mE^@2dh~HdzqMLV zL*_(bn{2WQcL2c!S<7O6Ef(FL*GTGFv(RoR35-wT+UYR6hm2vKZNBOB#lxVT&h6C2 zz-gSS@n`92#ik1jH&J<`j(FzFe89hR?W5PrwA4!?#k zd(bYjuTK|;d16T)ZlmZXcM}X0Z=0W63ZrmQcMcx-;0Z4hIKA^)dAaI|5#9m;kj(VO z-5CB+nkXRAzBC+VIC6x{Z=MHgJJf46aHA|*1lI;)UpNG+_*~74T3*&#V9U5dKFn0? zP+7t^46kjQY5ip8Ph1J!9*oEIdO#;KW#fD>3Tt+~(?Z=)njIm9ANU17N{9%8qJ%N>aPZ*?DsHCxr766Zbv~-W`akvNXn2ry8GOPI9a6n{57n=@D0Z17L zT=~(YkTZ#GJs7{B$Rv*~B99hY3>AZKXXr@?W)Ti?+!x-3ziLN`4<|+1 z%`tBd(N&oY7Y8XEx^JdR32`;20a0IC>$V0G^-0B|iu5W{@}msBzo!5(&dmRS8!(6w zB@*g^N)6*}BhE?q5An1rBHoBjP9ERKD@02Q>D?W5yc0N`;PBb^xsM?=awXpE&*el` z+byfr9xpHlPqn2);?2o>8hlS-5&vc%?2;d4wvuvTvl~I5O&8>RET~16iMlsGpI~4* z@|48d=kqmqt69T3T#GX^CVGo-}2SX`8isV|N|ID_uJ@QTDjI@n)?70}~p6`NCqIlG0)? z8}r^SElGV~u&0FI#QgQdBVvqA>{awv@8Hcc{1k5I+(fx8=lUJw@;vDSkxoa! zkO!4)ro=&*MTE!@(Yag#nI8% zG~z6(l~P@9MNu6P;|12*M#8i) zi)!wbXs7UbBr(S9r=M{Umi#MPulww~;rcD8Ru`UFiS6u?tk76Bt(-i9h(&ll@+gF(nlNPEi31k3O27?bIYqxMD-Wp{>2x~xX@h{_yTk$6M18_#rDi%+3F|R+J$$kAf8dti&Te|6gG+O z)o0W9b)1>BO24k_R2S%G#oT;o*DCU!bPGX)v{q^g9mw0vlEerJsVUN|c15m^WH#3K ze5Ku0!|qfTe~|INJFfxMSsXI87`Di1*SsKC`dp$FDAfk4(QB%pk?@i~tJl+CkQg!U z@taOCPz!ba=)AwQM8k+9D_vhSy2lcM5|rtP>(3~$Gbx7xc(^L4k*{8n#+IP8 zK7R_DrBJiy4nF|RFh7%oHk9PZC-+!aVt*ZaYi9w!q7R%$VwQSbTmkVu>R>Il?0#L_ z>?7mhV_P(f*LW5R?1>7t?aD`Nq^Fl4$LnNS?NaiqnlxMOYtwaw8IUx6q6D%#Q3|*Z zF$>EzMHn8mx!e&42jdE1R7s(c(yG7zIjgF@%G`9C`Cu1ggz<3pve6Pr8^E1^UWY#` zQeQ*K?{wquj@w=cb8tz)nu7kTb{s1|cv{U7Fh9gx6jI+45|Sw;-@qU|?~-&w*N_;7r`J zRtB5rE5^6$_NSn+8XYX8Z;-9o>!4(gd^$sCFU82w{1fA@yL}H~hVPZMii!K1PnUe& zOQkte7B?9H)-PSBgndN++KvPuBvel_h0+=CN zxr9J$bqc~R-d{xLo%{%jq5xsjp{S87g0A`kV_y!Syd-r(?PGDU^>PFESW5yi1OHtn zs?}`cx0{iwl+ZU#8V;!a$Lq4jfjPWTUz-gyJYSv~u9Z&P$^lDrH|P_*{)8%dawZ1r zAk1gVfDYp^7C`9s@Q*~g7xD6C zffKp|s$3kG32*a>0f>bM@uuWZf$JOIo&5e7ePei`RSl4iuiEry_EoKh8p?z9Ghw)XVMJPwgx;M_g#50>B9rq5s~(uIXU2G4>{j(fX1vLukrco$S!*JUQju$h3Q4B;B9ZF2Ae;7kIYD%a_2jN+`g z)T4(4vq+=dz*31b7dLZ$P&L#-MMkDvN;W!s=U113<0O1-Cs+pBeDJM1+`73{dxI1h z+-a#smnY7f-1-_+ZLOn-tO-yQs{%UVK6Nu#tq2Yt%g8i;-`#ARm=z|66ZycO3-cMF zyL_#1f`D=`mZ7jSW_M89@FpIvrbsS%2en&JeNVh7{62F5hdj*p>HcTKk% zKq@gHM-+jj3r#$|+O@_*ZF?ws*yEt&lyW!D=&aD+EZSx-%R#8VE6fKz1~q*sQ0RCZtMY_2L`Ja+25ayamSS4%$4=PC|e1*qhTn z@EEr}w~k@Wuob?>A1T8!eUH-6WgShtkAgvClx`SDLESw!vK8bKVcU9tB;0;$RM#(t%3KSLt#I!)@^As(|PP62`#EwQ*5svF!D z5G1o>9 z(h6P{Baa9@z0-9+^)J`KH}jYc6t-~Q+M^Fw;kmO;@#$3 zhVMcPG>z5i`?xNzR+sYo*>t(yS_+Mx>}$`7@`E9BPsMTCs)wLH6b$yLW$q{$`e0;u)5{z&T7 zf`A`H6DwF%l442K&Ha#R>7<3)4T+-L=1@f>=sLlJGK~WYo@vv~2U-NW!Euk*5;sA+ z=e4ZXHoOqxEa9byuZaI@A9+|Be~CnjMXQ!pERKM<)Y{HX|3UlZISu58I%noiBQ++H(*>yE+yw zMM%AHhfK4Zjn*A^8vlvZy@8<^azc%JL}6w%lLh83q`8dL(^v31hVvTl3r_6W(%LE& z0?1o@dDg-*q(y8A1D}SIZiN$@%o70x0&Hgpm1buli}faXM1t;8VT85b6R=cI!6DOy z7T$}Ku93-H#f-g*snHcb%&eHJ!LGN(W3$D*Xs#MGyRM(~n}Z|D)R`T|=!Wr8dnDun zRdG=e8OR{bg-7uqvkhd^1{KL;529?evrM^?=8W$wI)^plpQG4yah8cQ@}>5Qufq(r z@U+V!nK#Zr@_8quaHj&r76W@74|wjo@ntLNx98BHZ+Gc^zuf5E7II6P)JYngADY=m z5uJYBychii@O2h%kBkD~dzXCP4CN%O`MD4x+H&RO2ccKjfW%wV*o6;$Y^_{ubk`1o zitLOqynci5{U%U_Up&j}t=JY2eZLHrbJLV8o>8k>EojAKZ|fD|u+?$9QLo8I{Nd_| zA^`4cB2KVq+O{xQfm>e!89?Zrc^dda9zm5QSwAG>k1d@i@gH2Lo(8#G;Hdh{9qql+H(;R!eBnIHj$( zzl6C`lziVtrU_8v#^&wLgqH~-+myjWmTUh2=F$cX#Bd&P{dg$sgK2K~jc3{BjKv-_ zXxU7}u2$Ozc@l6qXJ4zOdl%u7b)^q*5+a8ptl53KEfYpp`|xRa0oCyXc5%mQzRCNU zzN!5Y&)p7rn};Fy1!Qy(0CazmpAx_FS>e^J4oPx4hByMM51VwO}->#k6JTA@!GV z#L%6M0hy82+E>tC=J12p`E9mr*v-V#GO$wIz5S)evSgg`!{VujFJ<_Ow_&8DQ7BY5 zz3d^*M;H*`j78XIBepa)%(669_*KRS|GDVo@qBmLB}4C>9hQgU8T^KQ=X-^>Tg1eh=jDBxtoA`g=Dv3R{lJ|AC0_#pzL z2K5dMw|1EfN+0E&?VXA7nSBNHh|TW0l6JUj=HejUmT2Ux~pRO93mS<|K{)qgV3 zUxMhLIu81@vC!vsd5JDqBjb-0gFsmgB+HBxEXsoEm@JgDd?h!|*4|vGwB6)NeSfkn zRpa7@V7)DeJADlH3|8*}$F#iY#78P-h6$1;JAZ5))FeCJ&C$_CG5;K)16s!ACn5Qv zWJH>&*=Fv9AJU`Oui<|g*~@V9E77VF#SM^2Zv{}^CL0+UIg19hzhp{uI2P(0q`jXx z@DyS5O(>GPi=;sA3kQzw*m!=I?-xFhCl$b{Dr63klKIpOa1gsrA^WnP$fP_gsjjUS zp?{X=8zHENK=QS(VF)#j@t37xSsm)6aus)sD|gI|huz2XEmiuhJJuiqZoNInTOpUoJ>%tr%rO z&;w)wBd5<8q@OrM!n9^?UO)RD^^rSX?%2$iTNJelz*sJ^`)I!DF$=`jnFV?o_D`)w zKGJg#z!{-JB^x2QHM=}UIN%jBN>n&x0cF5oel^Q>$;&&GR}-%&-r|ON{}dGS1eP5d zUgxcZqs7x#H>2ksM*m2oyTzbg3r+-$Gf==CEFp_|{R^J=QFsS$NNfP`Y#L* zSIKKU`Bj~Cnx81J#lW0m2D;|MUclI8$I48D)eYYRrm7SCx~| z8-36k>b`bCV?G4nA}*knm1aOU?iXfI(hQBccY*Q`LWQp$MxOxX|5|?!D0*&vv3KQ=jup z4F&q#oY8Yl`Hju15qRD-#YDY4w0?J403 z4hacLc)UTlCMvj3++Ls13k({H zOFiz@hQk7%S=3rlP$>mvo<$-!0if%Lbu)FMwREyHq8XIOavOGHiiefn= zxFTZFllqvF^WNKk^N!9b+a}Mh8lq?y83U_$-5X&r$ZUH(i>8LwOL=>hfX_09Uyyy3 z$uCF0^f&knahMLT1{F$Ww?86CWhUJY2Hm_{$8Ytt-4XHQRS-FWqScAHC#(gSekB?r z>gWcSvrvhwCe<~(Q;#`vSktq?xXFUQk``NLCsqnXY%td18Iq_mWJ{)%))Q+!jeN0~ zs5eM|;rR-vKD#Xty{IBj17)$|1#iG0?|e|kW?^4bB7A`(=U{iQ{4$ZNu6n#|9x^9I zibbQ<KjjH_-u^HrN=IUhe&_%PMZ zcKD7Ga2HeJLkR@hj9&hS;S3FlyZr`Zj+%_<6v;r3vgf0dr4-d!nPyd`s`sy~x3-U9 zNbbRKVO@4hM#O1HCjohypIl=;8GhGp`36&sY$(6egmNOP?Qr2*cLAEd;vxc}s3Qy2 z5T)dH)B81JNgafd7|Tr{K~fad)xLo1Pkxa>t_XTFLWm=Emi`Nu+p3#S58kS+0Fb8& z`ZjaDNz^IBT!10EMbBOu?y6-z`}OeG+Yy9c*J<0=qfr1s^>yd76b=;Ljt#m|Au~`i z=M(N`+5570_A(%b@~F>4#FMoMCj9tH`?&tFok_&_phrpdy{)~9w}p z-##3>5Z1)2TfL0STP|0AdlI^I$@Jx*z@2S{4!&xNEdS`av6;MrE+D!t2ye%%b{yCj zB=H>K!%d`*-j)Wh{w8*6plOESW-njZ2mPj?jT)E9V4@RWU?HVthq$Z>Dw02tZy`by z;rsXE7AeIRsP${j7AfL zfv4x&+|)M-_Xdr39z%g(#q>#NowS3k;2I2sn4JxPwa2HEby5l?FG%<6D5nUiKkd^* zk-$(Z2zWo6t1|Yukn0I1>8G^oG9imwjUdh@WFzCiHwir6r8h`{z4N6l!C$5uKQ@;C zDnD%tFSm01j2WT;gApH$p{OfPYtY)c?SlO&h45z6jn6H?M)*%7=3fSl1d$&C?rga; zz=lz~LBaJ%DE$X{7HT(glrd^XdLN`zSSw8KORW-@^-4xdQB*Hd!*T0{${}Ge+r** zA$0i=;;wW4n_sq)0#PWH>!4U7Y$rr$_P_Z|2fE=lmNH4a_0Hn$6rY-pu?16aEK2OaTpM zVn(mi*`xkvqyM{J$}wQBCGGuOz4;&Z&;K;ruTO-`^@|qFzgrR=*S_zByInSYxP6n_ z^xF|Ymm*vy;PE7((vTCvAz!O+yuT4d`NgKSwUy0c2Z~O;I30^wg-oo}PnOxB^__3Y zJlW|~899l?GUXB98&=kt=c|2oi+3Q|zqA@QfaPX+!Gj0u8Gg)N7EIGRBWLj%Qq!)n z{ei`}MVAwY@k8XBe%%Q`c8O>GGVge6-|1o_DAMa$8@@ohrrCg_G@98hLWaE9Nc3g~ zPsmxa^?*}G$ox8@+Gd5eId@9{2MS!LSnbP~*c#uF>T1WIf388Y!Z!$McInE;r40t) z(rFbxJ)S)4XdQw*G!~1Ut#_AaBM!=&LH!Xt}4{DIR(?DG+|3TCUm?a|9%jBKy zzS&rLx~BXL8Ji0xa(Xfn3?^MC*GLmBy!-H|zr&yts&DfR^Bsrl_D%`^#jkP)$D2-S zSr9|PRI!Qym+dm0_@mpbfui8EG5{e9ogvFDeI zp?gR1l2JwzM~nIFR*q6l{W3_9+ppe_aVLgeRFl4j47byqxsimHD{n^>Q>$d$p<1U< zURKH_31&*)U0bTpc-xOc2S@&FfsfcT4!}oipHHmGVs1XcVbrD`RG(vPu6Nw-qY!NL z`mVZwR^T#}^qPl*G1-_GA3<6j<(LzC;M5_g>zr`gYxwY759WwC?hd_6^PZD(-0h=B zkJX$X-OTNO3Fy7jAs=vky`cO?Dhy)Kt5mrm=Al=okDs~q-kh=NPk!Izd|#dVWhBAC zaQ3D*w2gbfUsw~N^oOt=Q^T=~;zmz+R+HazRCL=wVioRoP-J9%o*Z53LQSmPw%h>o zX5Juhn4c4ji61kSGL^EqPm%H3-z9jg?iB92>Uw_O8A()ceQ6H(GMF-cGePflQ}`jd zN(=0aq_w4sk-ul_-kwA&acNrvy^aXNn>?2Qj+41c+$Or12)(XgVzU5y^z4>?_(}Z+}+9SC(h|q+$AovRfimU`BQma z&y+3Q_FDAY3Ew_*>Z_%=Mo#+vDzj0Op=@m(maa2+Ip;2dwM1Y|o{BM4Vpv$Vk{CHd z4Q8PID#jiP^kf!|0=yCMa-@{ldzV3vzHKBSFQ{fVg1QYPV4geJkEo& zXz#4Q;)kzzRqYz+*nm1-A+biJ^2-1jX|2sW3zen<0dvLcdbsm66CYOWq5_3_M*4CwGoso@2 zepk^CxxOT@dy6;E#cYj*+Wtg16IL6+HBy~PL`!CL^|1r``6-%zto#zUbk7a4_huzB zZxkdO%=Ye>VsCN}pUxju9+%O#xv~8b z%D8?l)YxW9rp;AAzve;kwhK%&47M%0TA@j4(Zb*)P@106>sCA0s9N<3v@z@C!q((C z(O4S2u_+&vy9+=)nw-8;3owTzN3p7Reby)+y~(|J@Lzu^CNZRa`g)rwuDgAVhj9?P zTW2t=+vFiB2qzprnw;Iud~~|tDT7AD2V5qrJsVYTv{|W+j^U8~+_HLJBm`B)hbK|> zjk0z2@y^eT)Ahpo*a1$F@6~gGPLOfM<0Ih|rWZ<6X><2lj>Tw{S$Vn{iN$oaPx>Ta z)QDX0RV3huNNW`xfJY(GcxZNX9dP>+iNtzGllQL~5e>}!+0Q$wDFB-TN>8Q3usJ$?9s9T?{` zc0pXA(Z3otIlpUXr(l(Q{mkRGUMZw5=Webutercz3gY-(@e9`=g~x(&U)j(X>x9Dz`WBo@fR&? z>d+3bsx9SJOc62OyK<9wkzWOL$W+AK)(&!^7}b{0HlMKtbmV}|si{H4{dtdUm!Gm( za06WhZHHdAV4WalUHD1~1bi7?mfYrMpTl8R5n-dX`&EuNV}y`!(?iPZBgc1(M~k@8 z`;%y%J$VDUZ|16~>%74{>Wg~M6fm$GY}tVES(7f~c-K#mngaB? z`L%q3O4i_2$Vh*Ecxt?*@=w*Bg8jF0cE4|L1D-%=h*+8=7EU+}>h4YP{pqdx0axr@ z+*{rB>PxGOJ7*O?8q=gjFmK5M#O8nF)PkQQF9O9z-Y1mVDV1f@(9gzK#p`S@`sZkX zG^BWns*J;ZNGw#5JFm-eez70tBe?|en4!Mse1NY*4adVxs-bKUw!VE4@6ca4;WYy> zc8UhS&p?+dSIp67pjjlj#&|H zzSb)3H*bhKpSeu@N=cM82Wh%UuQhvQx8_SXpKS8G8Y(rT>`8SK$v_zbY?{?r6VtdW z5{eNp0>3p8XB8t7lt4k=Iz0xDxT746#asJgA4Rl^7jTWOt}Zd|yR-CaF^;w#k02^x zqH0zgLI2s_W5TX5zXK1fT-O#a)_J`d}`Wri)b+PCSI8p4=Vzl2)vx>nTD>c|2-A1sA3_sJV>M6oOx~ zqTejofCO3E0-_o3R*__jdvKW&G=mZhuu0YX-;&2?)F9=ASvi#Sel>bgH&eH*b)wIn zJR^{BK*STHA$QCqD41r;xg876=Rq>6lo3^Q2;VN8^|^ldsNZFDSt~e0z9S^jU{ds= z9QUOPLCnBP-xI2QHT+kQGj=ZFDEi&mpycAjeaIq82+E`gD( zf}&8ck6dA`L0e4l*Vz|KPyIh_W)U?q5eG(k0qRolt2pgUerdjY1>$=cH}H_iaN|2I zIN{X^tj;3b`|M}9RbrIQVLp4;aUwiyV#vn|L?5!IFOeUA!QYHo@nj1mOwdL{W4}{I zAdAP8{RHmdEMzJ?Nw_E;Qf$6}DlonmyCVF3Y?@7(^(|aRpSA-k;;v#^OMWK|cVhpU z@^H0xa;^u{V)LiQ@g4Zick9@kZs(5ojiVUqUFksQhxDM2W$D2g+MbbRd;@O65i{<; zqWDop&AQSJL@(m!4PeF8?MHE-4zm+4YozgeOqEGY)11w7U~4;`8|hCg#@QS?`cjwM$O1PxyayT?JHC+uBtmrMo*tLP`V=-5t^$ z0wUcF(%s$C-QCjN-QC@Bh=2Ry-goc&-x$C+FgAPb_|_M5&2O$ZUh8^_pp6HqmkmT6 z|J`J1xPBn|EFEYLq_QOQe(LVk+>Z5Lvp=kj*Gg--B?mJ9#)Nhp$_2cmwRWXeTPC=$ zg0u*pztqnpN$8exqKZGyjs%NEKdM%D6yJYW?eHN1XzRdn$}oSk%NSH--8*gfk= zug9-D*+UWA%6nV#15GVv^@cdNr9z1@&D`%T83-NogPhnD?4+%s7R6JW%cwf@yHj>@ zkpz~_5N=@usQ~wzAa0x|uSLD%G6mGv0qhwSW5tC0yWS$Y4+#JZtx=kQ`RjA_Hi1zPkRp{|Y|BgLUpBEB?ayLiq1C=34O zV;0<}C}ge8-eHEVRmUPo?h;-invwxlxFn(Hf|n#<%sLsBLu`l;Es(6X7;q z<$u;{Q>;B&!ah2zu-$ehL{e)M%+LX!Q~dpH|0@mWy`ucxY|4LcGnn7bm7_H*Ua3FI zci*`B0jL*!ZVZ2CB&9=f+^J2a7n(2ez&OJCxxm7*hoY!-LQuL#c=-vbJBzLq#?u#GWuWLksxkj zZQ|uPQa3d#xtGBN?$m+FxDTQ{to8McdtF;M(kEP&3RIHmjKsCZWRx-31plj5nq&tp zU?R;#L?&%ok;(l+KpQ0rq7=J%R0H{{N;Ico_uq88_LbzI65ZYK>^e! zV1a6g+GFd^xWR6>lz_)hI;_BHFpkbNjm3U#_@j~{ywG#)QlUJ}!)DT7n|J;L5=#&x z5qBwlsxtOJ`fMx7)1XpX%9&DSH|hLhM zwS1;VO;8S`mU$rhJTf+7Jd_REe@~`={KfN|z*@}#hL8nZnmz#25tgpd7H6P`P3DRj z)U^c%!vo;;*E!L@>=_uo<?831?f?Gu!hR*A1&o!CaWu6UtR*E|->1ox9}Xpug9YnKSd4CEIn2~CAH_cv#gIpSwF@p<9C2xhkTN0~JQe@3=yV=v4z6xa4soQ` z{JPOu^EZ3>^Vc5&5U6COs=hT$r_OyM2J)O5ucRfH-IX~RTXVt91;2K{12TF|jgT%a zV`*2H==Zx*S^HCD9`K30cbl{X*i#j@AVQJj*;wk%k>^DTN5qV7t-xt<*7_M z##T7N|LgHX3Xm+>l#*ghovElVybGS{OZ}8E2u}C9i{miRFlN2?B2uRi@RIcncrFzz z(>*kYZ(b)U&5s?O{7`u%W#lJgAKi2qn__& z3`9Gt9|(GIIOaYmiz*7ffUbUF%*4H8Z1^s|XI&8pd+q)p-wJp!q(j$>$5^!0jX@R4 z4NS#Yab543r6?irsfkS8bT9G1PL&LWt_JpgNe34XZL&PdMx(eQr|-H(jn(dT>-lEo z+Xh>S7+#{nhQ;BA;!dIHu5ijzENQAkX>R!qbu!%fE&*p+=!87CeT<15Yg!Jw!v@ym zlT$>8awF-6%Rc4NRB}6w`^?PbtEa=FZ&gzcu-!tpDglf5rRNY3Gm{9Gjr*KBanW=XVL4=tJWDVH8t@c);6;aog|08LSrg zotyFLYc1M6%J;XO99K2&Cp<1Wqu2L?+MrIh6E3HMPWAEAzU$qG$H3(0O%!`Lm!Cbj zmuqt(Qr`Nome=krKW76qj8S4%(%n?cScE!MoXxc98mVq$*9=U~W{OzOn@@t-h+Cc| z;lIte4~B!rj$02_*7jkTF!Tt_QP*pFTD-7lybmGSdpOx|c8{;)Uca|EFyZ~W1QPWik(zpPkXm+Fyuia(0wMS6no^{#lK-lkG8upDJZ2Va^8 zEx_Y{1XW;FZJoB1Pt-GmHeVMO3bDV~Eu^AHqdk{9SLNfG4;c6vDee8aysiijkAja z7h(@zt%@~mi5jb(F8h|#LEY-h5|48XY7q-Lw6)HN!$ud0b7U>8qe)Itke{i>whnYg zDPJ6Z^4|zrmwK2xUD>$bSMaIP|KI@AneJ9|`O(0hwrWq~6}`9Uc7Jca$DkV1yO4Im zan)$l7BA-_yg~Rn{LuTdznl2tz#aY;?0>&7GPt=XwzeINeQ|ar=5&8&b=Azbg85%Q zLINj^?8Zg&Thpkk6pHs+RC9{7q~xX zKd|zPtWVq0tfeqfC11D;kV4i8mPP(belJaj%@h>QKh<7QqS_74kN1sJGqBhg)Bq_G9|$?vM2QL2Eu& zie3~xJ!2qveFl-mY&Z=Al`Pwx{jAq3p2rG(X55%J@De#`+ZEo=5L+z7JO!T~isy;7 zoM1Pl&;pB^lY+OU6X2RJ&Ld4+Zu@H21t{11$>kdz<-}Ij^#c_Po9nwSJ!CpS95DY+ z?B;#tIV&!YAsEGC2TGkiDn}bwGlo7N{4RrPQb3m>B*@1EF^3N0mBM`w%@cAap#L_R z5_eeIf)t@0B{S%0>-*CkMn8%I0WUEQsD@yEmlo2tC(Px+Rvxo9P%EE~2!2yFR}AgW&K>RS(Mr>sd<8ckC{S_aquLea*~U1z>S|pc zLDFaSwT3wMn&jq2N4_-VXK6iyKDu+^XIcg^a*Np2J@8jYqrdwolqXo9qK>u5A?>A4 z#6WLgy(}gxMb!;c51tJaI~G3@f>UiHV*>-@`gbgyK4U)((+>flI>q)^b4rSWuc0F; zn-R1Oh3~e9Qg3aanX@8(7>GSs*O|UW@TvAg=zroG<1SmHqH)!6J;G$ASzBkUH{-gc zK!M-HTVrvF_YmDm8m$}%ZFiDFs=Yt>g^ZQN)MK|s>9`MWW)}4I?${~NFwbzp(lw|a zqEeWt&$S+zT+f7VT3)uE8y+<(PG8KI`E@(b;$*+74sTNHaCtExbpA!l?EiBifdBB+ zbX&0$-l7-qa#b*A?J7c6gpyT&LL3?E{Se}-TN;5t8sIz88}F^0UN8{pV6brG0&z-N z*4rAT8EBNuX*8*&fwF3i40^X8E9*;f_dx*yQN~1tqyWkP(RkUcy>|wPDbZ~*APiVu zL~88_dRo&7T<}kYx0>%Tra75Dx)eGtpd(<4$Wcyyx5EsN#6S5)ib|TOqr1fT&_D}? zNE(ZR@3CkngH6jj4p9_48V9t9&Q=~aiW|Rho{)xBg!$(!++2p+u_-mff3Peo?66vw z!(OU#{31*P9og^#*Pm6G&3`7i!s!E<)h9S}Dzo>!QtLJU;fRH`O8oE>ATE)EHsE@? z6!+=i$zCc8Qd2!=uDzwj`C8t!`E>BfM42LPpf|2kP|V8e`qtF$1I65q$bkAuBG4wr z@Ey_ITz9ky=g2p6zW;J}bZ~z%Z+oG}B#Ohvus@xrEn7O3b4-)l=|b?#>g(2V0K($m zioX?TPs?i!@A@}jx7$OXbNV2v=rY)0DOhny4d zPlYUn_uieL&!#WXdVd)u6BOpNP}Rl@S$Kzv28}GV<*$`rC0c_mV}GoRY()X5mAs<6Qf+#76Lcz!96&P43-`*remE^(^2Q61Ac<%foTs478kFEKE z!b0H%&N7Yjn@E4!DJGGFdc(};u@Pd87i`*9+%CG#phsIZ*#fj_E;&97=!sqn?&zWK zZh`!Xm+(&ABL$X=j^YY~F=VAHc(av2oBHMRq_W|*%;M!}tfjqp2_i(cT=lP7WPTRX zN?d|eT>aF|jb&^!_45xM1|_>*E?5>Fu(xiSEpK#^$#iv)DFR9zh+1N7#q@)lq|84a zF4Pm(z}|7Yl6c5GE0#(Tke5^%F=M|>%_@J?swc}kS&GKqpoT-IiV(-05G(yEHho%9 zB)RAzNCZT~;*jG5TFQyM*eIdkfI|lX3iq3o9ni>0$|o!Si=FE-VUv*i?Rf2MliAW9 z(mE`N+mq$!jqc#V2Af^F5>E#h1RRnl@a=49C_Z~!jzm24iH;4%$jiH`#8m&kyWzD2 zUen&Z4*Oi~64nXhXH5DiKEXm%pp%;{Nl~;a)ve^h+N&J8lR&qkTKtpMSK$+8k=@nm zmgSVeN;O}~9mQ$d^#%isw?EjEbx{gKzQ+kCSE)O$Z_8j;2Y9xeSHu))4hVX7Q=0I= z+6udWG-rVdg*bE5FgrG8-QmFP!d@Oo33{e#@U}ZVB`x6(B z_ck2vkM#r`)`FErqvlA@8^Mg(x}API6=i5LJkNLfm-T?x*x`2g3&;!LL~CZ~mc_!p zR+O-TOCH+=BRn&r+gMfCI#ui?>lJ=BXIC8ra>IDolDRFpH-%$TJ``jGXt!yLTv`fE zn5FTMnV{E>S=*A48XlG`z2+|cH}7X_>K1CiVVy#q)|+PuNo*!@92mNxb>_=a0{%$G z8GQ%iemB6{QO`R<@$Vnl@EiWRd<&SDMI>*% zzb~H2i!fzvdVRM9aoj+P>;g@Dv3!_d)b#Lb7MvoVT=OfA8GEfOWXu{rS-eZZnv#iW zg}c1;U%^2DR}rNGlEBxOOzHK>@8dlzu;oA`)hR<)HOK?{h(ikel|s za+lj=`Pg!kgG7H6<#i~(f>-bKScbqg6R5Jd168m(Qz-brrjN}Yd}HSHEgBzbx22`! zjg!4DFIvrWGP{Mi7bF~{(5nwCk?Ritu_Hn%`J>qOKrEr%Rlc~dW9*UDysgRHX1WV(>}5RA^B1#&9E7~x*Q0qu~k3Y25yb*Ft{MYG#S znihQ0T~~qVV&}HT*=jSAv_=`5<@;lL>g76~9FSVdD1ivxBFR}AIwp8C2-^&e-TPZ0g&; zo%8%@cXKpP(vf5*WwSFBDVHTYk2GzHZ%b1R_^Y&xQ>T{LO36QN-n93 zc$m!X_MnbBLoze6d|2|H%OS;~d;DTf`ri=UzaTY%-|`61X|Sh)x?cVClMu|)d-@gH+W?)dpPo}HXbu$3cfkff`wskaLB}K&ceJTQoOo@89kgSfi^DF@Zu!}zB zzLt_jd_!Kh3;og5Ie^XY6bvV`AG-PI6LC2!?9z1F16JcqR7Bz@J8r!_(C-a{JcL~O zhH0eS{&+#GLa+PlT)D1r^i8n1kH`=i*l1T0hC4TunQ(SPm z3|ilk-Y^%*9%3{~IcT|lM8E%bg2^{dAR?rbk`$2oH}8~5=?RNDi=YR9dl3!9Unj^G zI@i;@kRjOs)A$Dvok{lEN0TfZ58-}-1fg9W;eH&U%DEQTtmmWK!<93;)5Vr&2WZ{b z&_@)DR-tdt+_@ciH~j#=s|c#G#pO0AK0Y36AY?>F@l)}%R7-0piABq3%{SU)6V_MNC zv1}a!nkZee5SKf{ET;reuh#Z`k(+xEys_~>OC5`{p{&O8+o&l_Ss0938Xyp;E3yuU z{|nE<9=U3pdy5wIMI)&x`Ub(!fu?^0Lg$i_#V5yVC?k}o6t*ohfiO-C8Qyj1qFMYM zUQzl4HN+KL9XMo=;}9-1G9QKmY!NBUw~F;VgS~~t3A28?{_{?;0=D($8-?VC%e2SV zUUive>mEvD(01mEb{?%pyi%G)fiq!r2T$sZZkBEfckf^1TmVrmGYAV!4fPt`_%#7? z03P-XAVU$^MjhOa@}zGi!0x+}44|v&LDd`Ne{ertFu> zX(tYih?mWCmdlKgW)>#Mm?iVAj)r@z)y<^}2O00?` z>x`?JA2m@AkIT(aGjtf~j&B{`R{jv9V5jC2OV@Jon`#-Nz!K*O{Le5{M*y53kr;_(cGTg+c_ zCC9yprFEnLUmOhteyD@p{e5GiEa!Y(K-ll2{WVssEcwKmn^Dag=$XWv=#%BIqcmz6 zA{(CK&)b!hQOGerZus84*h1A2KZqC5!Nu0^oUYGi%QCkcb?%E?OzpO3>BS zl``@|XRy?#7A%u4Cd$#y-|^AmM5AiZDBX=}vp1YQyn@B~>f8QAPOy3MN3*05!p|Sa z?%6qbNg+E)&Pb1JfTY^`Y>h8V)nc8=h@N1q(m;X`;ydD-5`}^&R`Vs55b^BIp3rDW zIJ7{a`fooY6je0?~+E$Abl!Dz&iS?hic$jW@-g{Hp+s$ZC>mN9nb^hf`l!Rnv0`1n21sBJTusrb zrDK4sY5z;7KXRS@I2Z*PwF8$3x{O7Eo2@W?AsL;t7AQEz^JLF4Ry@K$uRI?1sjX~m zs@SD`s$++fM3r088V=LGS_Qw~{J1(kTaZ95=c5rG{WqLN&>R8*K6Gi+zX+J6uzo*+ z-@e!?a@1>R#O}RWr{?3gl1i7;i!GxoO{@wksu$&-PGc0)>rZA4q>%5x+sc?bN8hvR znM&xTG-kGf6Fsx2{=C3XQU-UeNm@EAYUvb`PUqVbdLU-OPHB~DaPSc^ zcc#!Y{2(yg0|O}_bOBOOgC%m4{V|$JUjf?|<|ZNwZOX={`a^6QSzebO+|A-eAXkHX zE3`(0=yKX}+qJyB{E4;h%uv17G|?4&TxYnrIM<(bQ66f1KuT@S9q$*-*yr~pJV!># zp`g^dX8dolMUUt;Hm39z@#;m~$uf9YG?&0Eh-#} zD<$>kTl>pRmAQ+`){h>~UP>!d=JFo}IK?n#wey2`i~{evf~mvHw6V*gsVSZ(d!zQ3 zvB)Yi<5*4u(WxOxGdXN_Vulh~{0H^@l;?k!^FVBd$QVq^$7H~kkJf0imr_=0vDpn9 zf$@)!@kvvI0<`uRW7&c7279|F6ra-+lVb*@^+7u+oYu#3eo+Jz)g5_P(b-#c+SW|0 zmHambx+!Gl410h1GPwxgkp=Z3tk5Z=>Y?EM50KUiu(X{D*Ei$9!|3b&2OH~ixDa0) zDK6?5;Jh$F9V>nrKRnG)--yimu0dBIr}ybu#r#Z`^7Wng`@{SA+RwM=Xm_-U`nL>R z+=X~>JVinM0$hQu)FCN@)!pga@r(A$+`s*s=o$||^f~7FF(Lujpdj6A$ExWEr7WKa0%oy%C^e7eE22SMc_yn6=Py^Y=(d z^7y}U#(s~v_TyD2Kj9BumcM$x|5(TL5d{2!sE^~{R9gRIR05#$Wakw^^4}1eKQD}g z0_YmyC+oWW@4NihUx3T#W`oh0ll+}BM27w<`K6(GG41{3P7s*`&Li`p+l;{3=hvO5TK5y(Iri5Yh_P_EkW5Zn%i*%h9_v5?i8MD6`yz;Mb=*_3xDh#{i8o!sa7zq|301crNcVW6 zM|UUsDU_0bCmG6CrqLv4I1K(W^UN{%Ey#NDH@7`ne9Ua(XYSTenh=1Ww~v+MDGm%Q zyQDpwrQN#SuU@ou(+gQ&heKF}FswJ)-P}@YFb?$pVWfH(p5I7Im(LsXh}CH8Fi;=P z)?#%{07d6oDG)%p3E+don<}KmoyePZNcoqB+q}zJKG3xz$Z5Zy)!dgfP^$^v9veqz z*3)4Wi=zwtmyFx?bdmB#BKz*k{Ac7lngOa1Wq0Xi0v~|0!N#v#>(P{r_ zg$s67+u|A=LX!DZW?>P$RuA{ZcsnWdYBPYZ+I`ag!gf?hfl}{wgbTdit4%%8-q{OF zrWiMrSiD&dac(h}&s1%&Xl`8O9D8xKa>yv(6M{jHc2amqH3@($gNdxLtR<@RTc$Mf`UzG!=Zn|JGD*hiLNKnq&F z2LU(VZm?&nME~Fy#yNJ6Ac7o(+hGnIb?4Ly;Y-R@bTj?z1_TZ zk(OlbQqSTDP>RMB@jp%r{2lueCIBt7&C#DNo zQL7K8&T&vK)6A0NdFkJE!*2(}bsXTA+1hcMFGdtkt6s*-1Mp}5yWqsjyQTHVJQ-qA zouj#$@K%EB;A-~kRVUk!QMl4FL%3-sAA2xk1J``k|I~ofWLpqbEkH4gJ}as`F*%=>GES&aLUqlGnC- zeQ=}!Jf`vI-hA>4V-~$*@MRtt`!)9ZJ|evGwOMxWUQQn;n3dO}7qVC#5@1&Jt|sxaUJ+ z2O@z@7W#C^vL=CAgEw6ywk;n2^T|JKfcp~q6cvQgA(8EV{QYsPRcYZP_*eo20(@2A zfaM%X$014I{Biv13l->B9GzA|n)z}{7{O;!J^Xz-%+SZWqCpSD+OHJJLTg=%4NdzJLQ@fL4j6N;v_nD zhttZCd_X$)J03h+ttoq*A-}Ci!uV+8^Dk6L8B6bl+fgy@>D?6MVEr*uK2X zX=E!Jt4(#;C+5!k5b%SsZ8}{#m3vT9UDh3ooJ5DLjtF6sch3|LDc(#ruQAqQ6xD*` zSNo#JWgH4*`HT!JYCH67d`0jQcd6XfsJ9TChR7Mi!Trh0x9f%BE1Y026nv`{60cvD zE2Q@JPPuH;`D%Qn)Edg=dO~me?t9r@d1Bcmj}6a_h?&ymc+yz(E&4xtecQcl%N<+^ zqI>?Or;opQ9rpal>HgLwLJF|mFJGvzkgZOj5$^p)(%>@yF^+KnhftM#2^AW|oY*OC zf!TX{tqsVYQy0klPC!;XS;rh=>5ZyCK@Ylt<>T|n;Y{)&I~;_u40YF3GF3=B!W}DW z=wX)J-uI;GiG;(99U!U~4_D3MBh8WvT7|&xV$3Q=L)Qo?xMiJ^yxllN@jH$5770`B z)!Igp`M~XP>n|x{THMj>^}NB&PrP#Y!oe}P7;xAua*F)UE@|ot9X?>Ev3AyAM*p)m zlV*JG%AG4uqJ4!A&I41r1087`Sv6kT;0NV$TYJK8dnpP3D=9dd*OWhh+k3qQq&%=) zLVX~rha~dz9^$}3k4InCPe1J_-NifXdrXs$a=_LT(Fi9d%jsE%vt^e8HlIQXxI7uO zTRS`+v7{>>YRG^y$rHVHq-#Gk9c>k0_2?IOQn}gn->`g!5kRU4Upaoav5-ODYy8qq zek7#e|ImCNb@bvb^cwWDy{UxKMRHiHJOrxt`Ur6{;pT*gB8`_mnTyKc*aC%>1OajH zl5@I9QPIBL#tbc(tNaZe($5z2)CIXbq>``r9n~byyr3$4NKD5xz7IdJ(GbX>x;XTs zjfQfVQ#{Oc+Sm;yOVsO(AC91yfnv0kPRq{S$qn|f#~qhrt~jXN2c!yQO_{ay$!d#) zB?JbqVP;}&dNK9d2O`%!=jECzm`XKU-uowlLy zt(#iHaxEVtE;QrslptgNi>A*p1~{}OuHnu8fhFbi?uRr5_P-MQr!&cor+ zC{@74Eo>&MGEfbA)xx{&L9UrW+p(m~(bT;wt(5y{-`MoZ!b5$-Bzc4j?v~_}a811{ zPq(cmXOs5E!xM(}dgh0&TPps`V?Sbos3b~AHI=DDSThbV;K>Kh<8A* zS4SJ{CNhZenH<&QL)@0Oqb|!1-HtX`d5kSB<87Lm-JNbBy+8T!n!k5Lu#)(m%sV6} z=TbA9dx2ALKJvTxKC;I#mk{Z6#5f*ab*`0P&N$3@WJT(R)|=YrZN#6&d}?GKTB$PA z=F232*+9ev(Iyk*__L?)(#jFjht)AX0p@!E-kF*==@qh4fvd6V24aRg%4}F=9lQ_m z7NM68j1?k34pG$MOg%o#cS0dDl{IqEOvrraRCvWKtm))T>JbMT&0(LEud;$bKI%}~ zXlSYooq#A7(E&d{!ha*RTlDrKeShkEmzCwCFe_Z_o}0Hrb4BNZsP@4oTtMcDt&7;ZL5dHpWMAdK-T}`T z!=8~QHAVgP4^z1h!tdx#;qP?^EPzS{-R0M>(}?h5Bks6f>c-=uzdpB9MY$xz@gUslSGnqXnqI+f6^|z zakB$$I|Os{gRalmO0!dRS=I1HV&I2;Wi7{#!nKASs7A9*1;jiv?a5O(C-0Whcbt10 zyy6qiakx5eQBUl)yllQk=Z!`VpI#j>+%{%0kJNV0)INQBXc7V&CYW&K5{6NbcdXzgd+$MN1h^CBRJ;jT#+cwzK%26B|3~{HR-i zL(=_ZP4{EvWM1e3Wj*`_mFKygh=Bec`803eU;8D~V_tuKn}LvG{KWVMv_Dh8woBM3 zO71~4>cMNY%OhJZ`}LzD~{2pe58Df%b=+CAuyWR91l?6I0CmP#TTIE&$Ix-P0!!bC2vhZVE9vv#mr<*Wo) z@j)-`BtcWfO5xwwiNGwc~T<)R%#N)0>0-9ztLypu0m3ZLz$ zRFWz^VE8BmiMTIQQPs6Ks@hx=OgtX_-<>bFM;`q(;G7(V+_OL_vN(QA-|n`bSYLEG zf}`)qvW>C*`EcJ4u1kv^1jqBZ)RfGZ4`9i(J30NkJmLTm0!S<$Q00PAP*=T=*@O; z42~!hZ{#xV3FaQAnWqbk=ya8$I%R{ez9@Idmr&u@&Y;=7Qq;89-;}X^cIB_j46ol; z2{FE*I^tueu5q2$J&c}(fQla2WKkhfqIp^ zXGm;ycHHCk?3T00pse-2@Q@0Q%zmz;km}_~Wb+7=q?OI#S4G83wgR>z;*je_JSAxw zPH2%8)b?4KZ%K;yO0+?5ebGHDspmLU8bn;U*8WC@CZIGyV{JK{8=J2T7rrYY1|lw6 zz;Dwqi40<@KqPUsuV3LNxQlIAI*gKrDN@x97QRy+c8 zrLr^WdM1kmCfa1m_JO_p$agFQHU|06EyX zt!ozy7tL`rR~61>2|v(uvOJnlb8Ev?fegqb-V%M zp1;S|-zw*mCIv;1cD;fgM|3h{@Y9Urv3ze6mc`^D4Xn+ST1wXxZZz1FUTK|Vq&^uKKJvt?Tg!& zFD(+pNDtyf3>C=8F`_ESa)Wcxpo;eL$hN-DQcWBta7C8`GFqPp06It$JbT01igJe& zhD#Y$8MN%wWbZUh~Hn;;F2mLV3P^AJsYOj-@g=G#leUrO?kES!Mo zQHp^P@+#KEksnj58IkJKNhzrd? zXYz`Lk18&wV6?Rhk}x3@U;%dRs{UlL!8Z`$ON2JEcN^;UVK~b z8T#s~9tVLvQHO}LOjOaoo@Tti$Rvni$->^>3cEA$8s-aaJftUv-Zu%+uCu3*`23%R%(0Bk-8EKB=)^7-kUK@6ntZNgMK%x=4;}hzf=ugWu&IPF!&u zJfSV#MspxZz&`O=`f(>m8c$n)bX>0>4L-QoC# zr)-`u<-tk?qEvE?DAnf=h_m_f($=MRr_1RAq9CCZfl~NK(uF#Q+i&Q2Bu0x$&urLn zk;EFP+|$>IO5;RYl245azkT;7vL9udj*leG2t=52P$(k3pBDWZ&t##(*+s5(UJ|Qz z_n=*hg@z5b@}(WKN&O?>T!Pi0d4T1s`tRH~=1ljqlDO4&v7J1}q*l9gCX{b>eQgG# z<}qvB{9N!e=*i$H2AW*jiEY+Ol z+TLjDFrI!R+{Nc{B@_RZYEvl0Rz?}q^xWVD zxSYOuHo_jVpZFdg91kA9uD-0?AbRr%u5qM+g;D;;tp@JEH}m=BljXhr{SL^?SxwBXx% z!2Cs2CU?o72gpL)dh>3-HTc$EZ58M6{Ius?TkwbV(s+u5{s1=4?NL9I%=-T4BSCY- zfz@G#V*BGNfHc8#i#&q!K4~KEKW_RTD9~SSP>8p?#{bau;M@N`Dk>5fvL9AGS^kgo zLr=M;bE#6yg5);@X@)Z|q+P)t|>l zrSMjcVijhpMWqXr$o}#C{ygBH*RaNoDtgKDQMt}-e?W1e5&WTKxl%++-JUSJv)6kM z5S@qt_COR*XVA=SvV7`66vq!Q0F)+MrJ{3(Ndw%p(oO=+c{tv~g6!f9N7Tg|T0k@s zJCb4(R}+f(-%i`J6tZ=={jZPbJrc0!G^HqmF*APyhJE+4;>jQBbHpysgs@)N%ovvI zouXZ>T{yq$eq0GRp(%A^ahuBd|DVK~8U(|w#-hU>WXVEx@X1mjftxe;720}@%_?f4 zVt;xN_D%4uD5@T(!48C4wH~2ni*qPI%9Oaje2@>{U6eaffvi%mGoO5H@;s*s!(j{4mON0N#{hTb7RzQgmiM+5|6TvD^`&Kwx!GHB`(@7Z%uVU z5=|~qXUzn5ots>IYWrE46Ewca)%1xjJ&Juqwc4vxt4SDhFfPOjN6ZPadoIGvNCRy6 zSx`ClUy%9V-YzzpWkEf(u35KV>cmsWy<5RoR32cRh%|jPt%=tKDeb2~FGLCRIp$pM zu$th@u(ojQKx}5^bGMKV{3pAffx{hs^TvLt^QY~b37rG<@qMtD!?(`3)FU>#Q~=cH14O5?3+NW0AXBlzn@dNzg`C`M)Tc9-SE+_0 zDz>k$bCtCnlbUT@`koVdydVaZEV4P^mB)ZxJM+I~JRS+*i0@CVz>h+y`;ZWQ#uX)M zu$JGE#4WK$6>oBzbstD1Z!%48`bK%Y;1E!#NGnja!k4d|=T00r#!2&S2;A;&h1;RQrL0 zpo5k>Pb}5%yHXJ^UrL$z*({Gu`sm;@u1y@QONtDvx^Ow0S??_#bFXe-Yi2qi;FSps zJszn~ZQPU6Ex&~n>^#R~zG2I0y9GJD(V8Qj8q_`Ii($VX6cbotAuqc6*LnMIC*lbf z|7DP7LJcw6_Y37MUUCLPhk%vjv~{=sd-G!p*`~q(8qpJ;NAT(#3;lZ+3oe1~V2lXn zxir7%)0fjHWy(4{pE6xKyi^2`6wwJsiE}wb#;zbQO7Q2<0)xqiN@TshMyb#F(%0gw zHqY_{T`TIVh)=R;4-&84U23Il8gc9cXKWgXQWq14BjYNjLp#ny!PVLp91O%R_D>hR z7za=CA|qf$@!Iw;ro`|{_Aa+IrAn>!Vqc7^jFxE|hlsq-2!f62&RD$>@$ZNl4EpH~ zpZr5I-@DQw=(pNGLAT62sTRs-RGWI=vAO{I1`anjPvy^XFzaE zxp(rmi?cbz1N^<>-&z2CK1+=@W%o3Les)D)c9G}}2=$3CcNO+OU$k`3)QMv5!~C!5 zhhmvnkL5gzKCq<{Y;2nw!abbd-LY=-1l`~ zfjpB{!PeBRSj*0(RNyWRVrLU#>Nu`%GaTFz$#8BiAEL)-EeFPZ!F2)8t2>B737O?z zIk~p+gfMmC7v&e1j_`)sgY8p$EEUBjB}gaXoEK0QqE99yU@Z!IM}0lLQJbviAVO?=H-5H+i&&!ejWFN88^ zRY0i7VfL-OlaOo3DD%f{*}~7D*c`o5rpx#18BUVkvxi8Fh+eRQVs@JMB>q?bp1u7? z;Zj!$p-ECgyqnk5%(eG!M06&o`P==6PyKh*EZ^$_=CO56T}5Qoj3fy0<4)m1%ucg> z`7i0WCF99}3S~+7TRRUFJ9K%%fwY)scsM=#_?mD$jb)dqBNH07dung6je@b0zp=Kz zVc(AtwMZAsRu5tU1HZNHKDy0)(v)1QjTp5mgKanUk-N1O_vU0!CIjSb|7*1qcoVJDvbTMfuwB;!M|+cKv>< zG^*1!iFhgrYRuW{6XX+8i@Ew;zO19`52ruujOeG2eka^ot$Ls4VQ=iG4JJvokE_Z; zMZPu3ja<(#zL9k1wdj4CU@Br)th#5&j zaQUsJf)Y6=%bXW}8JY`2nU50*U>C||Q$2Be;ygV*@NP`UaeOi3@VJCfqSzhPHbD}= ziRvf3ECuWfVI;p`rW*7-DU86#)LbTWXZ@Wa&^$JoVh! ziwQm`I1<@xaP&u7C-lFAijQwY=e5!FzEp}-cf-Qojg5J~Lw_K)$6Mf znZ3B1^AtC@$fXoRIWUxmI-xm3ntb}MMMr5C1eKY37SPoLsE?-StrtY-m>rI9f!LQO zXOX$itT#~j-L6e;PYsu=I5df4PDniJEe_EA_SdtQ^#mXFc4Spk4^R!&qPhiBRE8SV zOB`&~tF1yTSgp_M1BM*GhJP8(Xo+{#OmJ9-Yo$vz^`NS0>CUC0F8tqpL0!PN!LDj~ z;fwJRPf>$k;1MbFDI*vS`qo09hGK&BH}n(gQ7WZ7P@n^_^}-I6a$o&-cS*P;H_K7@ ztDH7jTy+TrE`g~kiJs;%W-L3%ArnfxS=%EV<=8pLS~LPZvw^_^dP0NFQ#)(qWhox-S9qkE3yvE4R3vXiy~@tp1FPP zkXz1WPXed6pi%1d9m>=&gFfdviKj=C?PTHLO2a@|W=rQ{qd`i#0bsyD_dk=`B<#qv zK2hsa^h67>U7S|z%Ggio(49;+a(+o~PC&rnkwzr$bgda;Y{!?!*2C(ewa1}1-(xIJ z7A_nJU2J&^#FJKA*Enw5=nnmY8UIK-7d?#G$NbH4YZr@Q107maSj=o4+$*x_Zo?fu zLt4M@J)6~p!@)(rioCJ5jx|hUa>!Vm-N?s?n$TkFafC7WzqFKpS+MvjP{g_kMC%IG zmtXsqxiWdP)8D$(w5(;M><)c&-{+Uex43Le*YK`0>@cEMf z-za4IW{thvD;Es4-tnO(Rv(`8+uJMty|a1f1DQ*%uxGDHJoI~>`6hAtrdgGnzo)9!3Jz)i>P!8@wWTkM6kxN|g( zla@eN>Ta#5<4m*N031=@^EPFn8RiQ!oAX|L<)b<9&`G7L5@=%R4y18$S_*vXnPGKz zZ@@_fJ3eDqdA@0 zGDGF20?YY%ACma0_()5mqGl%_UfFAZ_x@P5)6ZGCSmGHPZ6*pOt|pca95L`Yg)91p zJN(8b<~5NJ*-oWp5=ztFRLnO@C{Q_+*JT$u43HBjFycAKIY})kaz-GPH?|+_WtRFs z?hc|ixXllr$+7IgS+XDn`cx<`LDwek{BP;3hQm?h&!{9DQ1Kz=dyB-^;R~K?b#P3V zR;t(}v_J?4$hW~zdWE0VHy$Sm4E*#S^Xb80p*NZauNG54HMuNrropun!rh+uCze|u zq0rY8{^u5G4$0?k7+I^)6y$|RD0rQ~g1^0}E?ZD|cE2y@FRIL6{e@on$p0YaSRa%54+P_%ORS3n6rTa7 z3lX3E+gNfnGPS0;C@oFDMI5Ql3Y=6}4bcLKD8IJ5F}j7SO|aN)S{d3K?EdkrnvB04 zn=JSTG9Sj2LvKz_9YqR-7(0%B=5$3Z8K>ItdP!D9?LPn&pDY5f2xchrSP66`UF!Uw zX54?f>OLQ(z@*V#M7k;o(mrXK_S2Nq+tI1l0uM?A$s3Swhd#A2LNDVgPm-d;)ZafW znhchPbXF8(ETWPWY+jO8=t%j7c+Czxp@}a?YerT!zH$cg?*%h?7#P>w=}?fds7fO6 zDT2Z)UdXH~ZF3d#<<*|ZwJOLQ&0atr zE7d26Vaar10waM@K+8Vz5EBuO^WkU2ifdvAjaJTR%Y9;+9)F43ww=5eabUtoQftb6 z>q9Uo$?Nfs44QShV?Fob15WmhyE9=eRpP!%iT%xU=SQzygxJk;2LRIO`ReGa!ejgf z&d|O2Hl^Bip-8yObdlyhYt-D~YT*jw(6$R+x9pJRmuUS2U$=jE}HZ$z{QZa;ekNO6>(>@^$Trc~Ll6=!r2iFn(Q0W~|{ ztdErj&w#ZIU>K1HsxyAaf+Gq|D^< z09K~b#3@!f6*{hLwBy}lp7t8FQHZF+ zH4tk(p0HP95&l4NyPiPcz7tL^WJ5h{_j<)21S#(W#6?>`6@RrkH!oE+j9N zu{yR+0&YzY^;=lYPi;TgQEB!_9R*ZCHZ14y&)SUYft;Wa$vn9%ry%+)- z&d0In5Ul_-v8DR3c*7+PWiP{QEf$~1JBOV8%R-HC01)M-!l3p^va53Wd9ojooDLCEEpDH@@VDMn)*P7d8jje_weVc<|RIPXCQD z+1?O4hckX?s$I#c{R_2(QF^XHAbeo<$+CXtOz^YE)bS9*<}MbXhSsq*f&Ws#a;>8P?V}GU!1OLcnv4HOtgZozd_`ds7pOX-bnS4P>fav>%N&i|8X;z9K zGzQpNw|RtCad}>2pHPYc%}rR<=UsUGI_APSQbr@XZ}0Iyjp&@UvF9%%Y6RN0i1QMt zv;>RD12ppQUmtcGe_;m~rGmdVS~v#a_!+uY=BsiG-b8B|=o8qf?}Gwo*};$8#K_)V zn6Iu!Ba^Fy8lPU$YJamclxZ;`;u73YW5}l#=1ok4<0AeQqow*5Pf7rcQtkH&9O5%^ zFe37<;1+#=tdKs=F_QTBW&s9a42p6LcOgJb6CJLZi}P}AGK3>T@0;xCc#UPyEmjQ- zQ~|}K^DI~T-ksZE7%Hnb+9n5?BO)O2YSyRl1_m6*`Hmde_8e&+Mb08le6I8`Rt*+{bj zoivk)_UL;CvUD<3h*ShvAeNyOwPKI&2A^P5H~+XWA?C6?mBx-CJrIoU9Snv|=nRlI zf*9wH#Qs_>zGWi6II-Q56d^}hF{GW;5spByG;%R^m4jJ?g*t^4K(QWFQhoqqTP*MD zeO3`tjAOinUF~B@7QtoeG#JGm?ee}yDfIVDd3C7%jPLg4W?k$2p%qH=iyNzZ>`Vi@ zw;IDLC-7IV$Fm+*rBZzf7ZZehWnbaHC+&Yi?k5A5qCQW7TgdK>ruxzynu2cd2!HC9fs{4hR z%QCk&RCD*%M>;8iHy7tk=+Bf`$1U9~M(%1_-fU1yEuZf=JlRCDGyl6@z{^HqbG+uF zRxKCDR^qZV%*8~N49<(0=#7ne3hYxYtl&i@Uz0RvIYC0QoB8E9RVPh+ejOS_B{guZ zsigueKV~Y0ZH(@a&&;h6| zl4wJH8|InmZq@a2IpMovwce-1J+SpWlJ|-=7FNhP&=CwV+%|g{)H~uRdJID>FvRGL z2}UC^krHUsUF#XS`y?SwB+e;Mx0+ngU>yME%5dYHI9LSK-lH7BXvH={TARyMZgC}& zm{|ESB-+tT@t1z|ThpmMXohG~A>l3O&Z0D1`XI*yIszSSo%64=DnSl(QcYkH0-!{K zm}-;tM~DbED*80x!CAYzl;1uHJ~_{|d;>~k3In>)Qm??5RHLwm*`zYYU;Oetg2txbgr}WHMWLSf@h^z zhDTJwsgzBSB7A$^zJ9gob;mZ-=^(CHmzFSHvwaYQa$?4TI!DIoe-Jc@Rgxtyt!W-`?-;?Cf5^@+SSbFZoQQ&k%K z>izg&I_XPq_Q>>>t{T@XD>jccEc9#Qr~f_m{UQ-?ewUMgW?n-%cF$bm`sm0Mz$;E z2dQ^fItjo5Yo|ok4&qLbiU%C)&&;!~T!fgg*TvJuLJ`1n5i1Vjd*2sAGq}XFbK*t~ zQtKhSFSNQ`b*WXu(pUR#IaH2a()f>|)Q{{lrxpchyx?CUofy$eP~(JQcf{$}Gd}p&p|wuNGG*IN&_{wB9X2`K z1w+XIvnakVm|0Y_-B}qK)xau@r~}S?SpAdH*pKjYT!=RjnbI$|yLbv|?gqzS*w|hr zIS@FG;Ecw@xwR{YxP$?Yl)J$yj-mc~^RACVV3rF_UnKm?W~-9^f+}nXew}T}l*g|0 zC5T8+?|}OD8AA_Ej;>gtTB?IWVkc8kQxea{#TNfP2Hbk?Y1BXFpRt+6^h6GH?Fw!ueKC0mU!H2Ql*Hsc4!p%KFpO<`E4YT7 ztIXzbYZCfY?|7&j`VeiNyJFujtiCAs&jJ7GS0uiVi_e5_Cdgm(-r*FDEFXPo%l|6< z;^60D-)Ntd+eiKrrwYLjzl)i!SUbZY>r(E6y3QAGMNLK`jVLWRtNh zW@@b#4r%T}omvv=L|$rX!&KD!J-=F)3ItZ)-JvK$O4FOPC!h!pR|=La%Mx{KIVR4(|pQ#1Y4{6c?@)?Y(4|A1LJu}f&^D~i`QCAZoktjiiOU8#c(H^ zUlfR#E%m=|-c9*7KK$nsi}MD&7kor)OKrLt}|4F<83ALzlP5OZv|m z;GQ6|aEk#fi@-!aO@C%OKD8#i3gRiZmPhbAm)*Ed{D9_(Lr=_yMTm~h`{a}B+-z8a z5a&~o#d7-yD4Wxi;obQ7B;FM|d5ry>;l=%fX>)mFx>3C*rza9MTGemMQ_Wn4+%#8W z{O_&zc7YJX{kHbb80JDOr9%10ff$p`W?Y~!&S2B>a*Y0_BOwvWc)AS@`x6k zP3<#6$nYcpJHo&wR^%d*{$d$MTMPpD!^QELpl-6dNpkA2(=S)Y*MU`&){9_}Kp z^?8Cv4;EKi&CwjOrJr1wSuD9^T%Y$hzA?>K-OA9;#l;Y_={$+Wpwt;(ijlD;I z*eJh29#iQoftnAeVvp9>;7Ba(+49|X5cGQo)#e>IyI_wjmh&{CsFd;vh{$kpCa~)r z)EZ0~Kq~2iS(xgVA$G=C;ce$LJq&8~3g2s7HX+xGTlq;6_`XhV^mZ(`Sr#Gn56;eR z2mMAdiS|KydRUv{afI$HzIBGIAmx>&LviJN0k!9B`c%)_PREp1AhAiFZdPldl}M>j zJ+g_5kmQnFJqvN&@b_8j{T2lV-)L4 zRV`y-LwC)(#{0BN=Tpr-*CcLd{8Tn1v3KVWa?=#3*xIy>PA8evi%w%_n{O2BWZ$&h z4D?TEt9YF7+EcslUPsl~rdq622%Zlp=6js1gbzLiHq=CY3 zfm!LqBWiM?orU^h2f#u~p{@TDvShS<>@7WyV@AEd;2)sw2roTTWro1+s}?{nm9nFZ9`J z<{!Ra#aVLrSArQ%-wx-c7c;!&#j>*e0L^Y~NvqrtQ2mshcG7oERSyG7XZwVxooQu% zmoh>fp=9*fMZSK_(_OqdZnZ$wvd$a+{AHlb2AyXs#JXeBco?O4$T&Ts?BMR|=KGA- z$b+G!bIru&bZw`C;gIELKPOHn&*_a*iPD=b*%bTE?P}Kh0Ox}R#sym~o!^$s(R21j zN?nuzxFf^BQ_x|5_p$Qcmj{(bjrs8*-7CzgxV|18&KQX%MVPP9Bh7dFw^Cr`o@rR7 z?01UwIt0DS+SL~}E=LmULg~(Jzvpye&PxNnuP#1%u~}62-$&1w(V{!pcXhL_ZH~66 z6;~Em_D}ZZEj8<3pP>jO&(3&zY1LFKVJZ#wO- zj0?o&c0FO=TzzN0l@QHutWWK|r~37lw^Bvy4w?}ya8uR74@kKp_BgJ9UvHIBLk#y! zb{63(RE;GWhf(z`&yM%`rje%%fffbd3NZNq6M?Bql-Hg7H ziH2*2s5P{1cNY!(!St`1;`ATSKfNE*n`0i2Mq7h~Q3l-+v{gw!IM4^_$G1_%J)mOk zoqmG>#R8efZ@Brs`IE*-ymcr|?q5yN(`51$atXZh;w@VrInq>{@LlM(ch%B$yv|&G zML#v!@Z7H=sy93N#b{K!HB+6{m<=~OnrB*W=jwRH%L+e_>eLXVpr^S|F{xr(bQe#b zcwtL=OFxR<`<(am$Rr7nlzVxMG_&*65OZNYcyg&?v?Y(F;JRdA{azO3dP5J%SPsb* z*%OLIiz9z^Amm~O2?04CSIk+IvqP;)fR8kH>d}i(J`%<3{H&*kq+EjKGF)vwDPKbF zqO$S008f=vwTGu2P8Q-m>cYM-*j=-7l+9Xv0V^ZqLb>6kn?bXXakhRu;6CC2cjFq5 z?*3hcgi9ncx?H%j=bRgCR7}6Lbvj~n8sZ`{7@d;f5My*qmvFx_Lr3EQxuL@1o%?SV zFADYJzPcrE?$tfQn|BKVwHmcFqy3J+6j<002EI9A%xd5E&t3Ew)~8Go$-5Rvn5x3h z2#54*ZHK*gRbWAYHcSlzXSeu>W``eYL_5z1Bo`Zf;E)MVs*@g^J;Hm=pOj;!kK@Hc zra)oc;CpPw?(vRaUTdoV&kJaWw#)t$AXvaWTAH? z?k$hpbdJgtw)}$}`2!pZ?siY>err;f{(1_vBgvF5eU?8w>`g${3!&@LsVEGHb+jql09zsFNtC%zC8K1N zSMcSTHKIhbS)#Ogg1QGspvaFuD~bK;gV{_~hDX4UUL4Dc<2`uag;s^!O|V#tL={NFVt?p> zMs{e`kL&4qykurJRb2Im8B;ra zTk65~wQP&9iv>z|`j9F5bbb`_I>erAT?BzqgpC-kgj!DF*7r@p1>Lf^pMOf+e+*gA z+?$SXK)xoOnk$qku>~ce(W-;G%PnjhUJ!#h&q{-2Z&=-~ej;@ev``{CJsK>IAftsL z>ViZH|HQz=$RY5!+8ItG*7^-wR*oIc)=-gJ#&*J+MYlvp0+=bqTn>)k_L^ShXgS%D=Hg%5|y3+%7r}5egVa7OgwO6{oYpNA?6Xqo_>csom_xI@ z$!S)r5;N<~kk*_*KzxJmx(^5a%!^-bzGLBzGHT!QJ9?-94`a{OL(3zH1rieB482JR^Z$yt)Y_pD~h(W>c_vk^^b{F{}IKrjh_vZa583ssOQ{j}v z_b0gd!xRd{37L!ha0++C{f)Z@M8O?w+<=#j|LJ!RtCx`^(#2mb%+?D*W{i~jr(}m0 zR|WoCUp%n03AQje!%&ykWPwd^df>j(@Jy%bDkx1 z`fW=G^S1|tU8MT6wW~M`EZ$@Hel_ERpus2O8>Zqu_PenUsw~n&7DG$kJC!v5>i^!n zhdAcQ%5F@)xaES?Dr*i5M+uBNU-e_%x|p}mK+yq^;iQ|&W+{K?3Xf#4TJwDMv^ZK>v7P(bR7%9a~7b@5AEDow+q11zq;^@nv z93>xJJGDMpF|DIchpvH+5UE3Lkg8MeEN*# zzEpM*JzRr|i~(ENH1`I0TPv0pv|6O74cy(VJCcvJhZi!E)pa7At*1$yBrGLqwCkg^ zEn|^u%YlfKE7sm*83pN=-svkIPsB*gL+ymEI8v>Tx3N%yh$d@>wZAl5V zrG`!q4o{K=i-;k}gPIbC+Et$)U5Cv=2kY!2%8^$-&ARDvcq3NW;;g4am!A!mwq&jo zdi_M7>$JNalM#Zb)>*wiwY&UqlL>9jvc6M(#mV!q>Hgxl|J=}d5bZ9)5STg^_UC4^ z!H?(JQ00)C$$C1FfbYo_F6AOe=#cnH(0aLnI<|chmRBT4JX+moX(*BK{zDKM#_IXC zzLl*|&>0y3hOKDVXB}mEyp_b5%Yl&m)GP%}R2>0)HCGJa6dTx}uIi@(-NmRcqUqPG zvMf^EB?z-_c3R-Or_aSJbvGCHz4-ll6elZft_<%>lGl?Z!Mk+WNV?H;CEQF$${mrU zdU`6VjalkRQkNx+kQ2Cwow|g$Tf&aHVGX1g{Nzz1Q)_f>z3`?tSW|_T!M&!5_=1py zOIKJ(D_S!FM5^My*(H5xgbKlbVRSLOh$kje%0V#(*O)IesJn_{t&KC^2bSh}E|Qv_ zj#(2;eVpy%^n?Vkiba#hI^3epP~%S}uAqpP3nLk~v)Eb#UIF|~J;eD?d@eQ?Ns41} zr4RQZkKg(nZ(C(riMCif*?#C)u5WBR*xYcmyfCPD!oW5C*}g0v;*PjWkI;Xb zK3&fF6Jy3BM*7y~nA%(`aQCvZg*ZzWy}Q455p_XD8=_HGq{bkgV6?CIj!Xw4VmU7_xG~hB|V`Q~}V7xZFYs!GCac zWFvz@xI4!hynw1N3cdA%xFNYjWN-L^4huPoN7UtPB*tY{3!2d{eJjw5?#G+M|Mq^O zth6;=91IWUnbDHOeVof2RjbuDB#3s0*VtW5wfvWVv7OQOc`T(7Gry#i=2wf!og?G| zs5iY<*9=h3j{p>My*xe>@tK!=#pk-LKhIxEm9)lsv4!&BSjankl%2D}IujMm#2N!d zmneIEK}Z$X&IBKQF<-$r>z<`pT@^oDEX$jHE3eb&h=8<40zrsfFlaVm7{6WLuq-5rF0 zxNRzd$|pMpOpQjbOtsi;Kc^R^VojeF&qCuYo`Zk!Ey*Llak>ZMGo26B!^SKU=1K`@CHu=};}`2Mfq%R; zA&*^=$ZkcRf0Xw`jBlVUL=^4)XBU3ghjhI)?CML;cP-pCSu^e|M)G>v=A&dnxC;%f z-wnQ%!Ac{$mSwG69c0`;!%vk?y3 zznq|U-?I07g;D~EqMnQJnrQQ)J!7Za2mJWr5+Uq4FQ~P-{D$KXpFM?3KG2^uX4f(sVg;16^;CM_@u&HOwd?tmN^-ht+J6z0Y?~v}n$c!Qmd? z6Kq-brc4=$UPau0OuogCAcjD15`-s}0_J%mQrL)BOtp{M^SrJq6tgYp3+oA}e(C=5 zq2%&oBOy?&wnhKUg=X-yr(X0`y8|x8$5>#GVAKjz!&NE)>_gq*to6k4Q}1oU;D)er z#G)`}baSBe*Z@4IDd|aLe@33TWk9xW^3)ZntLI~{RK>#Y?!%5V`9CBYL;-vfFF0rY zIwUC!F6^F$BZ<6^jkvuc0$q2pMdvsz#2p%3)AUP>GUDb~2b&NVc5tvL>nnE>q6>jf z>7G0UTs&7o2VmY%0A4ViI6^Js(!LSfIcabmX_?RH8h8O0W!E>cUD$CpA4;#(voym| z(>%5bUucE~)ycTsXME)Bpjke_Ty#!*<vX0l}f^xPp$|R_h7?x?>wDMMc`{*k9O2w_2wAYS?p%5F^Ir6~$ z#80NklZvXpr7NXUEcW8P@gti~;`H%ks+$nUP+2>BEtb2y2#2$m|6t%nQPDL4eTjWI zbK#fLrtA(|EiC1*r0QsW+mRs_QAxTmnPfjmZ&ZCx6a9(R$?T(B8|P_m+Dw)k4|oOL+s}s=>v)9-Q?c}o zIxcaV?}{wz(Eg=u%OU~?X54Tuh7&1&Km_(QRSye}BY{1hP_V`k49{5m(p4=sCDme! zdX%F$X6v;lLM6Kh-bOys3%a`0@}A;nZ{XUIrP^8YhfznP4(j8!?6Q^fUddEq7;ivi z1nKjV%bb%n@RE7EgS0{gdtut#MTzv0yKvgt+XMH5QelxW=kHx&!d{NvpG`14tQBt@ zCMRzwM6l0LMUFx<0wjN^H1pFeU0pxfn>wAA*zfSNHQK33RUYGTgMy(if-w|`Ft_uh zPX_026-YatSG+b+FXRN+*PB6Ov!Ef8g(6cy^%@(FSZalVb9sU7QyNN*hL|cp2H4$4 zL6Y>(Jz%9kZp{fr3?<=VAGAMD=U~AmsfCF@o@=EDWlIjzzXg**V=3FPVNQPb~I zm0R{Ycp!|#`zH#9IUdigoL4a|>ZxzI^#Ym}0Ocq4#+{)r{0&<5?kdvFVWb?I7P z@_d*!zU=Iy-I(49^jyulS@8<PUvcACaTxS<-SGoqqt)tF#>2LY68qo_#bERsA1ad{K!ccC<9#g5z7>n3B?K3I2e$7;gqlqz<_L;_fb~)xJ^^{xUKeHu4?Y|g(tw)h+4ga;`^XBb zrp{L%XhFmsIC@O)EfMBtr9=c=b`k&J1zPlg} zgnwCb;1MH2tzVKU>=wn8)L1Ak8`jUtgNJloBB3x3Y1Szhm`oP2Y!9Sevd?OsQRQ!_ z>y0$v0Nmv^Pr|ie+O7u{49nXLk{>Y}3x1GhNB3W*eu|s>?#eAMFn8&n@*ieii~eQw z+AsWdd8Qcz{r1ORtI{T>wD*)m$#Yhf(`n{m=sR-*yC4QGHNon0Voe4J6)s6L)jUb* zSmi(Ymuu_9V*nuf{UTE?tYKJKwNvcj%5`)7b6L35Uw(xx9vD4T2c{8%R)vuUcK8^9 z)9VcE>mG&f@QSv4Nnu@F3{y4DpZtmlFaY$4H-MCYL&cBn%b2dR^%MQN#Ub?P{{uyJ zm()+IYK9nmPYwH+m0AVYM@=tG=1}dEJAzlGBWY<~`*)*B?vI-j{C`p&fDu1lIm8dbBHL7n zs;}K7NFgrDUkc>Pvv$7PgQKy}%vh`t;+P}Ow2h#;&ZID<8zd`fN;1T#zw#Mhn+l&j z2nOR3p*sfAAskds>wzWTeh9PavG3pIcjhOx|4kn&Az3?0j8j(`(ifCvK@%%TX18CkFUVZD-*YYbbyZh)J@R_7W@D$ft znsu@|-aYLZteJ8+TtZA2s?8G{J9kBRj{%aY{dlBw*@Y@{%uLB!lkETNpjrJ;6(H#zkYlNr8%0ZYRRi3K?`79yns^){|NHX4p7Ablgmq5a z2TB8x+*kl}4f&)zsvD+X%y>vm${wxcr}?b)STe4cv}1t^pwYvc3}1dQJ^mG2b<>7K zq4W!id$xxCZtFVh17z6G3F45kXTRRP%lWTnvbmVmZcT3thZ68H>rvk1?nSh|WcOT| zkNIYs|2mreKlu8u`(cgW4DjC**#(^6tV(M28%YULJ!!2r zmuDN)7sKB}jIU1aA_*w0fBK6n%YVOrr+Y|Z;~THCBlacx+LUUhd<99iU3*JH0T#eR zSw>RD^5+UJTn+~_h1^ZJWu8)HugOFe`*{aHb3sgIe51pUO+Uer$zDN`0V1e(=i3%867jg80ZvC4^Jh?LI+RBpg6cVPHF7=5F|1i4v??d=wrE;l*&Vn(P9Kjz^tI$p| zpZRGP#bkb-*Iqdk+2?q%L*3tOgxP8AlI!ZWRVBa+_)p7>R*=n>Sur6>)07Rjgs_pRp$5%)hA!N0CM{rqh}?Ml924?nhEzH@lA9m7k)T!zKNIT#T~ zp+tc?^SjL9->!lGz2M-9fRnq`jA4kPMWkA)v*i5pzv$kCqW*KU{p&CK^UenmG&*ws z5>o#!TZX@Va|^_jJ#|Z0RntHBrvJ54)=BbpGdF+yV~G3b_y6Y)eBjV|b#Z()ZVCUN zuNg}*cZ2`qJ{%+8>US92JM_(>MF1H%@}FMhFP9iC^K|_ZRB2fy39zrtd=u7#e; zQ{%jMSsP<>zS)!skO#^U)9!+5TOJYEKik#6Tok?mq94CE)C&~zp=ke*ezf^X{B)a^ zU~=9eTBy;5rcU5iYhVWk_f-b-6lyvR9>Bz6+~*NS<)`8&dxhzRFZ-?Yum(D-5j@%C zlP}R%HxKYx4e%PTgEq1p{Vbc9T3jz2Qp>IDi(Jx0ryTYRH1Y31Uej3LiFbwsGo}K| zXoq4Wzhu($3HIS$yI^Z1i}#&llLe>UWu1oz@7F=)qPWr3mrKg92Yvah&DoMwA(^UU zB4GSO^2DtbUT=dR<92;4=r5^Ee3`31tFmu#%07>Nb#!Odob~J<5--^**Yb*$boLa> zU(TIHU;e(JmDJkfJ$Tf+B`Zv_772^n^uFJAJ{T(xtWs%``f_i64);3Y0y)~e{CqL~ zh=W7Z`??wjMBMreD4F6(VKSLg4;4!|{y7W&mqvnkO#r+f8O`n01;cZV?NtW^loEz) z^OZ*UygIZLN=&%*h9g@Y_#{PUTt&b@DUxf+o}|e4!C?xpy4b^XU*vjLEq<7KYpD#) zr3rz_tsH+aRY0R{LaAJm4S8iY{^&1h+WyOMYkQwxt+L^}%_RT`D_r!lA_*0il}UoP zyR>V;!G@eAOyv{4jL_@vXd+e0iswglo9qD>I2tm)*zw=*V{XdQ>c>4ac-xqRA}QDAt?`XZ_#!>~>FDjXAi4 zi#Z)oZ4o#9za%gz3249fxGW*JqGq+67iqlto!c|KsIiC#XEgLmbiATGns3w*;& zOmz1T53R2--=+==@Qyp*nHKJ-}<4>~!kW!_Ipz&;H;mz-r;(VP&*U z!I&J6%&@%iWUT7#2dXzgJaka}Wh!nC8Iz<={f8aTl-l(M?9%Q5^PEe=6m;=(f6qT>v2PtB~ewVjyn#RWvib$^=ASpK}+pNLM@K=XA*<(itvX}+mWqS4|ww3q4?%dV*nh?vd*7&bov z$ddnc?D_n(f`$ZxAKUXf+gq?)-4Q>7SZuMcokz{hj&QbmCB79^Kxz4Nujao+rIr_) z0TR*h?{-h|FE@mtFJeAFLY6iSK0YNAOBz*@PfWBb+7A4{=hii4oq~?EBM7n2K<_L% zoq+vKZovu|9>yd#C$$eJlt!?&57K(`@ScSW23hc}kyj?aGAw|+-It$K&cBxgF>?P( zH~hy|(iRJGT)itc{-+lJ_d60>N~m{Q)#M!yztr!L6?25z#i(7}cLKnZ20%iWLS{+iU%;kp<3T(VVu@|(`K-rk# zy-Srbym&MA?FInJyud(~tJM)CQi)$^9ZhBUb4Tqy2L=&Ld}J?vfAq-hnTD-E=B<4_ z&?t!O%@h2p?1~sc!udowWAzL0&sSJwZKzy}AKv)p!O#16kAAe`98{v+EV5sZ8+JJT zlSPIpieWV@kxVx~pI!8G(`5&ZPEN3)XDY$UI>ct7N^d5#X{N zObM^W0h91Qm0hN2;9T5G`A^Yd`9k9Y6T34@$7n_sFKcpctlg+2hKq* zqtzC5Cv@le)%A;&edqT}3dA*w0!g&z-$N~`CxR0NgU664sWgO~I?`6!!Pp4fN3NXNW zUrGX7U#=zLVTD~NhZ0js?oZ=L94SOg(qCA|#(6Ip-D`%z^_PJBn*aFY^8>iKY38a; zU;(nS)&X2lAA}P-Tpt4wT`5C0y`P%9K%(6-nWQ6q-xZ9%?3sF?I!LF{JEn2dUYRMz zV8*VF72tteE;VRyw5%!;B%Trki3`KFlnBg?aKF#8@mWGGTlj~f5CRlVjiI=dx z{UU-8(e%vCdEmFpT&cH8$_?4))7hIP+oDE0=KRvDH! z+Ex18%po2n1dSb74hBx8ay@kJ6#}UqUrV3qt&A&oeLiho(RpgV+7RjX`-mmYvOkK* z$>qeg@Pp%+7+w`(TS20#D>9{}dI*ZgEx);zCYUdl0DL5mV-J;9UR%poupZgtu&4vu zYt#4@hKCdXbG2M2?ZLU;a3y;Bbk!BE`mNCVh<3yRXc_t;ITqUihkUu4&suF@XC5=&g_Us3kww4eBej+=A_?rM zHfU0s*?uLPh4;yr6<(xbj*)b3lxMjrH`lP2I*3|J4E8p-7O8$4bmXp-5p9DIt8RV4*75HefNLw zdfyv^!8jYYXRp|6%{kZnzWIHg@~jOOzYDvy6mbHXv_!aeR@I)~W}d-0mAayoiMH@M*ue?=j2#gpHJ&e z=YSGH34;KI(3<1rqAL};7^dtYh+ykoDu6CqWX>oBP=~Bo4+W=OR|H!=PdR;J9yjf6 z_Am^prceb{$UH~MKsy>tSq>6KyZ6fB#L;kB6SwFHJ`43>H4h~+-cUh_O-`%DOJf1^ ziJsW+qlQfQ^-H06Z+@1yE;d$KJd#fsjB#wkVZftaOCMLEc%%Kt(apx|v zQ=FQG*W2A)+fFNeUq57G`-fUIdD7F|;DSe*9q+eDuozuLfzruSpr5|kvhPbHG=#Fo zeb!7r__c4gZlR6@+yxiB);j)`2pR9f3b&{>hX0S`F0i1uf z(;a*%aW5Iy6F!U40Wp^eEe+5pn8xbBw?3=2LRBtm8f~pE4nMYZB zkp}_au4ayv=6RFlvKGI~`v9LHCzeM-5vEFgs4ig^u=>T2iS`U~6w|Ev#zj1{FrP+? zVfwJgAtv(A!R+;Uv~KS&T*L8G%*rm&b86JJiEqriR0{4~b-nNffniH8)P@#wIB$=72o|HgZd>rk;P^+}{kK25-)<>WQMBtjyh@FRF`zw;5Pjg1XlK9UH2DPTyQSA472;LSs24AHV4{#h_ zX-w1}=@VG1_V77PD2#||nS|aVeHxTYQkv-TTFa5F2O|N2@&)$mRjvZfLt?KC2E@bw zHDU$@d2krJ5OFuLEufeXpXnuIqdE0DVhK+GA{L_+b#%y7B68AZkAzpK3eGTXPR z-6oQpqu8V_%;T}2i$cO76_kvpitf1iYTIf=oqGLpsrl43Q<&A^oEnR8cf}t*!!Kqu z^eg&l-y_RHf&JQ|-XWm29R1H9p^voaowAe%sj+7;R6H){HKoff5;CT;sUm7GYH^u_ zp6d9Kmv&0y4AE$?x#?*rvmu;kN3gJ`M=%hM zn($Z{d~B|kJ#`j45>Jl{n{77|#^Sg5SQ_kI6^z9B)kg1R)YGRK#WfwX7`8I1gR|U< z$LabNFpmQ}?lx0%rRRK*qpuYcTz|KIKCoT1zCa}il*)?tX_PVyTFs8-p&t{XO$9xV z)#*Qw7f_YotJ_$KUJK8fynoZMYkL^n%q+j{ad^qHLa2&*F(2=ks=#u2ong_rY@zzc7cuz)GQT&}ARHtumdIceHEpI;&$Z(c>5q%4)zhmB--) z6sC_^5j%`fyEOe=Y;%Q2pT|;atSA0pSooVy3{0A@jTDqTipyaaawMvf8Pg9lR=(6g z95l`*gMeX~M1Mfx&qfT&zEmSS3wuTz!;tXzH4#7z;Hq43{nzGD#y=W#zA6h0tnLv2 z1U_4^VgB^B-AY@re_96ozE$2~bX4PK4C>FYrL?1D+XSy`zT$hmkBJoB;VlYP;@7nr zD*L1x{r8`15Tg3H@eJF%_ayR)R$jvvFZ~vfQTjtIw}{|9+Gog@8g1Md7d`mMz8 zQ~R$+p?^YpuZ>(=5Jd9N2LIW9!~J6LZN}yXokc;#xwBbeiFr zXr1OOsq*r+FKG~INJ)Y4m%7LYb^gZ_@2`1^weY7u2eIe}SGEDg_B^vpP%Y#6x6#}5 zpNC8Cv7B;rkkuvJn@~)e(B~Fk`tKPo_NLF(mZ!&R2&(UG-@5MBP%X^aZ^PZorn6+) zy;5x|9?@%1j&eS_kGNwt4p?mSlo zg2{5}kN2iy8Rc^om>3P)ua#BzV2GLv7Aw|_a!p(FABtgb*QmUwYbx92RK>#*N~2Ff zGg#*Yb*4+={1W(h^IDB=>G@wXr}tXEdLpb~eD#`iX!~uS33vmjz;?|*3_-w-C_>>Y zms&5=oqsfRf>rQyGLlR({MV1o1z%Bo~!^|Ie~IV1VjV^)E*uGfT3;(te;F4rXG-U-Q|bhsZba<( z7PQE|o#S-BWj7s=W;rY5O~lY(`)#sGOFSq~iih1%HRHS?Xys$oB0h ztlX$2YOXJfb~#z!;sNR1yV z0?z@Ao;W(j&MH8a}JdCbNs5wQnUK~7b1>ADp%yhFCUC(3un#7 z_soelk#R;!G`@S!E+3T8I2L0!MQ}}h_A1rjl+Ybd7hSfPlwF;!*Z)xkb#I5g4*z#6 zB2-8%Wcx-r1J@}O*zg!IW^2tdpHnAP1hsV!56>C)gd9p%1>m}T>pWcX&eByoc8~^C zWb^sm&edDNZr&V1SKsP=@7=XhcUw&k^cmSh9201y(j>Wlz{3(FN}$`2m)-M&VtOJ; zWCHnI1{yzo)lJ`JwO%KSr2=qM3flL7nWxCbEZ$0la+#+mu<@NxKr)^{4vmw{hw!s8F zB5I1H!89R*Xt-02tNfvGk%$IvErxldH^{Y@e0gpZGiu+w&9eT}vZTQNbs#yrUCPPf zr-!kH-I%R1)PN$!3@*902d9c421*o%>4~|Qi!5zHu?ep?Y2T?7Y3nj)5(7m~Ex>Zz z1+C+Qu{WOsfdWZ0=&H`1y*Y?*p(@ItMnf^=p)nnI4tnl}YP~+Wgqb5p#Wi%l%|5vW zVvX_i_SJGS^U2&9BYND?xQA!n*dsg$C&y+Rw!zVI>Madk8NsvS4Gd!?Iu-BS^ie3X z(D~C*4e3z)vS@nRR_Yp+U#ZRW&|m%LG>Y&5#xna3w$lA+Ic5rt5zkFgp-{%#U*|Hl zJ{sM~3MbKY@r2&#(SWN20U3wM|RJ?t_Kq5(mgnQDI5?t@v&}P{jpNJ$IE+ z8An=TIKc$Z#CHK)9~&-(bgGSN)RD}3;D}5IalIC7`1Xa-2SoLftq4a_&VFd?-(1@O z9vJA2gsw&OS%aq?>KcTkT%;|}`@Qrc*f0JS#f*NSq~7T1K0scrNE5J^ZzJPd1n2k; zAuyG`tu5Y_&PSgL#U47UC+Q((@lzG+u^Uu`;=d%N*ce%jXP2NLMg>0UDh z4q3qmPs9}CMyvG`joi`Vg^XN((qkGAcx5+td3Ve9w|)4#uuq0X_6A=C9x&|&Nl>bj zJuuM6NhxnV6Wl0iM{+K?5#)F=IY%|3JED>c|B_yf+%z2452D@moq)W8f7^fp<8jjQ@tGs^01%vON%v7{QWg zER7jW8=4JmamoFP9k1sbuwCqi7Dx)|8Q>xy`eV^5fN>;P1m`NBrRHtpWe&I>@X9nX zz_ABlm3SL+C^`p4Pan44mf(l*skhos9UpPHdsi#&!Lfl;J+=K2F5?wxLU&J6rs;

j};piJ9-mAoj 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≀HWCa97%Kpn#~&e zGo{{LOXNl1kG3k8f1gu+aVL9;_wiG|?D<)R^p*Iafid?dhSo3UwSpN(2hWn)dWKur z)<p%HbuU7T6sx{}G4sO3TY%(Y_%OtP0iHbTtD@>_JehK&amAbK%T%}{5*#VRlvsNZ#;c7U4C#Rju(a+#QxtIso0S9CCv3f;iB1K zFXh;S@V5cf{VBZ)xAsero|9MxQKp$F4-Ug_e8Igu59wwj3~05Kb9(zx(iM zsVA;8LOFJI)CcodLJs{UxnUa&+q#H^R@ml>%C8BuUsi9m0VZr7I@k51kWp-r7bt@C zEz}uG>b|U|#WprQ5ysyj=62d8R%A>otpAeAqm&LQwVooIjz(2KH&K>=f)$LM(!LGF z|1LHk0R3GQxrr?-;5;cY{=*v??f`kXMtPLBgZMV`5b{2a7x4u))VqZrGiLPbr9aiA zA&qB7e6OLaUa%hUB4YH^5CL{oS(tH$s+Ha!@=!n~r}S^KXwPeGJy6-vqeXD|#a(wl zU!4=0DIcA%1&K%~{Ux^$_sOc=-pbmDqs@Uo4E*t-0y;lhn48mSCtnaU@cV?|KLZE< zx0UqmY~^s>8o+A5n_IKz#Cth+@duWAG&(}7@N05*0L%?lR77a_1%bVWJOPq6ouu3U zUdg2D1&%OORPR_FR&!hb#f%-r=VZ19Y0OQX`65g%sRicnCg&%hFd}Q@uTUtMy$iT! z9?s;wm|Ew~h}iIevrB@$tEnbx|&(x}``&!uww!ywm3w(d|6@`9HUuIh yI9PJ5p0s;c|YdI-Z1OyZ+1Oy~U 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 diff --git a/source/docs/bot_routing/README.md b/source/docs/bot_routing/README.md index 21828f594..94cd8b058 100644 --- a/source/docs/bot_routing/README.md +++ b/source/docs/bot_routing/README.md @@ -1,5 +1,5 @@ # Bot Routing - Preview Mode -(version 1.2 - December 2023) +(version 1.3 - July 2024) Bots exist to perform a variety of automation tasks. Usually they take as input a message from a human and respond performing @@ -55,18 +55,12 @@ BotRouter for the question being edited.** * Bot Name or Lambda - You can configure and existing Lex Bot or configure a specialty BotRouter implemented via a Lambda function. QnABot route -requests to a Lex Version 1 or Version 2 bot. The syntax is different -depending on the target version. For Lex version 2 bots use the syntax -lexv2::BotId/BotAliasId/LocaleId. For Lex version 1 bots use just the -BotName. Note that QnABot can be installed as either Lex V1 or Lex V2 -bot. It is important to check your QnABot configuration and select the +requests to a Lex Version 2 bot. For Lex version 2 bots use the syntax +lexv2::BotId/BotAliasId/LocaleId. It is important to check your QnABot configuration and select the appropriate identifiers when you want to use QnABot as a specialty bot. * Simple name - A short string that we expect web User Interfaces to use as a breadcrumb to identify where in an enterprise the user is interacting. - -* Lex Alias - If your specialty bot is a Lex version 1 bot, specify the Lex version 1 -alias used to communicate with the target bot. * Lex session attributes to forward to the specialty bot. A comma separated list of session attribute names can be specified. The session attributes diff --git a/source/docs/bot_routing/images/botroutingconfig.png b/source/docs/bot_routing/images/botroutingconfig.png index d75c5071c29e1794a72c03fc1b41b9824a1cd8c1..7daa945dc3150593f290bd1b4b9eaa743389ae54 100644 GIT binary patch literal 70557 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μ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 xG=n1;gcZVmf5iVk$3N?Ne=cv>|4ZvZ;b+>z9 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 VY6V{f15SaLk)D}uvG(1N{{k)S(c=IB diff --git a/source/docs/canvaslms_integration/README.md b/source/docs/canvaslms_integration/README.md deleted file mode 100644 index 893f1ca93..000000000 --- a/source/docs/canvaslms_integration/README.md +++ /dev/null @@ -1,115 +0,0 @@ -# Integration with Canvas LMS -- an early example implementation -__**NOTICE: Canvas LMS integration with QnABot on AWS is deprecated in this release and no longer be supported. Customers may fork the code needed for their specific use case from previous versions. The integration code will be removed in the next release.**__ - -Students use their schools' learning management system (LMS) to keep track of their assignments, grades, and working through their course work. To make it easier for students to stay on track and also have easy access to a knowledge base, and help with their learning progress, you can now integrate the open source AWS QnABot solution with Canvas LMS, and enable students with in-the-moment support. With this integration, students will be able to ask the chatbot about their grades, syllabus, enrollments, assignments, and announcements. - - -## Setup prerequisites -There are few prerequisites to get started with the setup: -1. Setup up Canvas LMS – the setup requires a running Canvas LMS environment (on-premise or AWS environment). If you do not have Canvas LMS, you can install by following the instructions on GitHub at https://github.com/instructure/canvas-lms/wiki - -2. Setup the open source AWS QnABot solution deployed in your AWS environment. If you do not have this setup or are running an older version of AWS QnABot, you can easily install or upgrade by following the [AWS QnABot implementation guide](https://aws.amazon.com/solutions/implementations/aws-qnabot). - -3. Setup a companion Web UI for the chatbot. You can deploy this using the open source Lex-Web-UI project in your AWS account by following the steps outlined in this blog post -- https://aws.amazon.com/blogs/machine-learning/deploy-a-web-ui-for-your-chatbot/ . - - a. During this setup, set the `{EnableLogin}` setting to `{True}`. This will allow us to enable authentication in the chatbot and connect to a Identity provider. - - b. For `{BotName}` and `{BotAlias}`, use the BotName and Bot Alias as made available from the AWS QnABot solution deployment outputs. - -## Creating and Storing the Canvas API Access Token -The AWS QnABot solution uses the Canvas API to integrate with Canvas LMS. To configure the AWS QnABot solution, we will setup the following: - -1. Create a new Canvas API Access Token. For more details on how to create a Canvas API Access Token, follow the link: https://community.canvaslms.com/t5/Admin-Guide/How-do-I-manage-API-access-tokens-as-an-admin/ta-p/89 - -2. Store the Canvas API Access Token in AWS Secrets Manager. AWS Secrets Manager enables you to replace hardcoded credentials in your code, including passwords, with an API call to Secrets Manager to retrieve the secret programmatically. This helps ensure the secret can't be compromised by someone examining your code, because the secret no longer exists in the code. - - a. Login to your AWS console and navigate to AWS Secrets Manager. Use the same AWS region where you deployed the AWS QnABot solution. - - b. Click the `Store a new secret` button - - c. For `{Key}`, name the key as `"API_Token"` - - d. For `{Value}`, copy and paste the Canvas API Access Token value that you created earlier - - e. Give your secret a Name and Description. Start the `name` with the letters `qna-`. Such as: `qna-CanvasAPIKey` - -## Configure AWS QnABot Settings -Once you have deployed the AWS QnABot solution, you will have access to the QnABot Designer console, which allows you to create and manage your knowledge bank of questions and answers. -1. Click on the link that you received in your email and login to your QnABot Designer console. -2. Click on the menu located in the {top left corner} of the designer console. This will provide the “Tools” option list. -3. Scroll to the bottom of the page and click on `ADD NEW SETTING` button. We will use this to store the Secrets Manager key name that you created in the above steps, so QnABot can know how to connect to Canvas LMS. Enter the New Setting values: - - a. Name: enter `CanvasLMS_APIKey` as the name - - b. Value: use the name of the Secrets Manager key that you created in the above steps for storing the Canvas API key value. For example: `qna-CanvasLMSAPIKey` - - c. Click `ADD` button to add the new QnABot setting -4. Create another Setting - - a. Name: enter `CanvasLMS_DomainName` as the name - - b. Value: use the value of your Canvas endpoint. For example:: `https://lms.myschool.edu` - - c. Click `ADD` button to add the new QnABot setting - -5. Update the `IDENTITY_PROVIDER_JWKS_URLS` setting to add trusted Identity Providers (for example: from your Lex-Web-UI Cloudformation Outputs, using the `CognitoUserPoolPubKey` value). -6. Scroll to the bottom of the Settings page and click `Save` button to update the setting. - - -## Enabling Authentication -As part of the prerequisite setups, we setup the Lex-Web-UI (a companion UI solution for the chatbot) and configured the solution with the QnABot solution. The deployment setup an Amazon Cognito User Pool to support authentication. We will now extend this User Pool to add a test student user and test out the chatbot flow. - - - Go to your AWS console and navigate to the Amazon Cognito service. - - Select `Manage User Pools` and you will find two User Pools have already been setup (via the prerequisite setups earlier). The User Pool we will use is the Lex-Web-UI user pool. - - Select the Lex-Web-UI user pool and create a test student user. Also use an `{email address}` as created in the Canvas LMS for the test student user. -``` -Note: We are creating the user manually in Amazon Cognito to show this example setup. This manual user creation step should not be needed, if you want to SSO to Canvas LMS. - - Additional information on setting up Canvas LMS with SSO: -https://community.canvaslms.com/t5/Admin-Guide/How-do-I-configure-SSO-settings-for-my-authentication-provider/ta-p/217 - -In this example, we are using {username} as the matching attribute with {sis_login_id} in Canvas LMS. - - Additional information on extending Amazon Cognito to Federate to your Identity provider -https://qnabot.workshop.aws/deployment/sso.html - -``` - - -## Import Canvas Questions -In the QnABot Designer, click on the menu link on the top left and select `Import`. -From the `Examples/Extensions` section, click `Load` for `CanvasLMSIntegration` to load sample Canvas questions. - -## Lex Rebuild -Once you have loaded the questions, click the `Edit` option from the `Tools` menu and choose `LEX REBUILD` from the top right edit card menu (⋮). -This will re-train Amazon Lex using the newly added questions as training data. - -## Testing the Experience -Launch the `WebAppUrl` URL as available in the Lex-Web-UI AWS CloudFormation Output and Login to the chatbot from the menu option. Use the test student Canvas LMS credential that you created in the earlier steps to login and test the setup. - -Try the below example questions: - - Type or speak the below question(s) and see how the chatbot responds back with an answer. - - - *canvas menu* - - *do i have any announcements* - - *tell me about my syllabus* - - *do I have any assignments due* - - *what courses have i enrolled in* - - *more info about my course* - - *what are my grades* - - -## Notes -- This early example implementation supports English (en_US) language. - - -## Additional Reference -The following Canvas APIs are being used for this integration: - - User Profile — to support authentication, and greeting the user - - Grades --- student can ask questions such as “how did i do in my Math course”. This supports the overall grade information (out of 100) which is aggregated by course (not by assignments) - - Course — students can ask questions such as: “what are my assignments for Biology 101” - - Syllabus — access syllabus information. The output of this is a URL to the syllabus. Student can ask about their syllabus by asking “tell me about my syllabus” - - Enrollment — students can ask questions such as: “what courses am i enrolled in”, “what courses have i signed up for” - - Announcements — anything sent by the teacher to student(s) such as: “you have a test coming up”. Student can ask by saying “do I have any announcements” - -This integration uses the canvasapi python library to access information from Canvas LMS. https://canvasapi.readthedocs.io/en/stable/getting-started.html - - diff --git a/source/docs/intent_slot_matching/README.md b/source/docs/intent_slot_matching/README.md index 0ef722c5d..759165c6a 100644 --- a/source/docs/intent_slot_matching/README.md +++ b/source/docs/intent_slot_matching/README.md @@ -114,12 +114,4 @@ More information: https://docs.aws.amazon.com/lexv2/latest/dg/build-intents.html - As you are building your knowledge bank of questions, you may have a combination of FAQ based questions, Intent based questions. There may be instances where a wrong intent gets matched, or a FAQ question is matched instead. To troubleshoot this, below are couple of options that can help: - Enable the `ENABLE_DEBUG_RESPONSES` setting in QnABot. This setting provides debug information to help understand what is processing the request (such as: Intent, ElasticSearch, Kendra) - -## Additional Example Implementation -Also take a look at an example implementation showcasing the use of Intent and Slot matching. -- [Integration with Canvas LMS](../canvaslms_integration/README.md) - -__**NOTICE: Canvas LMS integration with QnABot on AWS is deprecated in this release and no longer be supported. Customers may fork the code needed for their specific use case from previous versions. The integration code will be removed in the next release.**__ - - ---- diff --git a/source/docs/kendra_fallback/README.md b/source/docs/kendra_fallback/README.md index 7cfc34d12..0eae566f3 100644 --- a/source/docs/kendra_fallback/README.md +++ b/source/docs/kendra_fallback/README.md @@ -4,8 +4,7 @@ This feature searches a set of Kendra indexes as a fallback mechanism to provide Kendra provides a number of innovative features. This Kendra Fallback function performs a query against a set of Kendra indexes and will return the first answer that Kendra identifies. Kendra can return multiple -answers however to keep responses limited in scope the first answer is provided through QnABot. Links to -documents stored in S3 buckets that Kendra indexes are also provided. The security of the S3 bucket governs whether this link is usable. In addition Kendra can return discovered text with links to these documents as well. This function returns a default of four discovered texts/links. The maximum number of returned links is configurable. +answers however to keep responses limited in scope the first answer is provided through QnABot. In addition to providing the generated answers, it provides [signed S3 URLs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html) to relevant documents stored in Amazon S3 buckets that Kendra return in its response. These signed URLs are a secure way to grant temporary access to specific objects or resources within an Amazon S3 bucket. This function returns a default of four discovered texts/links. The maximum number of returned links is configurable. ## Configure Kendra Fallback index using the following Cloudformation parameter diff --git a/source/docs/lambda_hooks/README.md b/source/docs/lambda_hooks/README.md index 93445d0b0..80f961f09 100644 --- a/source/docs/lambda_hooks/README.md +++ b/source/docs/lambda_hooks/README.md @@ -84,3 +84,4 @@ For an example implementation using Lambda Hook -- refer to this [example](../.. - The `Makefile` residing in the extensions folder creates separate zip packages for each separate Lambda hook function - Lambda hook functions use nodejs18.x or python3.10 only at this time - Lambda hook functions will be allocated 2048MB memory (defined in index.js) +- LexV2 has a timeout limit on [RecognizeText](https://w.amazon.com/bin/view/AWS/Solutions/SolutionsTeam/BuilderBestPractices/NightsWatchUserGuide) fulfillment. If the QnABot fulfillment processing (including lambda hook) exceeds this timeout limit, then LexV2 will timeout the request. \ No newline at end of file diff --git a/source/docs/lambda_hooks/lambda_hook_sdk.MD b/source/docs/lambda_hooks/lambda_hook_sdk.MD index 83f112eb4..b84989bba 100644 --- a/source/docs/lambda_hooks/lambda_hook_sdk.MD +++ b/source/docs/lambda_hooks/lambda_hook_sdk.MD @@ -81,7 +81,7 @@ object ### Returns -- Lex V1 - [https://docs.aws.amazon.com/lex/latest/dg/lambda-input-response-format.html](https://docs.aws.amazon.com/lex/latest/dg/lambda-input-response-format.html) + - Lex V2 - [https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html](https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html) ## get_bot diff --git a/source/docs/semantic_matching_using_LLM_embeddings/README.md b/source/docs/semantic_matching_using_LLM_embeddings/README.md index 672215fce..3d5caeaea 100644 --- a/source/docs/semantic_matching_using_LLM_embeddings/README.md +++ b/source/docs/semantic_matching_using_LLM_embeddings/README.md @@ -17,6 +17,7 @@ You can select from three different options: ## 1. Amazon Bedrock (PREFERRED) Utilizes one of the Amazon Bedrock foundation models to generate text embeddings. Currently, the following embeddings models are supported by QnA Bot: - [Amazon Titan Embeddings G1](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=amazon.titan-embed-text-v1) +- [Titan Text Embeddings V2](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=amazon.titan-embed-text-v2:0) - [Cohere English](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=cohere.embed-english-v3) - [Cohere Multilingual](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers?model=cohere.embed-multilingual-v3) diff --git a/source/lambda/aws-sdk-layer/package-lock.json b/source/lambda/aws-sdk-layer/package-lock.json index 73abe629c..834fefd97 100644 --- a/source/lambda/aws-sdk-layer/package-lock.json +++ b/source/lambda/aws-sdk-layer/package-lock.json @@ -1,16 +1,14 @@ { "name": "aws-layer", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "aws-layer", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-bedrock-agent-runtime": "^3.622.0", - "@aws-sdk/client-bedrock-runtime": "^3.622.0", "@aws-sdk/client-comprehend": "^3.621.0", "@aws-sdk/client-kendra": "^3.621.0", "@aws-sdk/client-lambda": "^3.621.0", @@ -18,19 +16,6 @@ "@aws-sdk/client-translate": "^3.621.0" } }, - "node_modules/@aws-crypto/crc32": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", - "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", - "dependencies": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, "node_modules/@aws-crypto/crc32c": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", @@ -99,17 +84,17 @@ "tslib": "^2.6.2" } }, - "node_modules/@aws-sdk/client-bedrock-agent-runtime": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-agent-runtime/-/client-bedrock-agent-runtime-3.622.0.tgz", - "integrity": "sha512-rCX/LSAPjk7ZOMzNF2yruHTuqbZnfsKya0FTiyKm6GDsNI1rWmx/dx/fh8NH2LOOfxiNSqMez2Wv2biUyZ46Jw==", + "node_modules/@aws-sdk/client-comprehend": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-comprehend/-/client-comprehend-3.621.0.tgz", + "integrity": "sha512-OEO5obeYkBMRWBs863fTTzGrqs5lxUydg52K6XYcexXWMTEyoAWhRlxERDzC94rfEoowQ2Xyf8Y3qI0CAaNLlA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -120,40 +105,38 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", - "@smithy/eventstream-serde-browser": "^3.0.5", - "@smithy/eventstream-serde-config-resolver": "^3.0.3", - "@smithy/eventstream-serde-node": "^3.0.4", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" + "tslib": "^2.6.2", + "uuid": "^9.0.1" }, "engines": { "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/is-array-buffer": { + "node_modules/@aws-sdk/client-comprehend/node_modules/@smithy/is-array-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", @@ -164,7 +147,7 @@ "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-buffer-from": { + "node_modules/@aws-sdk/client-comprehend/node_modules/@smithy/util-buffer-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", @@ -176,7 +159,7 @@ "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-utf8": { + "node_modules/@aws-sdk/client-comprehend/node_modules/@smithy/util-utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", @@ -188,17 +171,17 @@ "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.622.0.tgz", - "integrity": "sha512-zJJWnHdORNNSM74yTeya5UyzEfXrFJDAuU7/JPc8PerURC5QElwWHNq6OR9AVTmJNvgs66XNZDgt46FStphMbQ==", + "node_modules/@aws-sdk/client-kendra": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-kendra/-/client-kendra-3.621.0.tgz", + "integrity": "sha512-OdftXrxoECqYMrIQmzmPygWCUxag5Mb+RpNDBtoQro1Tk/AkUNkOQcC9+eUzsvvahi6JQwqXZx1y2ywwvLOARg==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -209,41 +192,38 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", - "@smithy/eventstream-serde-browser": "^3.0.5", - "@smithy/eventstream-serde-config-resolver": "^3.0.3", - "@smithy/eventstream-serde-node": "^3.0.4", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", - "@smithy/util-stream": "^3.1.3", "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" + "tslib": "^2.6.2", + "uuid": "^9.0.1" }, "engines": { "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/is-array-buffer": { + "node_modules/@aws-sdk/client-kendra/node_modules/@smithy/is-array-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", @@ -254,7 +234,7 @@ "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-buffer-from": { + "node_modules/@aws-sdk/client-kendra/node_modules/@smithy/util-buffer-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", @@ -266,7 +246,7 @@ "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-utf8": { + "node_modules/@aws-sdk/client-kendra/node_modules/@smithy/util-utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", @@ -278,10 +258,10 @@ "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-comprehend": { + "node_modules/@aws-sdk/client-lambda": { "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-comprehend/-/client-comprehend-3.621.0.tgz", - "integrity": "sha512-OEO5obeYkBMRWBs863fTTzGrqs5lxUydg52K6XYcexXWMTEyoAWhRlxERDzC94rfEoowQ2Xyf8Y3qI0CAaNLlA==", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.621.0.tgz", + "integrity": "sha512-QD3FOMOLc9CQqfYOEzpTlB9LZbpN+0BrLUpc4+kNa+IheD5kes6gRRLB3Y1OLY4GIRTfPnYPTeFnW8AsSbcNzQ==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -300,6 +280,9 @@ "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", "@smithy/core": "^2.3.1", + "@smithy/eventstream-serde-browser": "^3.0.5", + "@smithy/eventstream-serde-config-resolver": "^3.0.3", + "@smithy/eventstream-serde-node": "^3.0.4", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", @@ -322,36 +305,91 @@ "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", + "@smithy/util-stream": "^3.1.3", "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2", - "uuid": "^9.0.1" + "@smithy/util-waiter": "^3.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-comprehend/node_modules/@aws-sdk/client-sso": { + "node_modules/@aws-sdk/client-s3": { "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", - "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.621.0.tgz", + "integrity": "sha512-YhGkd2HQTM4HCYJIAVWvfbUMpOF7XUr1W/e2LN3CFP0WTF4zcCJKesJ2iNHrExqC0Ek1+qarMxiXBK95itfjYQ==", "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", + "@aws-sdk/middleware-bucket-endpoint": "3.620.0", + "@aws-sdk/middleware-expect-continue": "3.620.0", + "@aws-sdk/middleware-flexible-checksums": "3.620.0", "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-location-constraint": "3.609.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-sdk-s3": "3.621.0", + "@aws-sdk/middleware-signing": "3.620.0", + "@aws-sdk/middleware-ssec": "3.609.0", "@aws-sdk/middleware-user-agent": "3.620.0", "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/signature-v4-multi-region": "3.621.0", "@aws-sdk/types": "3.609.0", "@aws-sdk/util-endpoints": "3.614.0", "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", + "@aws-sdk/xml-builder": "3.609.0", "@smithy/config-resolver": "^3.0.5", "@smithy/core": "^2.3.1", + "@smithy/eventstream-serde-browser": "^3.0.5", + "@smithy/eventstream-serde-config-resolver": "^3.0.3", + "@smithy/eventstream-serde-node": "^3.0.4", "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-blob-browser": "^3.1.2", "@smithy/hash-node": "^3.0.3", + "@smithy/hash-stream-node": "^3.1.2", "@smithy/invalid-dependency": "^3.0.3", + "@smithy/md5-js": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-retry": "^3.0.13", @@ -369,24 +407,76 @@ "@smithy/util-defaults-mode-browser": "^3.0.13", "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", + "@smithy/util-stream": "^3.1.3", "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-signing": { + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.620.0.tgz", + "integrity": "sha512-gxI7rubiaanUXaLfJ4NybERa9MGPNg2Ycl/OqANsozrBnR3Pw8vqy3EuVImQOyn2pJ2IFvl8ZPoSMHf4pX56FQ==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" }, "engines": { "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-comprehend/node_modules/@aws-sdk/client-sso-oidc": { + "node_modules/@aws-sdk/client-sso": { "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", - "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", + "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -425,19 +515,15 @@ }, "engines": { "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.621.0" } }, - "node_modules/@aws-sdk/client-comprehend/node_modules/@aws-sdk/client-sts": { + "node_modules/@aws-sdk/client-sso-oidc": { "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", - "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", + "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.621.0", "@aws-sdk/core": "3.621.0", "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", @@ -478,1324 +564,40 @@ }, "engines": { "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.621.0" } }, - "node_modules/@aws-sdk/client-comprehend/node_modules/@aws-sdk/core": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", - "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", + "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", "dependencies": { - "@smithy/core": "^2.3.1", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/util-middleware": "^3.0.3", - "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" }, "engines": { "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-comprehend/node_modules/@aws-sdk/credential-provider-http": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", - "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", + "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", "dependencies": { - "@aws-sdk/types": "3.609.0", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/property-provider": "^3.1.3", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/util-stream": "^3.1.3", + "@smithy/is-array-buffer": "^3.0.0", "tslib": "^2.6.2" }, "engines": { "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-comprehend/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", - "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", + "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", "dependencies": { - "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.621.0", - "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.621.0", - "@aws-sdk/credential-provider-web-identity": "3.621.0", - "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.2.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.621.0" - } - }, - "node_modules/@aws-sdk/client-comprehend/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", - "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.621.0", - "@aws-sdk/credential-provider-ini": "3.621.0", - "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.621.0", - "@aws-sdk/credential-provider-web-identity": "3.621.0", - "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.2.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-comprehend/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", - "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", - "dependencies": { - "@aws-sdk/client-sso": "3.621.0", - "@aws-sdk/token-providers": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-comprehend/node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-comprehend/node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-comprehend/node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", - "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-kendra": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-kendra/-/client-kendra-3.621.0.tgz", - "integrity": "sha512-OdftXrxoECqYMrIQmzmPygWCUxag5Mb+RpNDBtoQro1Tk/AkUNkOQcC9+eUzsvvahi6JQwqXZx1y2ywwvLOARg==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.621.0", - "@aws-sdk/client-sts": "3.621.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-kendra/node_modules/@aws-sdk/client-sso": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", - "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-kendra/node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", - "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.621.0" - } - }, - "node_modules/@aws-sdk/client-kendra/node_modules/@aws-sdk/client-sts": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", - "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.621.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-kendra/node_modules/@aws-sdk/core": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", - "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", - "dependencies": { - "@smithy/core": "^2.3.1", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/util-middleware": "^3.0.3", - "fast-xml-parser": "4.4.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-kendra/node_modules/@aws-sdk/credential-provider-http": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", - "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", - "dependencies": { - "@aws-sdk/types": "3.609.0", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/property-provider": "^3.1.3", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/util-stream": "^3.1.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-kendra/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", - "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.621.0", - "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.621.0", - "@aws-sdk/credential-provider-web-identity": "3.621.0", - "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.2.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.621.0" - } - }, - "node_modules/@aws-sdk/client-kendra/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", - "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.621.0", - "@aws-sdk/credential-provider-ini": "3.621.0", - "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.621.0", - "@aws-sdk/credential-provider-web-identity": "3.621.0", - "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.2.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-kendra/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", - "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", - "dependencies": { - "@aws-sdk/client-sso": "3.621.0", - "@aws-sdk/token-providers": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-kendra/node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-kendra/node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-kendra/node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", - "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.621.0.tgz", - "integrity": "sha512-QD3FOMOLc9CQqfYOEzpTlB9LZbpN+0BrLUpc4+kNa+IheD5kes6gRRLB3Y1OLY4GIRTfPnYPTeFnW8AsSbcNzQ==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.621.0", - "@aws-sdk/client-sts": "3.621.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/eventstream-serde-browser": "^3.0.5", - "@smithy/eventstream-serde-config-resolver": "^3.0.3", - "@smithy/eventstream-serde-node": "^3.0.4", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-stream": "^3.1.3", - "@smithy/util-utf8": "^3.0.0", - "@smithy/util-waiter": "^3.1.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/client-sso": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", - "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", - "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.621.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/client-sts": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", - "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.621.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/core": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", - "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", - "dependencies": { - "@smithy/core": "^2.3.1", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/util-middleware": "^3.0.3", - "fast-xml-parser": "4.4.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-http": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", - "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", - "dependencies": { - "@aws-sdk/types": "3.609.0", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/property-provider": "^3.1.3", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/util-stream": "^3.1.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", - "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.621.0", - "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.621.0", - "@aws-sdk/credential-provider-web-identity": "3.621.0", - "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.2.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.621.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", - "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.621.0", - "@aws-sdk/credential-provider-ini": "3.621.0", - "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.621.0", - "@aws-sdk/credential-provider-web-identity": "3.621.0", - "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.2.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", - "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", - "dependencies": { - "@aws-sdk/client-sso": "3.621.0", - "@aws-sdk/token-providers": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", - "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-s3": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.621.0.tgz", - "integrity": "sha512-YhGkd2HQTM4HCYJIAVWvfbUMpOF7XUr1W/e2LN3CFP0WTF4zcCJKesJ2iNHrExqC0Ek1+qarMxiXBK95itfjYQ==", - "dependencies": { - "@aws-crypto/sha1-browser": "5.2.0", - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.621.0", - "@aws-sdk/client-sts": "3.621.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", - "@aws-sdk/middleware-bucket-endpoint": "3.620.0", - "@aws-sdk/middleware-expect-continue": "3.620.0", - "@aws-sdk/middleware-flexible-checksums": "3.620.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-location-constraint": "3.609.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-sdk-s3": "3.621.0", - "@aws-sdk/middleware-signing": "3.620.0", - "@aws-sdk/middleware-ssec": "3.609.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/signature-v4-multi-region": "3.621.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@aws-sdk/xml-builder": "3.609.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/eventstream-serde-browser": "^3.0.5", - "@smithy/eventstream-serde-config-resolver": "^3.0.3", - "@smithy/eventstream-serde-node": "^3.0.4", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-blob-browser": "^3.1.2", - "@smithy/hash-node": "^3.0.3", - "@smithy/hash-stream-node": "^3.1.2", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/md5-js": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-stream": "^3.1.3", - "@smithy/util-utf8": "^3.0.0", - "@smithy/util-waiter": "^3.1.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sso": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", - "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", - "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.621.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sts": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", - "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.621.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/core": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", - "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", - "dependencies": { - "@smithy/core": "^2.3.1", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/util-middleware": "^3.0.3", - "fast-xml-parser": "4.4.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-http": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", - "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", - "dependencies": { - "@aws-sdk/types": "3.609.0", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/property-provider": "^3.1.3", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/util-stream": "^3.1.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", - "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.621.0", - "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.621.0", - "@aws-sdk/credential-provider-web-identity": "3.621.0", - "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.2.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.621.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", - "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.621.0", - "@aws-sdk/credential-provider-ini": "3.621.0", - "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.621.0", - "@aws-sdk/credential-provider-web-identity": "3.621.0", - "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.2.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", - "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", - "dependencies": { - "@aws-sdk/client-sso": "3.621.0", - "@aws-sdk/token-providers": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-signing": { - "version": "3.620.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.620.0.tgz", - "integrity": "sha512-gxI7rubiaanUXaLfJ4NybERa9MGPNg2Ycl/OqANsozrBnR3Pw8vqy3EuVImQOyn2pJ2IFvl8ZPoSMHf4pX56FQ==", - "dependencies": { - "@aws-sdk/types": "3.609.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/protocol-http": "^4.1.0", - "@smithy/signature-v4": "^4.1.0", - "@smithy/types": "^3.3.0", - "@smithy/util-middleware": "^3.0.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", - "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.622.0.tgz", - "integrity": "sha512-DJwUqVR/O2lImbktUHOpaQ8XElNBx3JmWzTT2USg6jh3ErgG1CS6LIV+VUlgtxGl+tFN/G6AcAV8SdnnGydB8Q==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.622.0.tgz", - "integrity": "sha512-dwWDfN+S98npeY77Ugyv8VIHKRHN+n/70PWE4EgolcjaMrTINjvUh9a/SypFEs5JmBOAeCQt8S2QpM3Wvzp+pQ==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" - } - }, - "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", - "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" }, "engines": { @@ -1837,151 +639,16 @@ "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-sts": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.622.0.tgz", - "integrity": "sha512-Yqtdf/wn3lcFVS42tR+zbz4HLyWxSmztjVW9L/yeMlvS7uza5nSkWqP/7ca+RxZnXLyrnA4jJtSHqykcErlhyg==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-sts/node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-sts/node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-sts/node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", - "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-translate": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-translate/-/client-translate-3.621.0.tgz", - "integrity": "sha512-xECN0dt6erzA5lXFyYfXyTHKXRPz67QEbw+6S0bnX4gu0SutzJ7DQSTw6ykWmk+fnjwUAw1qBfpDhybGk4oOcw==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.621.0", - "@aws-sdk/client-sts": "3.621.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-translate/node_modules/@aws-sdk/client-sso": { + "node_modules/@aws-sdk/client-sts": { "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", - "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", + "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.621.0", "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -2022,66 +689,50 @@ "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-translate/node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", - "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", + "node_modules/@aws-sdk/client-sts/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.621.0", - "@aws-sdk/credential-provider-node": "3.621.0", - "@aws-sdk/middleware-host-header": "3.620.0", - "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-user-agent": "3.620.0", - "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@aws-sdk/util-endpoints": "3.614.0", - "@aws-sdk/util-user-agent-browser": "3.609.0", - "@aws-sdk/util-user-agent-node": "3.614.0", - "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.1", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/hash-node": "^3.0.3", - "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.5", - "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.13", - "@smithy/middleware-serde": "^3.0.3", - "@smithy/middleware-stack": "^3.0.3", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/url-parser": "^3.0.3", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.13", - "@smithy/util-defaults-mode-node": "^3.0.13", - "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-retry": "^3.0.3", - "@smithy/util-utf8": "^3.0.0", "tslib": "^2.6.2" }, "engines": { "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sts/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.621.0" + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sts/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-translate/node_modules/@aws-sdk/client-sts": { + "node_modules/@aws-sdk/client-translate": { "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", - "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-translate/-/client-translate-3.621.0.tgz", + "integrity": "sha512-xECN0dt6erzA5lXFyYfXyTHKXRPz67QEbw+6S0bnX4gu0SutzJ7DQSTw6ykWmk+fnjwUAw1qBfpDhybGk4oOcw==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", "@aws-sdk/core": "3.621.0", "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", @@ -2118,108 +769,8 @@ "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-translate/node_modules/@aws-sdk/core": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", - "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", - "dependencies": { - "@smithy/core": "^2.3.1", - "@smithy/node-config-provider": "^3.1.4", - "@smithy/protocol-http": "^4.1.0", - "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/util-middleware": "^3.0.3", - "fast-xml-parser": "4.4.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-translate/node_modules/@aws-sdk/credential-provider-http": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", - "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", - "dependencies": { - "@aws-sdk/types": "3.609.0", - "@smithy/fetch-http-handler": "^3.2.4", - "@smithy/node-http-handler": "^3.1.4", - "@smithy/property-provider": "^3.1.3", - "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.11", - "@smithy/types": "^3.3.0", - "@smithy/util-stream": "^3.1.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-translate/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", - "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.621.0", - "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.621.0", - "@aws-sdk/credential-provider-web-identity": "3.621.0", - "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.2.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.621.0" - } - }, - "node_modules/@aws-sdk/client-translate/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", - "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.621.0", - "@aws-sdk/credential-provider-ini": "3.621.0", - "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.621.0", - "@aws-sdk/credential-provider-web-identity": "3.621.0", - "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.2.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-translate/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.621.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", - "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", - "dependencies": { - "@aws-sdk/client-sso": "3.621.0", - "@aws-sdk/token-providers": "3.614.0", - "@aws-sdk/types": "3.609.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/shared-ini-file-loader": "^3.1.4", - "@smithy/types": "^3.3.0", - "tslib": "^2.6.2" + "tslib": "^2.6.2", + "uuid": "^9.0.1" }, "engines": { "node": ">=16.0.0" @@ -2261,15 +812,15 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.622.0.tgz", - "integrity": "sha512-q1Ct2AjPxGtQBKtDpqm1umu3f4cuWMnEHTuDa6zjjaj+Aq/C6yxLgZJo9SlcU0tMl8rUCN7oFonszfTtp4Y0MA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", + "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", "dependencies": { - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "fast-xml-parser": "4.4.1", @@ -2294,16 +845,16 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.622.0.tgz", - "integrity": "sha512-VUHbr24Oll1RK3WR8XLUugLpgK9ZuxEm/NVeVqyFts1Ck9gsKpRg1x4eH7L7tW3SJ4TDEQNMbD7/7J+eoL2svg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", + "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/property-provider": "^3.1.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-stream": "^3.1.3", "tslib": "^2.6.2" @@ -2313,14 +864,14 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.622.0.tgz", - "integrity": "sha512-cD/6O9jOfzQyo8oyAbTKnyRO89BIMSTzwaN4NxGySC6pYVTqxNSWdRwaqg/vKbwJpjbPGGYYXpXEW11kop7dlg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", + "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -2333,19 +884,19 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.622.0.tgz", - "integrity": "sha512-keldwz4Q/6TYc37JH6m43HumN7Vi+R0AuGuHn5tBV40Vi7IiqEzjpiE+yvsHIN+duUheFLL3j/o0H32jb+14DQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", + "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -2374,11 +925,11 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.622.0.tgz", - "integrity": "sha512-zrSoBVM2JlwvkBtrcUd4J/9CrG+T+hUy9r6jwo5gonFIN3QkneR/pqpbUn/n32Zy3zlzCo2VfB31g7MjG7kJmg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", + "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", "dependencies": { - "@aws-sdk/client-sso": "3.622.0", + "@aws-sdk/client-sso": "3.621.0", "@aws-sdk/token-providers": "3.614.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -2456,6 +1007,19 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/is-array-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", @@ -2817,15 +1381,15 @@ } }, "node_modules/@smithy/core": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.2.tgz", - "integrity": "sha512-in5wwt6chDBcUv1Lw1+QzZxN9fBffi+qOixfb65yK4sDuKG7zAUO9HAFqmVzsZM3N+3tTyvZjtnDXePpvp007Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.1.tgz", + "integrity": "sha512-BC7VMXx/1BCmRPCVzzn4HGWAtsrb7/0758EtwOGFJQrlSwJBEjCcDLNZLFoL/68JexYa2s+KmgL/UfmXdG6v1w==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "tslib": "^2.6.2" @@ -2849,17 +1413,6 @@ "node": ">=16.0.0" } }, - "node_modules/@smithy/eventstream-codec": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz", - "integrity": "sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw==", - "dependencies": { - "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^3.3.0", - "@smithy/util-hex-encoding": "^3.0.0", - "tslib": "^2.6.2" - } - }, "node_modules/@smithy/eventstream-serde-browser": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.5.tgz", @@ -2911,6 +1464,30 @@ "node": ">=16.0.0" } }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/@smithy/eventstream-codec": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz", + "integrity": "sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" + } + }, "node_modules/@smithy/fetch-http-handler": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz", @@ -3127,14 +1704,14 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.14.tgz", - "integrity": "sha512-7ZaWZJOjUxa5hgmuMspyt8v/zVsh0GXYuF7OvCmdcbVa/xbnKQoYC+uYKunAqRGTkxjOyuOCw9rmFUFOqqC0eQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/service-error-classification": "^3.0.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -3324,9 +1901,9 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -3451,12 +2028,12 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.14.tgz", - "integrity": "sha512-0iwTgKKmAIf+vFLV8fji21Jb2px11ktKVxbX6LIDPAUJyWQqGqBVfwba7xwa1f2FZUoolYQgLvxQEpJycXuQ5w==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", "dependencies": { "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -3466,15 +2043,15 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.14.tgz", - "integrity": "sha512-e9uQarJKfXApkTMMruIdxHprhcXivH1flYCe8JRDTzkkLx8dA3V5J8GZlST9yfDiRWkJpZJlUXGN9Rc9Ade3OQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", "dependencies": { "@smithy/config-resolver": "^3.0.5", "@smithy/credential-provider-imds": "^3.2.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, diff --git a/source/lambda/aws-sdk-layer/package.json b/source/lambda/aws-sdk-layer/package.json index 4a5a7813f..130b7dd2b 100644 --- a/source/lambda/aws-sdk-layer/package.json +++ b/source/lambda/aws-sdk-layer/package.json @@ -1,6 +1,6 @@ { "name": "aws-layer", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot Lambda aws-sdk-layer", "main": "index.js", "scripts": { @@ -12,8 +12,6 @@ }, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-bedrock-agent-runtime": "^3.622.0", - "@aws-sdk/client-bedrock-runtime": "^3.622.0", "@aws-sdk/client-comprehend": "^3.621.0", "@aws-sdk/client-kendra": "^3.621.0", "@aws-sdk/client-lambda": "^3.621.0", diff --git a/source/lambda/cfn-lambda-layer/package-lock.json b/source/lambda/cfn-lambda-layer/package-lock.json index fe8b901fd..e45935b53 100644 --- a/source/lambda/cfn-lambda-layer/package-lock.json +++ b/source/lambda/cfn-lambda-layer/package-lock.json @@ -1,12 +1,12 @@ { "name": "cfn-lambda-layer", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "cfn-lambda-layer", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "cfn-lambda": "^5.1.0" diff --git a/source/lambda/cfn-lambda-layer/package.json b/source/lambda/cfn-lambda-layer/package.json index 2f8781839..700459821 100644 --- a/source/lambda/cfn-lambda-layer/package.json +++ b/source/lambda/cfn-lambda-layer/package.json @@ -1,6 +1,6 @@ { "name": "cfn-lambda-layer", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot Cfn Lambda Layer", "main": "index.js", "scripts": { diff --git a/source/lambda/cfn/lib/PostUpgradeImport.js b/source/lambda/cfn/lib/PostUpgradeImport.js index 652051a24..2825e9180 100644 --- a/source/lambda/cfn/lib/PostUpgradeImport.js +++ b/source/lambda/cfn/lib/PostUpgradeImport.js @@ -17,7 +17,7 @@ const customSdkConfig = require('./util/customSdkConfig'); const region = process.env.AWS_REGION || 'us-east-1'; const s3 = new S3Client(customSdkConfig({ region })); -async function copyData(s3exportparms, s3importparms) { +async function copyData(oldS3ExportParams, s3exportparms, s3importparms) { console.log('Reading previously exported data'); try { const res = await s3.send(new GetObjectCommand (s3exportparms)); @@ -31,7 +31,22 @@ async function copyData(s3exportparms, s3importparms) { console.log('Export file has no data - skipping import'); } return count; - } catch (err) { + } + catch (err) { + // Necessary for backwards compatibility. + if (err.name === 'AccessDenied') { + const res = await s3.send(new GetObjectCommand (oldS3ExportParams)); + const data_json = await res.Body.transformToString(); + const count = data_json.length; + if (count > 0) { + console.log(`Copy data to import bucket: length: ${count}`); + s3importparms.Body = data_json; + await s3.send(new PutObjectCommand(s3importparms)); + } else { + console.log('Export file has no data - skipping import'); + } + return count; + } console.log('No previously exported data:', err); return 0; } @@ -44,7 +59,7 @@ async function waitForImport(s3params, timeout) { let complete = false; let timedout = false; do { - await new Promise((resolve) => setTimeout(resolve, 1000)); + await new Promise((resolve) => setTimeout(resolve, 3000)); try { const res = await s3.send(new GetObjectCommand(s3params)); const readableStream = Buffer.concat(await res.Body.toArray()) @@ -62,8 +77,7 @@ async function waitForImport(s3params, timeout) { return complete; } -async function run_import(params, reply) { - const ID = 'PostUpgradeImport'; +async function run_import(params) { const data = { bucket: params.importbucket, index: params.index, @@ -74,51 +88,52 @@ async function run_import(params, reply) { filter: '', status: 'Started', }; - const s3exportparms = { + const oldS3ExportParams = { Bucket: params.exportbucket, - Key: data.key, + Key: `data-export/${params.id}`, + }; + const s3exportparms = { + Bucket: params.contentDesignerOutputBucket, + Key: `data-export/${params.id}`, }; const s3importparms = { Bucket: params.importbucket, Key: data.key, }; - const exportfile = `${params.exportbucket}/${data.key}`; + const exportfile = `${params.contentDesignerOutputBucket}/data-export/${params.id}`; const importfile = `${params.importbucket}/${data.key}`; console.log(`copy export file ${exportfile} to import bucket ${importfile}`); - const count = await copyData(s3exportparms, s3importparms); + const count = await copyData(oldS3ExportParams, s3exportparms, s3importparms); if (count > 0) { console.log('Running import process.'); const s3params = { - Bucket: params.importbucket, - Key: data.config, + Bucket: params.contentDesignerOutputBucket, + Key: `status-import/${params.id}`, }; console.log('Wait up to 60 seconds for status to be completed'); - delete s3params.Body; const complete = await waitForImport(s3params, 60000); if (complete) { console.log('Import completed: ', exportfile); - reply(null, ID); } else { console.log('Import did NOT complete: ', exportfile); - reply(null, ID); } } else { console.log('No records to import in: ', exportfile); - reply(null, ID); } } -module.exports = class PostUpgradeImport extends require('./base') { - constructor() { - super(); +module.exports = class PostUpgradeImport{ + + async AsyncCreate() { + return 'This is a new install -- no import required.'; } - async Create(params, reply) { - await run_import(params, reply); + async AsyncUpdate(ID, params, oldparams) { + await run_import(params); } - async Update(ID, params, oldparams, reply) { - await run_import(params, reply); + async AsyncDelete() { + return 'We are deleting the stack -- no import required.'; } -}; +}; \ No newline at end of file diff --git a/source/lambda/cfn/lib/PreUpgradeExport.js b/source/lambda/cfn/lib/PreUpgradeExport.js index 3e1549caa..1466af231 100644 --- a/source/lambda/cfn/lib/PreUpgradeExport.js +++ b/source/lambda/cfn/lib/PreUpgradeExport.js @@ -17,20 +17,37 @@ const customSdkConfig = require('./util/customSdkConfig'); const region = process.env.AWS_REGION || 'us-east-1'; const s3 = new S3Client(customSdkConfig({ region })); -async function waitForExport(s3params, timeout) { +async function waitForExport(oldS3Params, s3params, timeout) { console.log('Checking the status of export'); const now = Date.now(); const stoptime = now + timeout; let complete = false; let timedout = false; do { - await new Promise((resolve) => setTimeout(resolve, 1000)); - const res = await s3.send(new GetObjectCommand(s3params)); - const readableStream = Buffer.concat(await res.Body.toArray()) - const body = JSON.parse(readableStream); - console.log(body.status); - complete = (body.status == 'Completed'); - timedout = (Date.now() > stoptime); + try { + console.log(JSON.stringify(s3params)); + await new Promise((resolve) => setTimeout(resolve, 1000)); + const res = await s3.send(new GetObjectCommand(s3params)); + const readableStream = Buffer.concat(await res.Body.toArray()) + const body = JSON.parse(readableStream); + console.log(body.status); + complete = (body.status == 'Completed'); + timedout = (Date.now() > stoptime); + } + catch(err){ + // Neccessary for backwards compatibility. + if (err.name === 'AccessDenied') { + console.log('Checking the status of export with outdated configuration.'); + console.log(JSON.stringify(oldS3Params)); + await new Promise((resolve) => setTimeout(resolve, 1000)); + const res = await s3.send(new GetObjectCommand(oldS3Params)); + const readableStream = Buffer.concat(await res.Body.toArray()) + const body = JSON.parse(readableStream); + console.log(body.status); + complete = (body.status == 'Completed'); + timedout = (Date.now() > stoptime); + } + } } while (!complete && !timedout); if (!complete && timedout) { console.log('Timed out.'); @@ -38,18 +55,22 @@ async function waitForExport(s3params, timeout) { return complete; } -async function run_export(params, reply) { - const ID = 'PreUpgradeExport'; +async function run_export(params) { const data = { bucket: params.bucket, index: params.index, id: params.id, - config: `status/${params.id}`, + config: `status-export/${params.id}`, tmp: `tmp/${params.id}`, - key: `data/${params.id}`, + key: `data-export/${params.id}`, filter: '', status: 'Started', }; + const oldS3Params = { + Bucket: data.bucket, + Key: `status/${params.id}`, + Body: JSON.stringify(data), + } const s3params = { Bucket: data.bucket, Key: data.config, @@ -58,30 +79,34 @@ async function run_export(params, reply) { const statusfile = `${data.bucket}/${data.config}`; console.log('Running content export as backup before upgrade.'); // Create object in export bucket to trigger export lambda + await s3.send(new PutObjectCommand(oldS3Params)); await s3.send(new PutObjectCommand(s3params)); console.log('Wait up to 60 seconds for status to be completed'); - delete s3params.Body; - const complete = await waitForExport(s3params, 60000); + delete oldS3Params.Body; + const contentDesignerS3Params = { + Bucket: params.contentDesignerOutputBucket, + Key: data.config + } + const complete = await waitForExport(oldS3Params, contentDesignerS3Params, 60000); if (complete) { console.log('Export completed: ', statusfile); - reply(null, ID); } else { console.log('Export did NOT complete - possibly this is a new install - delete status file so it doesn\'t show up in Exports list in console: ', statusfile); await s3.send(new DeleteObjectCommand(s3params)); - reply(null, ID); } } -module.exports = class PreUpgradeExport extends require('./base') { - constructor() { - super(); +module.exports = class PreUpgradeExport { + + async AsyncCreate() { + return 'This is a new install -- no export required.'; } - async Create(params, reply) { - await run_export(params, reply); + async AsyncUpdate(ID, params, oldparams) { + await run_export(params); } - async Update(ID, params, oldparams, reply) { - await run_export(params, reply); + async AsyncDelete() { + return 'We are deleting the stack -- no export required.'; } }; diff --git a/source/lambda/cfn/package-lock.json b/source/lambda/cfn/package-lock.json index 684d582e4..ed9481e68 100644 --- a/source/lambda/cfn/package-lock.json +++ b/source/lambda/cfn/package-lock.json @@ -1,12 +1,12 @@ { "name": "cfn", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cfn", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-api-gateway": "^3.621.0", @@ -43,19 +43,6 @@ "node": ">=6.0.0" } }, - "node_modules/@aws-crypto/crc32": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", - "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", - "dependencies": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, "node_modules/@aws-crypto/crc32c": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", @@ -79,41 +66,6 @@ "tslib": "^2.6.2" } }, - "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@aws-crypto/sha256-browser": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", @@ -128,41 +80,6 @@ "tslib": "^2.6.2" } }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@aws-crypto/sha256-js": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", @@ -194,41 +111,6 @@ "tslib": "^2.6.2" } }, - "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@aws-sdk/client-api-gateway": { "version": "3.621.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-api-gateway/-/client-api-gateway-3.621.0.tgz", @@ -282,6 +164,41 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/client-api-gateway/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-api-gateway/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-api-gateway/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/client-cognito-identity": { "version": "3.621.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.621.0.tgz", @@ -384,6 +301,76 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/client-iam": { "version": "3.621.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-iam/-/client-iam-3.621.0.tgz", @@ -436,6 +423,41 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/client-iam/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-iam/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-iam/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/client-lambda": { "version": "3.621.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.621.0.tgz", @@ -492,6 +514,41 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/client-lambda/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/client-lex-model-building-service": { "version": "3.621.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-model-building-service/-/client-lex-model-building-service-3.621.0.tgz", @@ -543,6 +600,41 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/client-lex-model-building-service/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-lex-model-building-service/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-lex-model-building-service/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/client-opensearch": { "version": "3.621.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-opensearch/-/client-opensearch-3.621.0.tgz", @@ -594,6 +686,41 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/client-opensearch/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-opensearch/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-opensearch/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/client-s3": { "version": "3.621.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.621.0.tgz", @@ -662,6 +789,58 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-signing": { + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.620.0.tgz", + "integrity": "sha512-gxI7rubiaanUXaLfJ4NybERa9MGPNg2Ycl/OqANsozrBnR3Pw8vqy3EuVImQOyn2pJ2IFvl8ZPoSMHf4pX56FQ==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/client-sso": { "version": "3.621.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", @@ -762,6 +941,76 @@ "@aws-sdk/client-sts": "^3.621.0" } }, + "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/client-sts": { "version": "3.621.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", @@ -812,6 +1061,41 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/client-sts/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sts/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sts/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/core": { "version": "3.621.0", "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", @@ -1049,6 +1333,54 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/middleware-host-header": { "version": "3.620.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.620.0.tgz", @@ -1138,17 +1470,35 @@ "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/middleware-signing": { - "version": "3.620.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.620.0.tgz", - "integrity": "sha512-gxI7rubiaanUXaLfJ4NybERa9MGPNg2Ycl/OqANsozrBnR3Pw8vqy3EuVImQOyn2pJ2IFvl8ZPoSMHf4pX56FQ==", + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", "dependencies": { - "@aws-sdk/types": "3.609.0", - "@smithy/property-provider": "^3.1.3", - "@smithy/protocol-http": "^4.1.0", - "@smithy/signature-v4": "^4.1.0", - "@smithy/types": "^3.3.0", - "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" }, "engines": { @@ -1271,14 +1621,14 @@ } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.568.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz", - "integrity": "sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.495.0.tgz", + "integrity": "sha512-MfaPXT0kLX2tQaR90saBT9fWQq2DHqSSJRzW+MZWsmF+y5LGCOhO22ac/2o6TKSQm7h0HRc2GaADqYYYor62yg==", "dependencies": { - "tslib": "^2.6.2" + "tslib": "^2.5.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-user-agent-browser": { @@ -2848,15 +3198,15 @@ } }, "node_modules/@smithy/core": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.2.tgz", - "integrity": "sha512-in5wwt6chDBcUv1Lw1+QzZxN9fBffi+qOixfb65yK4sDuKG7zAUO9HAFqmVzsZM3N+3tTyvZjtnDXePpvp007Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.1.tgz", + "integrity": "sha512-BC7VMXx/1BCmRPCVzzn4HGWAtsrb7/0758EtwOGFJQrlSwJBEjCcDLNZLFoL/68JexYa2s+KmgL/UfmXdG6v1w==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "tslib": "^2.6.2" @@ -2880,17 +3230,6 @@ "node": ">=16.0.0" } }, - "node_modules/@smithy/eventstream-codec": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz", - "integrity": "sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw==", - "dependencies": { - "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^3.3.0", - "@smithy/util-hex-encoding": "^3.0.0", - "tslib": "^2.6.2" - } - }, "node_modules/@smithy/eventstream-serde-browser": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.5.tgz", @@ -2942,6 +3281,30 @@ "node": ">=16.0.0" } }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/@smithy/eventstream-codec": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz", + "integrity": "sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" + } + }, "node_modules/@smithy/fetch-http-handler": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz", @@ -2979,6 +3342,41 @@ "node": ">=16.0.0" } }, + "node_modules/@smithy/hash-node/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-node/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-node/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@smithy/hash-stream-node": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.1.2.tgz", @@ -2992,6 +3390,41 @@ "node": ">=16.0.0" } }, + "node_modules/@smithy/hash-stream-node/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-stream-node/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-stream-node/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@smithy/invalid-dependency": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz", @@ -3002,14 +3435,14 @@ } }, "node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.1.1.tgz", + "integrity": "sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ==", "dependencies": { - "tslib": "^2.6.2" + "tslib": "^2.5.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=14.0.0" } }, "node_modules/@smithy/md5-js": { @@ -3022,6 +3455,41 @@ "tslib": "^2.6.2" } }, + "node_modules/@smithy/md5-js/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/md5-js/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/md5-js/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@smithy/middleware-content-length": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.5.tgz", @@ -3053,14 +3521,14 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.14.tgz", - "integrity": "sha512-7ZaWZJOjUxa5hgmuMspyt8v/zVsh0GXYuF7OvCmdcbVa/xbnKQoYC+uYKunAqRGTkxjOyuOCw9rmFUFOqqC0eQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/service-error-classification": "^3.0.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -3214,10 +3682,45 @@ "node": ">=16.0.0" } }, + "node_modules/@smithy/signature-v4/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/signature-v4/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/signature-v4/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -3264,6 +3767,41 @@ "node": ">=16.0.0" } }, + "node_modules/@smithy/util-base64/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-base64/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-base64/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@smithy/util-body-length-browser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", @@ -3284,15 +3822,15 @@ } }, "node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.1.1.tgz", + "integrity": "sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg==", "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" + "@smithy/is-array-buffer": "^2.1.1", + "tslib": "^2.5.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=14.0.0" } }, "node_modules/@smithy/util-config-provider": { @@ -3307,12 +3845,12 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.14.tgz", - "integrity": "sha512-0iwTgKKmAIf+vFLV8fji21Jb2px11ktKVxbX6LIDPAUJyWQqGqBVfwba7xwa1f2FZUoolYQgLvxQEpJycXuQ5w==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", "dependencies": { "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -3322,15 +3860,15 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.14.tgz", - "integrity": "sha512-e9uQarJKfXApkTMMruIdxHprhcXivH1flYCe8JRDTzkkLx8dA3V5J8GZlST9yfDiRWkJpZJlUXGN9Rc9Ade3OQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", "dependencies": { "@smithy/config-resolver": "^3.0.5", "@smithy/credential-provider-imds": "^3.2.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, @@ -3405,10 +3943,10 @@ "node": ">=16.0.0" } }, - "node_modules/@smithy/util-uri-escape": { + "node_modules/@smithy/util-stream/node_modules/@smithy/is-array-buffer": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", - "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", "dependencies": { "tslib": "^2.6.2" }, @@ -3416,7 +3954,19 @@ "node": ">=16.0.0" } }, - "node_modules/@smithy/util-utf8": { + "node_modules/@smithy/util-stream/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-stream/node_modules/@smithy/util-utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", @@ -3428,6 +3978,29 @@ "node": ">=16.0.0" } }, + "node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.2.0.tgz", + "integrity": "sha512-hBsKr5BqrDrKS8qy+YcV7/htmMGxriA1PREOf/8AGBhHIZnfilVv1Waf1OyKhSbFW15U/8+gcMUQ9/Kk5qwpHQ==", + "dependencies": { + "@smithy/util-buffer-from": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@smithy/util-waiter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.1.2.tgz", diff --git a/source/lambda/cfn/package.json b/source/lambda/cfn/package.json index dcd43d66b..d4142f03c 100644 --- a/source/lambda/cfn/package.json +++ b/source/lambda/cfn/package.json @@ -1,6 +1,6 @@ { "name": "cfn", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot Cfn Lambda", "main": "index.js", "scripts": { diff --git a/source/lambda/cfn/test/lib/PostUpgradeImport.test.js b/source/lambda/cfn/test/lib/PostUpgradeImport.test.js index e713212b0..f546e7d45 100644 --- a/source/lambda/cfn/test/lib/PostUpgradeImport.test.js +++ b/source/lambda/cfn/test/lib/PostUpgradeImport.test.js @@ -62,7 +62,7 @@ describe('test PostUpgradeImport class', () => { expect(result).toBe('PostUpgradeImport'); }; - await postUpgradeImportCut.Create(params, callback); + await postUpgradeImportCut.AsyncCreate(params, callback); }); it("should be equivalent to Create when Update is called", async () => { @@ -90,7 +90,7 @@ describe('test PostUpgradeImport class', () => { expect(result).toBe('PostUpgradeImport'); }; - await postUpgradeImportCut.Update('mock_id', params, {}, callback); + await postUpgradeImportCut.AsyncUpdate('mock_id', params, {}, callback); }); it("should catch error and passthrough when s3 error occurs in Create", async () => { @@ -108,6 +108,6 @@ describe('test PostUpgradeImport class', () => { expect(result).toBe('PostUpgradeImport'); }; - await postUpgradeImportCut.Create(params, callback); + await postUpgradeImportCut.AsyncCreate(params, callback); }); }); \ No newline at end of file diff --git a/source/lambda/cfn/test/lib/PreUpgradeExport.test.js b/source/lambda/cfn/test/lib/PreUpgradeExport.test.js index eef001b9f..3b549f747 100644 --- a/source/lambda/cfn/test/lib/PreUpgradeExport.test.js +++ b/source/lambda/cfn/test/lib/PreUpgradeExport.test.js @@ -57,7 +57,7 @@ describe('test PreUpgradeExport class', () => { expect(result).toBe('PreUpgradeExport'); }; - await preUpgradeExportCut.Create(params, callback); + await preUpgradeExportCut.AsyncCreate(params, callback); }); it("should be equivalent to Create when Update is called", async () => { @@ -78,6 +78,6 @@ describe('test PreUpgradeExport class', () => { expect(result).toBe('PreUpgradeExport'); }; - await preUpgradeExportCut.Update('mock_id', params, {}, callback); + await preUpgradeExportCut.AsyncUpdate('mock_id', params, {}, callback); }); }); \ No newline at end of file diff --git a/source/lambda/common-modules-layer/package-lock.json b/source/lambda/common-modules-layer/package-lock.json index 68fa77bb4..1aa5321b3 100644 --- a/source/lambda/common-modules-layer/package-lock.json +++ b/source/lambda/common-modules-layer/package-lock.json @@ -1,12 +1,12 @@ { "name": "common-modules-layer", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "common-modules-layer", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-providers": "^3.511.0", @@ -132,16 +132,16 @@ } }, "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.622.0.tgz", - "integrity": "sha512-VE4Mi6HMrs0Fpq8Nhgt3wBm5i7SyfTYD+FFW+Ofq1zMRWWePPqbs9HMSp6mLwynWL0SNcefYoIKqz2H/2e4mwQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.621.0.tgz", + "integrity": "sha512-FpXia5qFf6ijcNDWenVq+mP9r1LbiW/+52i9wrv2+Afi6Nn1ROf8W7St8WvE9TEZ3t78y+vis4CwqfGts+uiKA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -152,26 +152,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -183,13 +183,13 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.622.0.tgz", - "integrity": "sha512-DJwUqVR/O2lImbktUHOpaQ8XElNBx3JmWzTT2USg6jh3ErgG1CS6LIV+VUlgtxGl+tFN/G6AcAV8SdnnGydB8Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", + "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", + "@aws-sdk/core": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -200,26 +200,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -231,14 +231,14 @@ } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.622.0.tgz", - "integrity": "sha512-dwWDfN+S98npeY77Ugyv8VIHKRHN+n/70PWE4EgolcjaMrTINjvUh9a/SypFEs5JmBOAeCQt8S2QpM3Wvzp+pQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", + "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -249,26 +249,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -279,19 +279,19 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.622.0.tgz", - "integrity": "sha512-Yqtdf/wn3lcFVS42tR+zbz4HLyWxSmztjVW9L/yeMlvS7uza5nSkWqP/7ca+RxZnXLyrnA4jJtSHqykcErlhyg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", + "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -302,26 +302,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -333,15 +333,15 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.622.0.tgz", - "integrity": "sha512-q1Ct2AjPxGtQBKtDpqm1umu3f4cuWMnEHTuDa6zjjaj+Aq/C6yxLgZJo9SlcU0tMl8rUCN7oFonszfTtp4Y0MA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", + "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", "dependencies": { - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "fast-xml-parser": "4.4.1", @@ -352,11 +352,11 @@ } }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.622.0.tgz", - "integrity": "sha512-WXfTA1Q1bntE/KgoW+Vo2L2hgwr9YCHrfXgZLGQzCZwKQpW9iMWMxylSdn0NAHldN3fwiV/Oj6DqN0Tc8ScgNQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.621.0.tgz", + "integrity": "sha512-Q+3awvTVJSqIGRjCUQflRwKPKlZ0TfmL3EQHgFLhZZrToeBapEA62+FY+T70aTKAZZZZprlvYeFPtBloNd5ziA==", "dependencies": { - "@aws-sdk/client-cognito-identity": "3.622.0", + "@aws-sdk/client-cognito-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", "@smithy/types": "^3.3.0", @@ -381,16 +381,16 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.622.0.tgz", - "integrity": "sha512-VUHbr24Oll1RK3WR8XLUugLpgK9ZuxEm/NVeVqyFts1Ck9gsKpRg1x4eH7L7tW3SJ4TDEQNMbD7/7J+eoL2svg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", + "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/property-provider": "^3.1.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-stream": "^3.1.3", "tslib": "^2.6.2" @@ -400,14 +400,14 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.622.0.tgz", - "integrity": "sha512-cD/6O9jOfzQyo8oyAbTKnyRO89BIMSTzwaN4NxGySC6pYVTqxNSWdRwaqg/vKbwJpjbPGGYYXpXEW11kop7dlg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", + "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -420,19 +420,19 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.622.0.tgz", - "integrity": "sha512-keldwz4Q/6TYc37JH6m43HumN7Vi+R0AuGuHn5tBV40Vi7IiqEzjpiE+yvsHIN+duUheFLL3j/o0H32jb+14DQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", + "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -461,11 +461,11 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.622.0.tgz", - "integrity": "sha512-zrSoBVM2JlwvkBtrcUd4J/9CrG+T+hUy9r6jwo5gonFIN3QkneR/pqpbUn/n32Zy3zlzCo2VfB31g7MjG7kJmg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", + "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", "dependencies": { - "@aws-sdk/client-sso": "3.622.0", + "@aws-sdk/client-sso": "3.621.0", "@aws-sdk/token-providers": "3.614.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -495,20 +495,20 @@ } }, "node_modules/@aws-sdk/credential-providers": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.622.0.tgz", - "integrity": "sha512-ImfpItaPwnwNBRG04x6iDwRAclvtW2+kSu4amGiMWF+EvnjnRTnyejAA/7rdBuxA4nwM4nb8jed0jnRkZyTu7A==", - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.622.0", - "@aws-sdk/client-sso": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/credential-provider-cognito-identity": "3.622.0", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.621.0.tgz", + "integrity": "sha512-FQbC7I8ae/72ZekLBa45jWJ+Q3d+YPhc3bW/rCks6RrldM6RgLTGr8pTOPCxHl828ky10RjkBiBmVU818rliyw==", + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.621.0", + "@aws-sdk/client-sso": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/credential-provider-cognito-identity": "3.621.0", "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -724,15 +724,15 @@ } }, "node_modules/@smithy/core": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.2.tgz", - "integrity": "sha512-in5wwt6chDBcUv1Lw1+QzZxN9fBffi+qOixfb65yK4sDuKG7zAUO9HAFqmVzsZM3N+3tTyvZjtnDXePpvp007Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.1.tgz", + "integrity": "sha512-BC7VMXx/1BCmRPCVzzn4HGWAtsrb7/0758EtwOGFJQrlSwJBEjCcDLNZLFoL/68JexYa2s+KmgL/UfmXdG6v1w==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "tslib": "^2.6.2" @@ -833,14 +833,14 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.14.tgz", - "integrity": "sha512-7ZaWZJOjUxa5hgmuMspyt8v/zVsh0GXYuF7OvCmdcbVa/xbnKQoYC+uYKunAqRGTkxjOyuOCw9rmFUFOqqC0eQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/service-error-classification": "^3.0.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -995,9 +995,9 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -1087,12 +1087,12 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.14.tgz", - "integrity": "sha512-0iwTgKKmAIf+vFLV8fji21Jb2px11ktKVxbX6LIDPAUJyWQqGqBVfwba7xwa1f2FZUoolYQgLvxQEpJycXuQ5w==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", "dependencies": { "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -1102,15 +1102,15 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.14.tgz", - "integrity": "sha512-e9uQarJKfXApkTMMruIdxHprhcXivH1flYCe8JRDTzkkLx8dA3V5J8GZlST9yfDiRWkJpZJlUXGN9Rc9Ade3OQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", "dependencies": { "@smithy/config-resolver": "^3.0.5", "@smithy/credential-provider-imds": "^3.2.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, @@ -1467,16 +1467,16 @@ } }, "@aws-sdk/client-cognito-identity": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.622.0.tgz", - "integrity": "sha512-VE4Mi6HMrs0Fpq8Nhgt3wBm5i7SyfTYD+FFW+Ofq1zMRWWePPqbs9HMSp6mLwynWL0SNcefYoIKqz2H/2e4mwQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.621.0.tgz", + "integrity": "sha512-FpXia5qFf6ijcNDWenVq+mP9r1LbiW/+52i9wrv2+Afi6Nn1ROf8W7St8WvE9TEZ3t78y+vis4CwqfGts+uiKA==", "requires": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1487,26 +1487,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1515,13 +1515,13 @@ } }, "@aws-sdk/client-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.622.0.tgz", - "integrity": "sha512-DJwUqVR/O2lImbktUHOpaQ8XElNBx3JmWzTT2USg6jh3ErgG1CS6LIV+VUlgtxGl+tFN/G6AcAV8SdnnGydB8Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", + "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", "requires": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", + "@aws-sdk/core": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1532,26 +1532,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1560,14 +1560,14 @@ } }, "@aws-sdk/client-sso-oidc": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.622.0.tgz", - "integrity": "sha512-dwWDfN+S98npeY77Ugyv8VIHKRHN+n/70PWE4EgolcjaMrTINjvUh9a/SypFEs5JmBOAeCQt8S2QpM3Wvzp+pQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", + "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", "requires": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1578,26 +1578,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1606,15 +1606,15 @@ } }, "@aws-sdk/client-sts": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.622.0.tgz", - "integrity": "sha512-Yqtdf/wn3lcFVS42tR+zbz4HLyWxSmztjVW9L/yeMlvS7uza5nSkWqP/7ca+RxZnXLyrnA4jJtSHqykcErlhyg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", + "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", "requires": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1625,26 +1625,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1653,15 +1653,15 @@ } }, "@aws-sdk/core": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.622.0.tgz", - "integrity": "sha512-q1Ct2AjPxGtQBKtDpqm1umu3f4cuWMnEHTuDa6zjjaj+Aq/C6yxLgZJo9SlcU0tMl8rUCN7oFonszfTtp4Y0MA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", + "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", "requires": { - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "fast-xml-parser": "4.4.1", @@ -1669,11 +1669,11 @@ } }, "@aws-sdk/credential-provider-cognito-identity": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.622.0.tgz", - "integrity": "sha512-WXfTA1Q1bntE/KgoW+Vo2L2hgwr9YCHrfXgZLGQzCZwKQpW9iMWMxylSdn0NAHldN3fwiV/Oj6DqN0Tc8ScgNQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.621.0.tgz", + "integrity": "sha512-Q+3awvTVJSqIGRjCUQflRwKPKlZ0TfmL3EQHgFLhZZrToeBapEA62+FY+T70aTKAZZZZprlvYeFPtBloNd5ziA==", "requires": { - "@aws-sdk/client-cognito-identity": "3.622.0", + "@aws-sdk/client-cognito-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", "@smithy/types": "^3.3.0", @@ -1692,30 +1692,30 @@ } }, "@aws-sdk/credential-provider-http": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.622.0.tgz", - "integrity": "sha512-VUHbr24Oll1RK3WR8XLUugLpgK9ZuxEm/NVeVqyFts1Ck9gsKpRg1x4eH7L7tW3SJ4TDEQNMbD7/7J+eoL2svg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", + "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", "requires": { "@aws-sdk/types": "3.609.0", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/property-provider": "^3.1.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-stream": "^3.1.3", "tslib": "^2.6.2" } }, "@aws-sdk/credential-provider-ini": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.622.0.tgz", - "integrity": "sha512-cD/6O9jOfzQyo8oyAbTKnyRO89BIMSTzwaN4NxGySC6pYVTqxNSWdRwaqg/vKbwJpjbPGGYYXpXEW11kop7dlg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", + "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", "requires": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -1726,15 +1726,15 @@ } }, "@aws-sdk/credential-provider-node": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.622.0.tgz", - "integrity": "sha512-keldwz4Q/6TYc37JH6m43HumN7Vi+R0AuGuHn5tBV40Vi7IiqEzjpiE+yvsHIN+duUheFLL3j/o0H32jb+14DQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", + "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", "requires": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -1757,11 +1757,11 @@ } }, "@aws-sdk/credential-provider-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.622.0.tgz", - "integrity": "sha512-zrSoBVM2JlwvkBtrcUd4J/9CrG+T+hUy9r6jwo5gonFIN3QkneR/pqpbUn/n32Zy3zlzCo2VfB31g7MjG7kJmg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", + "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", "requires": { - "@aws-sdk/client-sso": "3.622.0", + "@aws-sdk/client-sso": "3.621.0", "@aws-sdk/token-providers": "3.614.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -1782,20 +1782,20 @@ } }, "@aws-sdk/credential-providers": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.622.0.tgz", - "integrity": "sha512-ImfpItaPwnwNBRG04x6iDwRAclvtW2+kSu4amGiMWF+EvnjnRTnyejAA/7rdBuxA4nwM4nb8jed0jnRkZyTu7A==", - "requires": { - "@aws-sdk/client-cognito-identity": "3.622.0", - "@aws-sdk/client-sso": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/credential-provider-cognito-identity": "3.622.0", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.621.0.tgz", + "integrity": "sha512-FQbC7I8ae/72ZekLBa45jWJ+Q3d+YPhc3bW/rCks6RrldM6RgLTGr8pTOPCxHl828ky10RjkBiBmVU818rliyw==", + "requires": { + "@aws-sdk/client-cognito-identity": "3.621.0", + "@aws-sdk/client-sso": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/credential-provider-cognito-identity": "3.621.0", "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -1957,15 +1957,15 @@ } }, "@smithy/core": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.2.tgz", - "integrity": "sha512-in5wwt6chDBcUv1Lw1+QzZxN9fBffi+qOixfb65yK4sDuKG7zAUO9HAFqmVzsZM3N+3tTyvZjtnDXePpvp007Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.1.tgz", + "integrity": "sha512-BC7VMXx/1BCmRPCVzzn4HGWAtsrb7/0758EtwOGFJQrlSwJBEjCcDLNZLFoL/68JexYa2s+KmgL/UfmXdG6v1w==", "requires": { "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "tslib": "^2.6.2" @@ -2048,14 +2048,14 @@ } }, "@smithy/middleware-retry": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.14.tgz", - "integrity": "sha512-7ZaWZJOjUxa5hgmuMspyt8v/zVsh0GXYuF7OvCmdcbVa/xbnKQoYC+uYKunAqRGTkxjOyuOCw9rmFUFOqqC0eQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", "requires": { "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/service-error-classification": "^3.0.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -2174,9 +2174,9 @@ } }, "@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "requires": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -2248,27 +2248,27 @@ } }, "@smithy/util-defaults-mode-browser": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.14.tgz", - "integrity": "sha512-0iwTgKKmAIf+vFLV8fji21Jb2px11ktKVxbX6LIDPAUJyWQqGqBVfwba7xwa1f2FZUoolYQgLvxQEpJycXuQ5w==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", "requires": { "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "@smithy/util-defaults-mode-node": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.14.tgz", - "integrity": "sha512-e9uQarJKfXApkTMMruIdxHprhcXivH1flYCe8JRDTzkkLx8dA3V5J8GZlST9yfDiRWkJpZJlUXGN9Rc9Ade3OQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", "requires": { "@smithy/config-resolver": "^3.0.5", "@smithy/credential-provider-imds": "^3.2.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" } diff --git a/source/lambda/common-modules-layer/package.json b/source/lambda/common-modules-layer/package.json index 21884e1e0..006bb9913 100644 --- a/source/lambda/common-modules-layer/package.json +++ b/source/lambda/common-modules-layer/package.json @@ -1,6 +1,6 @@ { "name": "common-modules-layer", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot Common-modules-layer lambda", "main": "index.js", "scripts": { diff --git a/source/lambda/connect/package-lock.json b/source/lambda/connect/package-lock.json index ba39affde..6cecd525f 100644 --- a/source/lambda/connect/package-lock.json +++ b/source/lambda/connect/package-lock.json @@ -1,12 +1,12 @@ { "name": "connect", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "connect", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "devDependencies": { "jest": "^29.7.0" diff --git a/source/lambda/connect/package.json b/source/lambda/connect/package.json index 001952ac0..e517d0765 100644 --- a/source/lambda/connect/package.json +++ b/source/lambda/connect/package.json @@ -1,6 +1,6 @@ { "name": "connect", - "version": "6.0.3", + "version": "6.1.0", "description": "Lambda function used to support the Connect setup wizard", "repository": { "type": "git", diff --git a/source/lambda/es-proxy-layer/lib/bedrock/AmazonLlm.js b/source/lambda/es-proxy-layer/lib/bedrock/AmazonLlm.js index e7ee76b77..22e587a8c 100644 --- a/source/lambda/es-proxy-layer/lib/bedrock/AmazonLlm.js +++ b/source/lambda/es-proxy-layer/lib/bedrock/AmazonLlm.js @@ -19,7 +19,7 @@ class AmazonLlm extends BedrockModelProviderPrototype { super(); this.body = _.cloneDeep({ textGenerationConfig: { - maxTokenCount: 4096, + maxTokenCount: 256, stopSequences: [], temperature: 0, topP: 1, diff --git a/source/lambda/es-proxy-layer/lib/bedrock/BedrockModelProviderPrototype.js b/source/lambda/es-proxy-layer/lib/bedrock/BedrockModelProviderPrototype.js index e7b622100..11b40283d 100644 --- a/source/lambda/es-proxy-layer/lib/bedrock/BedrockModelProviderPrototype.js +++ b/source/lambda/es-proxy-layer/lib/bedrock/BedrockModelProviderPrototype.js @@ -32,7 +32,12 @@ class BedrockModelProviderPrototype { parseResponseBody(response) { try { - return JSON.parse(Buffer.from(response.body, 'utf-8').toString()); + const parsedBody = JSON.parse(Buffer.from(response.body, 'utf-8').toString()); + const guardRailAction = parsedBody['amazon-bedrock-guardrailAction']; + if (guardRailAction) { + qnabot.log(`Guardrail Action in Bedrock LLM Response: ${guardRailAction}`) + }; + return parsedBody; } catch (e) { qnabot.warn('EXCEPTION:', e.stack); throw new Error(`Exception parsing response body: ${e.message}`); diff --git a/source/lambda/es-proxy-layer/lib/bedrock/bedrockAgents.js b/source/lambda/es-proxy-layer/lib/bedrock/bedrockAgents.js index ddc500714..f6adefd0f 100644 --- a/source/lambda/es-proxy-layer/lib/bedrock/bedrockAgents.js +++ b/source/lambda/es-proxy-layer/lib/bedrock/bedrockAgents.js @@ -12,14 +12,17 @@ * and limitations under the License. * *********************************************************************************************************************/ -const { BedrockAgentRuntimeClient, RetrieveAndGenerateCommand } = require("@aws-sdk/client-bedrock-agent-runtime"); +const { BedrockAgentRuntimeClient, RetrieveAndGenerateCommand } = require('@aws-sdk/client-bedrock-agent-runtime'); const customSdkConfig = require('sdk-config/customSdkConfig'); const { signUrls } = require('../signS3URL'); const llm = require('../llm'); const qnabot = require('qnabot/logging'); const _ = require('lodash'); +const { sanitize, escapeHashMarkdown } = require('../sanitizeOutput'); const region = process.env.AWS_REGION || 'us-east-1'; +const inferenceKeys = ['maxTokens', 'stopSequences', 'temperature', 'topP']; +const client = new BedrockAgentRuntimeClient(customSdkConfig('C41', { region })); function isNoHitsResponse(req, response) { const { text } = response.output; @@ -27,9 +30,12 @@ function isNoHitsResponse(req, response) { return !retrievedReferences && llm.isNoHits(req, text); } -async function generateResponse(client, input, res) { +async function generateResponse(input, res) { + qnabot.log(`Bedrock Knowledge Base Input: ${JSON.stringify(input, null, 2)}`); + const response = await client.send(new RetrieveAndGenerateCommand(input)); - const sessionId = response.sessionId; + + const sessionId = response.sessionId; if (res._userInfo.knowledgeBaseSessionId !== sessionId) { qnabot.debug(`Saving sessionId: ${sessionId}`); res._userInfo.knowledgeBaseSessionId = sessionId; @@ -53,9 +59,9 @@ async function createHit(req, response) { const KNOWLEDGE_BASE_S3_SIGNED_URL_EXPIRE_SECS = _.get(req._settings, 'KNOWLEDGE_BASE_S3_SIGNED_URL_EXPIRE_SECS', 300); const KNOWLEDGE_BASE_S3_SIGNED_URLS = _.get(req._settings, 'KNOWLEDGE_BASE_S3_SIGNED_URLS', true); const KNOWLEDGE_BASE_SHOW_REFERENCES = _.get(req._settings, 'KNOWLEDGE_BASE_SHOW_REFERENCES'); - const KNOWLEDGE_BASE_PREFIX_MESSAGE = _.get(req._settings, 'KNOWLEDGE_BASE_PREFIX_MESSAGE'); + const KNOWLEDGE_BASE_PREFIX_MESSAGE = _.get(req._settings, 'KNOWLEDGE_BASE_PREFIX_MESSAGE'); const helpfulLinksMsg = 'Source Link'; - const generatedText = response.output.text; + const generatedText = sanitize(response.output.text); let plainText = generatedText; let markdown = generatedText; const ssml = ` ${generatedText} `; @@ -76,8 +82,9 @@ async function createHit(req, response) { markdownCitations += '***'; markdownCitations += '\n\n
'; if (reference.content.text) { - markdownCitations += `\n\n ${reference.content.text}`; - plainTextCitations += `\n\n ${reference.content.text}`; + const text = escapeHashMarkdown(reference.content.text); + markdownCitations += `\n\n ${text}`; + plainTextCitations += `\n\n ${text}`; } if (reference.location.type === 'S3') { @@ -119,20 +126,62 @@ async function createHit(req, response) { return hit; } -async function bedrockRetrieveAndGenerate(req, res) { +function processRequest(req) { const { KNOWLEDGE_BASE_ID, KNOWLEDGE_BASE_MODEL_ID, KNOWLEDGE_BASE_KMS, + KNOWLEDGE_BASE_PROMPT_TEMPLATE, + KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS, + KNOWLEDGE_BASE_SEARCH_TYPE, + KNOWLEDGE_BASE_METADATA_FILTERS, + KNOWLEDGE_BASE_MODEL_PARAMS, + BEDROCK_GUARDRAIL_IDENTIFIER, + BEDROCK_GUARDRAIL_VERSION, } = req._settings; - - const client = new BedrockAgentRuntimeClient(customSdkConfig('C41', { region })); + + const modelArn = `arn:aws:bedrock:${region}::foundation-model/${KNOWLEDGE_BASE_MODEL_ID}`; let { question } = req; - question = question.slice(0, 1000) + question = question.slice(0, 1000); // No more than 1000 characters - for bedrock query compatibility + + const sessionConfiguration = KNOWLEDGE_BASE_KMS ? { kmsKeyArn: KNOWLEDGE_BASE_KMS } : undefined; + const promptTemplate = KNOWLEDGE_BASE_PROMPT_TEMPLATE.trim() ? { textPromptTemplate: KNOWLEDGE_BASE_PROMPT_TEMPLATE } : undefined; + const guardrailId = BEDROCK_GUARDRAIL_IDENTIFIER.trim(); + const guardrailVersion = BEDROCK_GUARDRAIL_VERSION.toString(); - let retrieveAndGenerateInput, retrieveAndGenerateSessionInput, response; + const vectorSearchConfigurationProps = { + ...(KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS !== '' && { numberOfResults: KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS }), + ...(KNOWLEDGE_BASE_SEARCH_TYPE !== 'DEFAULT' && { overrideSearchType: KNOWLEDGE_BASE_SEARCH_TYPE }), + ...(KNOWLEDGE_BASE_METADATA_FILTERS !== '{}' && { filter: JSON.parse(KNOWLEDGE_BASE_METADATA_FILTERS) }) + }; + + const modelParams = JSON.parse(KNOWLEDGE_BASE_MODEL_PARAMS); + const textInferenceConfig = _.pick(modelParams, inferenceKeys); + const additionalModelRequestFields = _.omit(modelParams, inferenceKeys); + + const generationConfiguration = {}; + + if (promptTemplate) { + generationConfiguration.promptTemplate = promptTemplate; + } - retrieveAndGenerateInput = { + if (Object.keys(textInferenceConfig).length !== 0) { + generationConfiguration.inferenceConfig = { textInferenceConfig }; + } + + if (Object.keys(additionalModelRequestFields).length !== 0) { + generationConfiguration.additionalModelRequestFields = additionalModelRequestFields; + } + + if (guardrailId && guardrailVersion) { + generationConfiguration.guardrailConfiguration = { guardrailId, guardrailVersion }; + } + + const retrievalConfiguration = { + ...(Object.keys(vectorSearchConfigurationProps).length > 0 && { vectorSearchConfiguration: vectorSearchConfigurationProps }) + } + + const retrieveAndGenerateInput = { input: { text: question, }, @@ -140,46 +189,66 @@ async function bedrockRetrieveAndGenerate(req, res) { type: 'KNOWLEDGE_BASE', knowledgeBaseConfiguration: { knowledgeBaseId: KNOWLEDGE_BASE_ID, - modelArn: `arn:aws:bedrock:${region}::foundation-model/${KNOWLEDGE_BASE_MODEL_ID}`, + modelArn, + ...(Object.keys(retrievalConfiguration).length > 0 && { retrievalConfiguration }), + ...(Object.keys(generationConfiguration).length > 0 && { generationConfiguration }), }, }, + ...(sessionConfiguration && { sessionConfiguration }) }; - if (KNOWLEDGE_BASE_KMS) { - retrieveAndGenerateInput.sessionConfiguration = { - kmsKeyArn: KNOWLEDGE_BASE_KMS, - }; - } - qnabot.log(`Bedrock Knowledge Base Id: ${KNOWLEDGE_BASE_ID} and Model Id: ${KNOWLEDGE_BASE_MODEL_ID}`); + qnabot.log(`Using Bedrock Knowledge Base Id: ${KNOWLEDGE_BASE_ID} and Model Id: ${KNOWLEDGE_BASE_MODEL_ID}`); + return retrieveAndGenerateInput; +} + +async function bedrockRetrieveAndGenerate(req, res) { + let response, retrieveAndGenerateSessionInput; + let retrieveAndGenerateInput = processRequest(req); + let retries = 0; + try { const sessionId = res._userInfo.knowledgeBaseSessionId; qnabot.log(`Bedrock Knowledge Base SessionId: ${sessionId}`); if (sessionId) { retrieveAndGenerateSessionInput = { ...retrieveAndGenerateInput, - sessionId, + sessionId }; - response = await generateResponse(client, retrieveAndGenerateSessionInput, res); + response = await generateResponse(retrieveAndGenerateSessionInput, res); } else { - response = await generateResponse(client, retrieveAndGenerateInput, res); - }; + response = await generateResponse(retrieveAndGenerateInput, res); + } } catch (e) { - if (e.name === 'ValidationException' || e.name === 'ConflictException') { - response = await generateResponse(client, retrieveAndGenerateInput, res); + if (retries < 3 && (e.name === 'ValidationException' || e.name === 'ConflictException')) { + retries += 1; + qnabot.log(`Retrying to due ${e.name}...tries left ${3 - retries}`) + response = await generateResponse(retrieveAndGenerateInput, res); } else { - qnabot.log(`Bedrock Knowledge Base ${e.name}: ${e.message.substring(0, 500)}`) + qnabot.log(`Bedrock Knowledge Base ${e.name}: ${e.message.substring(0, 500)}`); throw e; - } - } - qnabot.debug(`Response from bedrock knowledge base: ${JSON.stringify(response)}`); + }; + }; + + qnabot.log(`Bedrock Knowledge Base Response: ${JSON.stringify(response)}`); + + const guardrailAction = response.guardrailAction; + if (guardrailAction) { + qnabot.log(`Guardrail Action in Bedrock Knowledge Base Response: ${guardrailAction}`); + }; if (isNoHitsResponse(req, response)) { qnabot.log('No hits from knowledge base.'); return [res, undefined]; - } + }; const hit = await createHit(req, response); + + // we got a hit, let's update the session parameters + _.set(res, 'session.qnabot_gotanswer', true); + res.got_hits = 1; + return [res, hit]; } -exports.bedrockRetrieveAndGenerate = bedrockRetrieveAndGenerate; + +exports.bedrockRetrieveAndGenerate = bedrockRetrieveAndGenerate; \ No newline at end of file diff --git a/source/lambda/es-proxy-layer/lib/bedrock/bedrockClient.js b/source/lambda/es-proxy-layer/lib/bedrock/bedrockClient.js index b9bb64567..233d7b227 100644 --- a/source/lambda/es-proxy-layer/lib/bedrock/bedrockClient.js +++ b/source/lambda/es-proxy-layer/lib/bedrock/bedrockClient.js @@ -31,13 +31,15 @@ const capabilityMapping = { 'cohere.embed-english-v3': 'C038', 'cohere.embed-multilingual-v3': 'C039', 'meta.llama3-8b-instruct-v1': 'C041', + 'amazon.titan-text-premier-v1': 'C042', + 'amazon.titan-embed-text-v2': 'C043', }; function isEmbedding(modelId) { return modelId.includes('embed'); }; -async function bedrockClient(modelId, body) { +async function bedrockClient(modelId, body, guardrails) { const invokeModelParams = { body, contentType: 'application/json', @@ -47,11 +49,16 @@ async function bedrockClient(modelId, body) { let llm_result; const configCode = capabilityMapping[modelId] || isEmbedding(modelId) ? 'C040' : 'C036'; const client = new BedrockRuntimeClient(customSdkConfig(configCode, { region })); + + if (!isEmbedding(modelId) && guardrails.guardrailIdentifier !== '' && guardrails.guardrailVersion !== '') { + invokeModelParams.guardrailIdentifier = guardrails.guardrailIdentifier; + invokeModelParams.guardrailVersion = guardrails.guardrailVersion; + }; + qnabot.log('Bedrock Invoke Model Params: ', invokeModelParams); try { const command = new InvokeModelCommand(invokeModelParams); llm_result = await client.send(command); - qnabot.debug('Bedrock Invoke Model Response: ', llm_result); return llm_result; } catch (e) { let message = `Bedrock ${modelId} returned ${e.name}: ${e.message.substring(0, 500)}`; diff --git a/source/lambda/es-proxy-layer/lib/bedrock/bedrockModels.js b/source/lambda/es-proxy-layer/lib/bedrock/bedrockModels.js index bf23928cf..f8bc8dae2 100644 --- a/source/lambda/es-proxy-layer/lib/bedrock/bedrockModels.js +++ b/source/lambda/es-proxy-layer/lib/bedrock/bedrockModels.js @@ -48,14 +48,14 @@ function getProviderClass(modelId) { } } -async function invokeBedrockModel(modelId, parameters, prompt) { +async function invokeBedrockModel(modelId, parameters, prompt, guardrails) { const modelProvider = getProviderClass(modelId); modelProvider.setParameters(parameters); modelProvider.setPrompt(prompt); const body = modelProvider.getParameters(); - qnabot.log('Bedrock Invoke model body:', body); + qnabot.debug(`Bedrock Invoke model body: ${body}`); - const response = await bedrockClient(modelId, body); + const response = await bedrockClient(modelId, body, guardrails); const generatedText = modelProvider.getResponseBody(response); return generatedText; } diff --git a/source/lambda/es-proxy-layer/lib/embeddings.js b/source/lambda/es-proxy-layer/lib/embeddings.js index bf746b07a..770eabd67 100644 --- a/source/lambda/es-proxy-layer/lib/embeddings.js +++ b/source/lambda/es-proxy-layer/lib/embeddings.js @@ -70,7 +70,9 @@ async function getEmbeddingsBedrock(type_q_or_a, input, settings) { inputText = truncateByNumTokens(inputText, settings.EMBEDDINGS_MAX_TOKEN_LIMIT); } - return await invokeBedrockModel(modelId, {}, inputText); + const embeddings = await invokeBedrockModel(modelId, {}, inputText, {}); + qnabot.debug(`Bedrock Embeddings Response: ${embeddings}`); + return embeddings; }; module.exports = async function (type_q_or_a, input, settings) { diff --git a/source/lambda/es-proxy-layer/lib/fulfillment-event/getHit.js b/source/lambda/es-proxy-layer/lib/fulfillment-event/getHit.js index e65f670d6..8b6a5ea05 100644 --- a/source/lambda/es-proxy-layer/lib/fulfillment-event/getHit.js +++ b/source/lambda/es-proxy-layer/lib/fulfillment-event/getHit.js @@ -253,8 +253,8 @@ async function useFallbackMethod(req, res, query_params) { try { [res, hit] = await bedrockRetrieveAndGenerate(req, res); } catch (e) { - qnabot.log('BEDROCK AGENT EXCEPTION:', e); - const errMsg = `Bedrock Agent exception: ${e.message.substring(0, 500)}`; + qnabot.log(`BEDROCK KNOWLEDGEBASE EXCEPTION: ${e.name} ${e.message.substring(0, 500)}`); + const errMsg = `Bedrock Knowledgebase exception: ${e.name} ${e.message.substring(0, 500)}`; if (!errors.includes(errMsg)) { errors.push(errMsg); }; diff --git a/source/lambda/es-proxy-layer/lib/llm.js b/source/lambda/es-proxy-layer/lib/llm.js index 2d710a0a5..52ceae1e0 100644 --- a/source/lambda/es-proxy-layer/lib/llm.js +++ b/source/lambda/es-proxy-layer/lib/llm.js @@ -147,10 +147,18 @@ async function invoke_lambda(prompt, model_params, settings) { async function invoke_bedrock(prompt, model_params, settings) { const modelId = settings.LLM_MODEL_ID; - const response = await invokeBedrockModel(modelId, model_params, prompt); - qnabot.debug(`Bedrock LLM response: ${response}`); + const guardrails = {}; + const guardrailIdentifier = settings.BEDROCK_GUARDRAIL_IDENTIFIER.trim(); + const guardrailVersion = settings.BEDROCK_GUARDRAIL_VERSION.toString(); + + if (guardrailIdentifier !== '' && guardrailVersion !== '') { + guardrails.guardrailIdentifier = guardrailIdentifier; + guardrails.guardrailVersion = guardrailVersion; + }; + const response = await invokeBedrockModel(modelId, model_params, prompt, guardrails); + qnabot.log(`Bedrock Invoke LLM Response: ${response}`); return sanitize(response); -} +}; function clean_standalone_query(query) { let clean_query = query; diff --git a/source/lambda/es-proxy-layer/lib/sanitizeOutput.js b/source/lambda/es-proxy-layer/lib/sanitizeOutput.js index 408862498..c881b5f73 100644 --- a/source/lambda/es-proxy-layer/lib/sanitizeOutput.js +++ b/source/lambda/es-proxy-layer/lib/sanitizeOutput.js @@ -22,4 +22,17 @@ function sanitize(data) { const sanitizedData = sanitizeHtml(data, sanitizeParams); return sanitizedData; } + +// Escapes hash if the input text starts with one or more hashes followed by a space. +function escapeHashMarkdown(text) { + + const match = /^(#+)/; // Matches one ore more hashes at the start of the text + + if(match.test(text)){ // If it matches the escape first hash symbol + text = text.replace(/^#/, '\\#') + }; + return text; +} + +exports.escapeHashMarkdown = escapeHashMarkdown; exports.sanitize = sanitize; diff --git a/source/lambda/es-proxy-layer/package-lock.json b/source/lambda/es-proxy-layer/package-lock.json index 4571d861b..7b81f54a4 100644 --- a/source/lambda/es-proxy-layer/package-lock.json +++ b/source/lambda/es-proxy-layer/package-lock.json @@ -1,22 +1,24 @@ { "name": "proxy-es", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "proxy-es", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/client-bedrock-agent-runtime": "^3.616.0", + "@aws-sdk/client-bedrock-runtime": "^3.616.0", "@aws-sdk/client-firehose": "^3.511.0", "@aws-sdk/client-sagemaker-runtime": "^3.511.0", "@aws-sdk/s3-request-presigner": "^3.511.0", "@dqbd/tiktoken": "^1.0.7", "aws4": "^1.6.0", - "axios": "^1.6.8", + "axios": "^1.7.4", "bodybuilder": "^2.5.1", - "handlebars": "^4.7.2", + "handlebars": "^4.7.8", "langchain": "^0.0.209", "linkifyjs": "^3.0.0-beta.3", "sanitize-html": "^2.13.0", @@ -200,487 +202,2335 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/@aws-sdk/client-bedrock-runtime": { - "version": "3.474.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.474.0.tgz", - "integrity": "sha512-1Ih/iG9KnDugX5tPPDVC8pzBzisEImWx5InaTS+B8uBF7NuFjxX2p1MKYJCEVpj+JYsRcND/PFIiQWeJ8UZeig==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-agent-runtime/-/client-bedrock-agent-runtime-3.616.0.tgz", + "integrity": "sha512-LmKgpTNNqJ0ClfDL1ZmssxiADS3hoznc4Tidh+M7SUJKmsd/iyPlyhu0Lwluw0k4wnPGqoDFwDWzjAzdxeCidw==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.616.0", + "@aws-sdk/client-sts": "3.616.0", + "@aws-sdk/core": "3.616.0", + "@aws-sdk/credential-provider-node": "3.616.0", + "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.616.0", + "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.2.7", + "@smithy/eventstream-serde-browser": "^3.0.4", + "@smithy/eventstream-serde-config-resolver": "^3.0.3", + "@smithy/eventstream-serde-node": "^3.0.4", + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.4", + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.8", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.10", + "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.474.0", - "@aws-sdk/core": "3.474.0", - "@aws-sdk/credential-provider-node": "3.474.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-signing": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.470.0", - "@aws-sdk/region-config-resolver": "3.470.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.470.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.470.0", - "@smithy/config-resolver": "^2.0.21", - "@smithy/eventstream-serde-browser": "^2.0.15", - "@smithy/eventstream-serde-config-resolver": "^2.0.15", - "@smithy/eventstream-serde-node": "^2.0.15", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.3", - "@smithy/middleware-retry": "^2.0.24", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.8", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/protocol-http": "^3.0.11", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.29", - "@smithy/util-endpoints": "^1.0.7", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-stream": "^2.0.23", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/client-sso": { - "version": "3.474.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.474.0.tgz", - "integrity": "sha512-6toUmQUIHkDM/P2/nyLEO/mcWOIPByTlegqX9VCHhYh9Fs5MDT2nit7I6fZzBjZjB5oVTwKjbzgxae9cE3bhqw==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.474.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.470.0", - "@aws-sdk/region-config-resolver": "3.470.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.470.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.470.0", - "@smithy/config-resolver": "^2.0.21", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.3", - "@smithy/middleware-retry": "^2.0.24", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.8", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/protocol-http": "^3.0.11", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.29", - "@smithy/util-endpoints": "^1.0.7", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/client-sts": { - "version": "3.474.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.474.0.tgz", - "integrity": "sha512-qPPMbrDVAUJgYiFWVewFG7dg0VyMfuGNNK4IC1nZr0eXejUTbdm8cio6IZ8OkWtK+A+L+wx1vX5686WYVgQ0dQ==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.474.0", - "@aws-sdk/credential-provider-node": "3.474.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.470.0", - "@aws-sdk/region-config-resolver": "3.470.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.470.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.470.0", - "@smithy/config-resolver": "^2.0.21", - "@smithy/core": "^1.1.0", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.3", - "@smithy/middleware-retry": "^2.0.24", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.8", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/protocol-http": "^3.0.11", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.29", - "@smithy/util-endpoints": "^1.0.7", - "@smithy/util-middleware": "^2.0.8", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-utf8": "^2.0.2", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-env": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.468.0.tgz", - "integrity": "sha512-k/1WHd3KZn0EQYjadooj53FC0z24/e4dUZhbSKTULgmxyO62pwh9v3Brvw4WRa/8o2wTffU/jo54tf4vGuP/ZA==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.474.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.474.0.tgz", - "integrity": "sha512-3Y2fHI4ZCNjdOO47Vh/xBgLXOrKm3KwBkYkBKKT2g02FUGNT8NLjJg8WBo3D4RQX2h34qx4mtW5nTY6YcGP80Q==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", "dependencies": { - "@aws-sdk/credential-provider-env": "3.468.0", - "@aws-sdk/credential-provider-process": "3.468.0", - "@aws-sdk/credential-provider-sso": "3.474.0", - "@aws-sdk/credential-provider-web-identity": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.474.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.474.0.tgz", - "integrity": "sha512-3OVVVGnb8Ru5hWeeHkg76YZT5mrufweIiWr6ge5zn7FYxc7WkyqIJ0XehqUqG5VQfaYhqh7uq/zmk8OE2B04lQ==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", "dependencies": { - "@aws-sdk/credential-provider-env": "3.468.0", - "@aws-sdk/credential-provider-ini": "3.474.0", - "@aws-sdk/credential-provider-process": "3.468.0", - "@aws-sdk/credential-provider-sso": "3.474.0", - "@aws-sdk/credential-provider-web-identity": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-process": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.468.0.tgz", - "integrity": "sha512-OYSn1A/UsyPJ7Z8Q2cNhTf55O36shPmSsvOfND04nSfu1nPaR+VUvvsP7v+brhGpwC/GAKTIdGAo4blH31BS6A==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.474.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.474.0.tgz", - "integrity": "sha512-ik4rzhQtcRLSHB/MLQfi/dSpILxPd3zITb79DIEnqT3gpZRNjoARkZ3Hi68pujkU2530NYf8NcFwLCWoV1hS7Q==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", "dependencies": { - "@aws-sdk/client-sso": "3.474.0", - "@aws-sdk/token-providers": "3.470.0", - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.468.0.tgz", - "integrity": "sha512-rexymPmXjtkwCPfhnUq3EjO1rSkf39R4Jz9CqiM7OsqK2qlT5Y/V3gnMKn0ZMXsYaQOMfM3cT5xly5R+OKDHlw==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/client-sso": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.616.0.tgz", + "integrity": "sha512-hwW0u1f8U4dSloAe61/eupUiGd5Q13B72BuzGxvRk0cIpYX/2m0KBG8DDl7jW1b2QQ+CflTLpG2XUf2+vRJxGA==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.616.0", + "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.616.0", + "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.2.7", + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.4", + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.8", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.10", + "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.616.0.tgz", + "integrity": "sha512-YY1hpYS/G1uRGjQf88dL8VLHkP/IjGxKeXdhy+JnzMdCkAWl3V9j0fEALw40NZe0x79gr6R2KUOUH/IKYQfUmg==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.616.0", + "@aws-sdk/credential-provider-node": "3.616.0", + "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.616.0", + "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.2.7", + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.4", + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.8", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.10", + "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.616.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/client-sts": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.616.0.tgz", + "integrity": "sha512-FP7i7hS5FpReqnysQP1ukQF1OUWy8lkomaOnbu15H415YUrfCp947SIx6+BItjmx+esKxPkEjh/fbCVzw2D6hQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.616.0", + "@aws-sdk/core": "3.616.0", + "@aws-sdk/credential-provider-node": "3.616.0", + "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.616.0", + "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.2.7", + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.4", + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.8", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.10", + "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.609.0.tgz", + "integrity": "sha512-v69ZCWcec2iuV9vLVJMa6fAb5xwkzN4jYIT8yjo2c4Ia/j976Q+TPf35Pnz5My48Xr94EFcaBazrWedF+kwfuQ==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/middleware-host-header": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.468.0.tgz", - "integrity": "sha512-gwQ+/QhX+lhof304r6zbZ/V5l5cjhGRxLL3CjH1uJPMcOAbw9wUlMdl+ibr8UwBZ5elfKFGiB1cdW/0uMchw0w==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.616.0.tgz", + "integrity": "sha512-1rgCkr7XvEMBl7qWCo5BKu3yAxJs71dRaZ55Xnjte/0ZHH6Oc93ZrHzyYy6UH6t0nZrH+FAuw7Yko2YtDDwDeg==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.8", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/middleware-logger": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.468.0.tgz", - "integrity": "sha512-X5XHKV7DHRXI3f29SAhJPe/OxWRFgDWDMMCALfzhmJfCi6Jfh0M14cJKoC+nl+dk9lB+36+jKjhjETZaL2bPlA==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.616.0.tgz", + "integrity": "sha512-5gQdMr9cca3xV7FF2SxpxWGH2t6+t4o+XBGiwsHm8muEjf4nUmw7Ij863x25Tjt2viPYV0UStczSb5Sihp7bkA==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.609.0", + "@aws-sdk/credential-provider-http": "3.616.0", + "@aws-sdk/credential-provider-process": "3.614.0", + "@aws-sdk/credential-provider-sso": "3.616.0", + "@aws-sdk/credential-provider-web-identity": "3.609.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.616.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.616.0.tgz", + "integrity": "sha512-Se+u6DAxjDPjKE3vX1X2uxjkWgGq69BTo0uTB0vDUiWwBVgh16s9BsBhSAlKEH1CCbbJHvOg4YdTrzjwzqyClg==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.609.0", + "@aws-sdk/credential-provider-http": "3.616.0", + "@aws-sdk/credential-provider-ini": "3.616.0", + "@aws-sdk/credential-provider-process": "3.614.0", + "@aws-sdk/credential-provider-sso": "3.616.0", + "@aws-sdk/credential-provider-web-identity": "3.609.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.614.0.tgz", + "integrity": "sha512-Q0SI0sTRwi8iNODLs5+bbv8vgz8Qy2QdxbCHnPk/6Cx6LMf7i3dqmWquFbspqFRd8QiqxStrblwxrUYZi09tkA==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.468.0.tgz", - "integrity": "sha512-vch9IQib2Ng9ucSyRW2eKNQXHUPb5jUPCLA5otTW/8nGjcOU37LxQG4WrxO7uaJ9Oe8hjHO+hViE3P0KISUhtA==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.616.0.tgz", + "integrity": "sha512-3rsWs9GBi8Z8Gps5ROwqguxtw+J6OIg1vawZMLRNMqqZoBvbOToe9wEnpid8ylU+27+oG8uibJNlNuRyXApUjw==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@aws-sdk/client-sso": "3.616.0", + "@aws-sdk/token-providers": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/middleware-signing": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.468.0.tgz", - "integrity": "sha512-s+7fSB1gdnnTj5O0aCCarX3z5Vppop8kazbNSZADdkfHIDWCN80IH4ZNjY3OWqaAz0HmR4LNNrovdR304ojb4Q==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.609.0.tgz", + "integrity": "sha512-U+PG8NhlYYF45zbr1km3ROtBMYqyyj/oK8NRp++UHHeuavgrP+4wJ4wQnlEaKvJBjevfo3+dlIBcaeQ7NYejWg==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.7.0", - "@smithy/util-middleware": "^2.0.8", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.609.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.470.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.470.0.tgz", - "integrity": "sha512-s0YRGgf4fT5KwwTefpoNUQfB5JghzXyvmPfY1QuFEMeVQNxv0OPuydzo3rY2oXPkZjkulKDtpm5jzIHwut75hA==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.616.0.tgz", + "integrity": "sha512-mhNfHuGhCDZwYCABebaOvTgOM44UCZZRq2cBpgPZLVKP0ydAv5aFHXv01goexxXHqgHoEGx0uXWxlw0s2EpFDg==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.470.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/region-config-resolver": { - "version": "3.470.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.470.0.tgz", - "integrity": "sha512-C1o1J06iIw8cyAAOvHqT4Bbqf+PgQ/RDlSyjt2gFfP2OovDpc2o2S90dE8f8iZdSGpg70N5MikT1DBhW9NbhtQ==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/middleware-logger": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz", + "integrity": "sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ==", "dependencies": { - "@smithy/node-config-provider": "^2.1.8", - "@smithy/types": "^2.7.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.8", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/token-providers": { - "version": "3.470.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.470.0.tgz", - "integrity": "sha512-rzxnJxEUJiV69Cxsf0AHXTqJqTACITwcSH/PL4lWP4uvtzdrzSi3KA3u2aWHWpOcdE6+JFvdICscsbBSo3/TOg==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.616.0.tgz", + "integrity": "sha512-LQKAcrZRrR9EGez4fdCIVjdn0Ot2HMN12ChnoMGEU6oIxnQ2aSC7iASFFCV39IYfeMh7iSCPj7Wopqw8rAouzg==", "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.470.0", - "@aws-sdk/region-config-resolver": "3.470.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.470.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.470.0", - "@smithy/config-resolver": "^2.0.21", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.3", - "@smithy/middleware-retry": "^2.0.24", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.8", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.29", - "@smithy/util-endpoints": "^1.0.7", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/types": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.468.0.tgz", - "integrity": "sha512-rx/9uHI4inRbp2tw3Y4Ih4PNZkVj32h7WneSg3MVgVjAoVD5Zti9KhS5hkvsBxfgmQmg0AQbE+b1sy5WGAgntA==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.616.0.tgz", + "integrity": "sha512-iMcAb4E+Z3vuEcrDsG6T2OBNiqWAquwahP9qepHqfmnmJqHr1mSHtXDYTGBNid31+621sUQmneUQ+fagpGAe4w==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@smithy/protocol-http": "^4.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz", + "integrity": "sha512-vDCeMXvic/LU0KFIUjpC3RiSTIkkvESsEfbVHiHH0YINfl8HnEqR5rj+L8+phsCeVg2+LmYwYxd5NRz4PHxt5g==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/token-providers": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz", + "integrity": "sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sso-oidc": "^3.614.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/types": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.609.0.tgz", + "integrity": "sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/util-endpoints": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.614.0.tgz", + "integrity": "sha512-wK2cdrXHH4oz4IomV/yrGkftU9A+ITB6nFL+rxxyO78is2ifHJpFdV4aqk4LSkXYPi6CXWNru/Dqc7yiKXgJPw==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "@smithy/util-endpoints": "^2.0.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz", + "integrity": "sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz", + "integrity": "sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.1.tgz", + "integrity": "sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/config-resolver": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.5.tgz", + "integrity": "sha512-SkW5LxfkSI1bUC74OtfBbdz+grQXYiPYolyu8VfpLIjEoN/sHVBlLeGXMQ1vX4ejkgfv6sxVbQJ32yF2cl1veA==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/core": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.2.8.tgz", + "integrity": "sha512-1Y0XX0Ucyg0LWTfTVLWpmvSRtFRniykUl3dQ0os1sTd03mKDudR6mVyX+2ak1phwPXx2aEWMAAdW52JNi0mc3A==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-retry": "^3.0.11", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.9", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/credential-provider-imds": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.1.4.tgz", + "integrity": "sha512-NKyH01m97Xa5xf3pB2QOF3lnuE8RIK0hTVNU5zvZAwZU8uspYO4DHQVlK+Y5gwSrujTfHvbfd1D9UFJAc0iYKQ==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/eventstream-codec": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz", + "integrity": "sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/eventstream-serde-browser": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.5.tgz", + "integrity": "sha512-dEyiUYL/ekDfk+2Ra4GxV+xNnFoCmk1nuIXg+fMChFTrM2uI/1r9AdiTYzPqgb72yIv/NtAj6C3dG//1wwgakQ==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.3.tgz", + "integrity": "sha512-NVTYjOuYpGfrN/VbRQgn31x73KDLfCXCsFdad8DiIc3IcdxL+dYA9zEQPyOP7Fy2QL8CPy2WE4WCUD+ZsLNfaQ==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/eventstream-serde-node": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.4.tgz", + "integrity": "sha512-mjlG0OzGAYuUpdUpflfb9zyLrBGgmQmrobNT8b42ZTsGv/J03+t24uhhtVEKG/b2jFtPIHF74Bq+VUtbzEKOKg==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/eventstream-serde-universal": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.4.tgz", + "integrity": "sha512-Od9dv8zh3PgOD7Vj4T3HSuox16n0VG8jJIM2gvKASL6aCtcS8CfHZDWe1Ik3ZXW6xBouU+45Q5wgoliWDZiJ0A==", + "dependencies": { + "@smithy/eventstream-codec": "^3.1.2", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/fetch-http-handler": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.2.tgz", + "integrity": "sha512-3LaWlBZObyGrOOd7e5MlacnAKEwFBmAeiW/TOj2eR9475Vnq30uS2510+tnKbxrGjROfNdOhQqGo5j3sqLT6bA==", + "dependencies": { + "@smithy/protocol-http": "^4.0.4", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/hash-node": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.3.tgz", + "integrity": "sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw==", + "dependencies": { + "@smithy/types": "^3.3.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/invalid-dependency": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz", + "integrity": "sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/middleware-content-length": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.4.tgz", + "integrity": "sha512-wySGje/KfhsnF8YSh9hP16pZcl3C+X6zRsvSfItQGvCyte92LliilU3SD0nR7kTlxnAJwxY8vE/k4Eoezj847Q==", + "dependencies": { + "@smithy/protocol-http": "^4.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/middleware-endpoint": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.0.5.tgz", + "integrity": "sha512-V4acqqrh5tDxUEGVTOgf2lYMZqPQsoGntCrjrJZEeBzEzDry2d2vcI1QCXhGltXPPY+BMc6eksZMguA9fIY8vA==", + "dependencies": { + "@smithy/middleware-serde": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/middleware-retry": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.11.tgz", + "integrity": "sha512-/TIRWmhwMpv99JCGuMhJPnH7ggk/Lah7s/uNDyr7faF02BxNsyD/fz9Tw7pgCf9tYOKgjimm2Qml1Aq1pbkt6g==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.0.4", + "@smithy/service-error-classification": "^3.0.3", + "@smithy/smithy-client": "^3.1.9", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/middleware-serde": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", + "integrity": "sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/middleware-stack": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz", + "integrity": "sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/node-config-provider": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", + "dependencies": { + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/node-http-handler": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.3.tgz", + "integrity": "sha512-UiKZm8KHb/JeOPzHZtRUfyaRDO1KPKPpsd7iplhiwVGOeVdkiVJ5bVe7+NhWREMOKomrDIDdSZyglvMothLg0Q==", + "dependencies": { + "@smithy/abort-controller": "^3.1.1", + "@smithy/protocol-http": "^4.0.4", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/property-provider": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/protocol-http": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.0.4.tgz", + "integrity": "sha512-fAA2O4EFyNRyYdFLVIv5xMMeRb+3fRKc/Rt2flh5k831vLvUmNFXcydeg7V3UeEhGURJI4c1asmGJBjvmF6j8Q==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/querystring-builder": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", + "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", + "dependencies": { + "@smithy/types": "^3.3.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/querystring-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz", + "integrity": "sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/service-error-classification": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz", + "integrity": "sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ==", + "dependencies": { + "@smithy/types": "^3.3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/smithy-client": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.9.tgz", + "integrity": "sha512-My2RaInZ4gSwJUPMaiLR/Nk82+c4LlvqpXA+n7lonGYgCZq23Tg+/xFhgmiejJ6XPElYJysTPyV90vKyp17+1g==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/url-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.3.tgz", + "integrity": "sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==", + "dependencies": { + "@smithy/querystring-parser": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-defaults-mode-browser": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.11.tgz", + "integrity": "sha512-O3s9DGb3bmRvEKmT8RwvSWK4A9r6svfd+MnJB+UMi9ZcCkAnoRtliulOnGF0qCMkKF9mwk2tkopBBstalPY/vg==", + "dependencies": { + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.1.9", + "@smithy/types": "^3.3.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-defaults-mode-node": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.11.tgz", + "integrity": "sha512-qd4a9qtyOa/WY14aHHOkMafhh9z8D2QTwlcBoXMTPnEwtcY+xpe1JyFm9vya7VsB8hHsfn3XodEtwqREiu4ygQ==", + "dependencies": { + "@smithy/config-resolver": "^3.0.5", + "@smithy/credential-provider-imds": "^3.1.4", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.1.9", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-endpoints": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.0.5.tgz", + "integrity": "sha512-ReQP0BWihIE68OAblC/WQmDD40Gx+QY1Ez8mTdFMXpmjfxSyz2fVQu3A4zXRfQU9sZXtewk3GmhfOHswvX+eNg==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-middleware": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-retry": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.3.tgz", + "integrity": "sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w==", + "dependencies": { + "@smithy/service-error-classification": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.1.tgz", + "integrity": "sha512-EhRnVvl3AhoHAT2rGQ5o+oSDRM/BUSMPLZZdRJZLcNVUsFAjOs4vHaPdNQivTSzRcFxf5DA4gtO46WWU2zimaw==", + "dependencies": { + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.616.0.tgz", + "integrity": "sha512-3uvKafBwlrJp2/Me/BMdvYf3J127vC69aDJloElX9eClhSBDwIQ6C7tuXmhqb662mKNy5iqXcmYhmv9FowevJw==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.616.0", + "@aws-sdk/client-sts": "3.616.0", + "@aws-sdk/core": "3.616.0", + "@aws-sdk/credential-provider-node": "3.616.0", + "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.616.0", + "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.2.7", + "@smithy/eventstream-serde-browser": "^3.0.4", + "@smithy/eventstream-serde-config-resolver": "^3.0.3", + "@smithy/eventstream-serde-node": "^3.0.4", + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.4", + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.8", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.10", + "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-stream": "^3.1.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/client-sso": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.616.0.tgz", + "integrity": "sha512-hwW0u1f8U4dSloAe61/eupUiGd5Q13B72BuzGxvRk0cIpYX/2m0KBG8DDl7jW1b2QQ+CflTLpG2XUf2+vRJxGA==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.616.0", + "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.616.0", + "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.2.7", + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.4", + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.8", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.10", + "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.616.0.tgz", + "integrity": "sha512-YY1hpYS/G1uRGjQf88dL8VLHkP/IjGxKeXdhy+JnzMdCkAWl3V9j0fEALw40NZe0x79gr6R2KUOUH/IKYQfUmg==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.616.0", + "@aws-sdk/credential-provider-node": "3.616.0", + "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.616.0", + "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.2.7", + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.4", + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.8", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.10", + "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.616.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/client-sts": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.616.0.tgz", + "integrity": "sha512-FP7i7hS5FpReqnysQP1ukQF1OUWy8lkomaOnbu15H415YUrfCp947SIx6+BItjmx+esKxPkEjh/fbCVzw2D6hQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.616.0", + "@aws-sdk/core": "3.616.0", + "@aws-sdk/credential-provider-node": "3.616.0", + "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.616.0", + "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.2.7", + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.4", + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.8", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.10", + "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.609.0.tgz", + "integrity": "sha512-v69ZCWcec2iuV9vLVJMa6fAb5xwkzN4jYIT8yjo2c4Ia/j976Q+TPf35Pnz5My48Xr94EFcaBazrWedF+kwfuQ==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.616.0.tgz", + "integrity": "sha512-1rgCkr7XvEMBl7qWCo5BKu3yAxJs71dRaZ55Xnjte/0ZHH6Oc93ZrHzyYy6UH6t0nZrH+FAuw7Yko2YtDDwDeg==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.8", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.616.0.tgz", + "integrity": "sha512-5gQdMr9cca3xV7FF2SxpxWGH2t6+t4o+XBGiwsHm8muEjf4nUmw7Ij863x25Tjt2viPYV0UStczSb5Sihp7bkA==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.609.0", + "@aws-sdk/credential-provider-http": "3.616.0", + "@aws-sdk/credential-provider-process": "3.614.0", + "@aws-sdk/credential-provider-sso": "3.616.0", + "@aws-sdk/credential-provider-web-identity": "3.609.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.616.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.616.0.tgz", + "integrity": "sha512-Se+u6DAxjDPjKE3vX1X2uxjkWgGq69BTo0uTB0vDUiWwBVgh16s9BsBhSAlKEH1CCbbJHvOg4YdTrzjwzqyClg==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.609.0", + "@aws-sdk/credential-provider-http": "3.616.0", + "@aws-sdk/credential-provider-ini": "3.616.0", + "@aws-sdk/credential-provider-process": "3.614.0", + "@aws-sdk/credential-provider-sso": "3.616.0", + "@aws-sdk/credential-provider-web-identity": "3.609.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.614.0.tgz", + "integrity": "sha512-Q0SI0sTRwi8iNODLs5+bbv8vgz8Qy2QdxbCHnPk/6Cx6LMf7i3dqmWquFbspqFRd8QiqxStrblwxrUYZi09tkA==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.616.0.tgz", + "integrity": "sha512-3rsWs9GBi8Z8Gps5ROwqguxtw+J6OIg1vawZMLRNMqqZoBvbOToe9wEnpid8ylU+27+oG8uibJNlNuRyXApUjw==", + "dependencies": { + "@aws-sdk/client-sso": "3.616.0", + "@aws-sdk/token-providers": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.609.0.tgz", + "integrity": "sha512-U+PG8NhlYYF45zbr1km3ROtBMYqyyj/oK8NRp++UHHeuavgrP+4wJ4wQnlEaKvJBjevfo3+dlIBcaeQ7NYejWg==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.609.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.616.0.tgz", + "integrity": "sha512-mhNfHuGhCDZwYCABebaOvTgOM44UCZZRq2cBpgPZLVKP0ydAv5aFHXv01goexxXHqgHoEGx0uXWxlw0s2EpFDg==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/middleware-logger": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz", + "integrity": "sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.616.0.tgz", + "integrity": "sha512-LQKAcrZRrR9EGez4fdCIVjdn0Ot2HMN12ChnoMGEU6oIxnQ2aSC7iASFFCV39IYfeMh7iSCPj7Wopqw8rAouzg==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.616.0.tgz", + "integrity": "sha512-iMcAb4E+Z3vuEcrDsG6T2OBNiqWAquwahP9qepHqfmnmJqHr1mSHtXDYTGBNid31+621sUQmneUQ+fagpGAe4w==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@smithy/protocol-http": "^4.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz", + "integrity": "sha512-vDCeMXvic/LU0KFIUjpC3RiSTIkkvESsEfbVHiHH0YINfl8HnEqR5rj+L8+phsCeVg2+LmYwYxd5NRz4PHxt5g==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/token-providers": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz", + "integrity": "sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sso-oidc": "^3.614.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/types": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.609.0.tgz", + "integrity": "sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/util-endpoints": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.614.0.tgz", + "integrity": "sha512-wK2cdrXHH4oz4IomV/yrGkftU9A+ITB6nFL+rxxyO78is2ifHJpFdV4aqk4LSkXYPi6CXWNru/Dqc7yiKXgJPw==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "@smithy/util-endpoints": "^2.0.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz", + "integrity": "sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz", + "integrity": "sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.1.tgz", + "integrity": "sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/config-resolver": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.5.tgz", + "integrity": "sha512-SkW5LxfkSI1bUC74OtfBbdz+grQXYiPYolyu8VfpLIjEoN/sHVBlLeGXMQ1vX4ejkgfv6sxVbQJ32yF2cl1veA==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/core": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.2.8.tgz", + "integrity": "sha512-1Y0XX0Ucyg0LWTfTVLWpmvSRtFRniykUl3dQ0os1sTd03mKDudR6mVyX+2ak1phwPXx2aEWMAAdW52JNi0mc3A==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-retry": "^3.0.11", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.9", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/credential-provider-imds": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.1.4.tgz", + "integrity": "sha512-NKyH01m97Xa5xf3pB2QOF3lnuE8RIK0hTVNU5zvZAwZU8uspYO4DHQVlK+Y5gwSrujTfHvbfd1D9UFJAc0iYKQ==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/eventstream-codec": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz", + "integrity": "sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/eventstream-serde-browser": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.5.tgz", + "integrity": "sha512-dEyiUYL/ekDfk+2Ra4GxV+xNnFoCmk1nuIXg+fMChFTrM2uI/1r9AdiTYzPqgb72yIv/NtAj6C3dG//1wwgakQ==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.3.tgz", + "integrity": "sha512-NVTYjOuYpGfrN/VbRQgn31x73KDLfCXCsFdad8DiIc3IcdxL+dYA9zEQPyOP7Fy2QL8CPy2WE4WCUD+ZsLNfaQ==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/eventstream-serde-node": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.4.tgz", + "integrity": "sha512-mjlG0OzGAYuUpdUpflfb9zyLrBGgmQmrobNT8b42ZTsGv/J03+t24uhhtVEKG/b2jFtPIHF74Bq+VUtbzEKOKg==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/eventstream-serde-universal": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.4.tgz", + "integrity": "sha512-Od9dv8zh3PgOD7Vj4T3HSuox16n0VG8jJIM2gvKASL6aCtcS8CfHZDWe1Ik3ZXW6xBouU+45Q5wgoliWDZiJ0A==", + "dependencies": { + "@smithy/eventstream-codec": "^3.1.2", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/fetch-http-handler": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.2.tgz", + "integrity": "sha512-3LaWlBZObyGrOOd7e5MlacnAKEwFBmAeiW/TOj2eR9475Vnq30uS2510+tnKbxrGjROfNdOhQqGo5j3sqLT6bA==", + "dependencies": { + "@smithy/protocol-http": "^4.0.4", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/hash-node": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.3.tgz", + "integrity": "sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw==", + "dependencies": { + "@smithy/types": "^3.3.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/invalid-dependency": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz", + "integrity": "sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/middleware-content-length": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.4.tgz", + "integrity": "sha512-wySGje/KfhsnF8YSh9hP16pZcl3C+X6zRsvSfItQGvCyte92LliilU3SD0nR7kTlxnAJwxY8vE/k4Eoezj847Q==", + "dependencies": { + "@smithy/protocol-http": "^4.0.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/middleware-endpoint": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.0.5.tgz", + "integrity": "sha512-V4acqqrh5tDxUEGVTOgf2lYMZqPQsoGntCrjrJZEeBzEzDry2d2vcI1QCXhGltXPPY+BMc6eksZMguA9fIY8vA==", + "dependencies": { + "@smithy/middleware-serde": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/middleware-retry": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.11.tgz", + "integrity": "sha512-/TIRWmhwMpv99JCGuMhJPnH7ggk/Lah7s/uNDyr7faF02BxNsyD/fz9Tw7pgCf9tYOKgjimm2Qml1Aq1pbkt6g==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.0.4", + "@smithy/service-error-classification": "^3.0.3", + "@smithy/smithy-client": "^3.1.9", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/middleware-serde": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", + "integrity": "sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/middleware-stack": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz", + "integrity": "sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/node-config-provider": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", + "dependencies": { + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/node-http-handler": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.3.tgz", + "integrity": "sha512-UiKZm8KHb/JeOPzHZtRUfyaRDO1KPKPpsd7iplhiwVGOeVdkiVJ5bVe7+NhWREMOKomrDIDdSZyglvMothLg0Q==", + "dependencies": { + "@smithy/abort-controller": "^3.1.1", + "@smithy/protocol-http": "^4.0.4", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/property-provider": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/protocol-http": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.0.4.tgz", + "integrity": "sha512-fAA2O4EFyNRyYdFLVIv5xMMeRb+3fRKc/Rt2flh5k831vLvUmNFXcydeg7V3UeEhGURJI4c1asmGJBjvmF6j8Q==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/querystring-builder": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", + "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", + "dependencies": { + "@smithy/types": "^3.3.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/querystring-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz", + "integrity": "sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/service-error-classification": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz", + "integrity": "sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ==", + "dependencies": { + "@smithy/types": "^3.3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/smithy-client": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.9.tgz", + "integrity": "sha512-My2RaInZ4gSwJUPMaiLR/Nk82+c4LlvqpXA+n7lonGYgCZq23Tg+/xFhgmiejJ6XPElYJysTPyV90vKyp17+1g==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/url-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.3.tgz", + "integrity": "sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==", + "dependencies": { + "@smithy/querystring-parser": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-defaults-mode-browser": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.11.tgz", + "integrity": "sha512-O3s9DGb3bmRvEKmT8RwvSWK4A9r6svfd+MnJB+UMi9ZcCkAnoRtliulOnGF0qCMkKF9mwk2tkopBBstalPY/vg==", + "dependencies": { + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.1.9", + "@smithy/types": "^3.3.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-defaults-mode-node": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.11.tgz", + "integrity": "sha512-qd4a9qtyOa/WY14aHHOkMafhh9z8D2QTwlcBoXMTPnEwtcY+xpe1JyFm9vya7VsB8hHsfn3XodEtwqREiu4ygQ==", + "dependencies": { + "@smithy/config-resolver": "^3.0.5", + "@smithy/credential-provider-imds": "^3.1.4", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.1.9", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-endpoints": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.0.5.tgz", + "integrity": "sha512-ReQP0BWihIE68OAblC/WQmDD40Gx+QY1Ez8mTdFMXpmjfxSyz2fVQu3A4zXRfQU9sZXtewk3GmhfOHswvX+eNg==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-middleware": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-retry": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.3.tgz", + "integrity": "sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w==", "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@smithy/service-error-classification": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/util-endpoints": { - "version": "3.470.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.470.0.tgz", - "integrity": "sha512-6N6VvPCmu+89p5Ez/+gLf+X620iQ9JpIs8p8ECZiCodirzFOe8NC1O2S7eov7YiG9IHSuodqn/0qNq+v+oLe0A==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/util-endpoints": "^1.0.7", - "tslib": "^2.5.0" + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.1.tgz", + "integrity": "sha512-EhRnVvl3AhoHAT2rGQ5o+oSDRM/BUSMPLZZdRJZLcNVUsFAjOs4vHaPdNQivTSzRcFxf5DA4gtO46WWU2zimaw==", + "dependencies": { + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.468.0.tgz", - "integrity": "sha512-OJyhWWsDEizR3L+dCgMXSUmaCywkiZ7HSbnQytbeKGwokIhD69HTiJcibF/sgcM5gk4k3Mq3puUhGnEZ46GIig==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/types": "^2.7.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.470.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.470.0.tgz", - "integrity": "sha512-QxsZ9iVHcBB/XRdYvwfM5AMvNp58HfqkIrH88mY0cmxuvtlIGDfWjczdDrZMJk9y0vIq+cuoCHsGXHu7PyiEAQ==", - "optional": true, - "peer": true, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/node-config-provider": "^2.1.8", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/client-firehose": { @@ -1934,21 +3784,390 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.474.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.474.0.tgz", - "integrity": "sha512-eVRdeB+AoTNSzfc4viHfr0jfkHujSlf4ToExJtTuxS1wlgmIyyxRNrVKxbf0K78YK/TXRsRlJPoS5QCD5h1S2w==", - "optional": true, - "peer": true, + "version": "3.616.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.616.0.tgz", + "integrity": "sha512-O/urkh2kECs/IqZIVZxyeyHZ7OR2ZWhLNK7btsVQBQvJKrEspLrk/Fp20Qfg5JDerQfBN83ZbyRXLJOOucdZpw==", + "dependencies": { + "@smithy/core": "^2.2.7", + "@smithy/protocol-http": "^4.0.4", + "@smithy/signature-v4": "^4.0.0", + "@smithy/smithy-client": "^3.1.8", + "@smithy/types": "^3.3.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.1.tgz", + "integrity": "sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==", "dependencies": { - "@smithy/core": "^1.1.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/signature-v4": "^2.0.0", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/core": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.2.8.tgz", + "integrity": "sha512-1Y0XX0Ucyg0LWTfTVLWpmvSRtFRniykUl3dQ0os1sTd03mKDudR6mVyX+2ak1phwPXx2aEWMAAdW52JNi0mc3A==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-retry": "^3.0.11", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/smithy-client": "^3.1.9", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/fetch-http-handler": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.2.tgz", + "integrity": "sha512-3LaWlBZObyGrOOd7e5MlacnAKEwFBmAeiW/TOj2eR9475Vnq30uS2510+tnKbxrGjROfNdOhQqGo5j3sqLT6bA==", + "dependencies": { + "@smithy/protocol-http": "^4.0.4", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/middleware-endpoint": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.0.5.tgz", + "integrity": "sha512-V4acqqrh5tDxUEGVTOgf2lYMZqPQsoGntCrjrJZEeBzEzDry2d2vcI1QCXhGltXPPY+BMc6eksZMguA9fIY8vA==", + "dependencies": { + "@smithy/middleware-serde": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/middleware-retry": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.11.tgz", + "integrity": "sha512-/TIRWmhwMpv99JCGuMhJPnH7ggk/Lah7s/uNDyr7faF02BxNsyD/fz9Tw7pgCf9tYOKgjimm2Qml1Aq1pbkt6g==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.0.4", + "@smithy/service-error-classification": "^3.0.3", + "@smithy/smithy-client": "^3.1.9", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/middleware-serde": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", + "integrity": "sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/middleware-stack": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz", + "integrity": "sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/node-config-provider": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", + "dependencies": { + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/node-http-handler": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.3.tgz", + "integrity": "sha512-UiKZm8KHb/JeOPzHZtRUfyaRDO1KPKPpsd7iplhiwVGOeVdkiVJ5bVe7+NhWREMOKomrDIDdSZyglvMothLg0Q==", + "dependencies": { + "@smithy/abort-controller": "^3.1.1", + "@smithy/protocol-http": "^4.0.4", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/property-provider": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/protocol-http": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.0.4.tgz", + "integrity": "sha512-fAA2O4EFyNRyYdFLVIv5xMMeRb+3fRKc/Rt2flh5k831vLvUmNFXcydeg7V3UeEhGURJI4c1asmGJBjvmF6j8Q==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/querystring-builder": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", + "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", + "dependencies": { + "@smithy/types": "^3.3.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/querystring-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz", + "integrity": "sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/service-error-classification": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz", + "integrity": "sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ==", + "dependencies": { + "@smithy/types": "^3.3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/signature-v4": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.0.0.tgz", + "integrity": "sha512-ervYjQ+ZvmNG51Ui77IOTPri7nOyo8Kembzt9uwwlmtXJPmFXvslOahbA1blvAVs7G0KlYMiOBog1rAt7RVXxg==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/types": "^3.3.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/smithy-client": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.9.tgz", + "integrity": "sha512-My2RaInZ4gSwJUPMaiLR/Nk82+c4LlvqpXA+n7lonGYgCZq23Tg+/xFhgmiejJ6XPElYJysTPyV90vKyp17+1g==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/protocol-http": "^4.0.4", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/url-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.3.tgz", + "integrity": "sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==", + "dependencies": { + "@smithy/querystring-parser": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/util-middleware": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/util-retry": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.3.tgz", + "integrity": "sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w==", + "dependencies": { + "@smithy/service-error-classification": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/util-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.1.tgz", + "integrity": "sha512-EhRnVvl3AhoHAT2rGQ5o+oSDRM/BUSMPLZZdRJZLcNVUsFAjOs4vHaPdNQivTSzRcFxf5DA4gtO46WWU2zimaw==", + "dependencies": { + "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/node-http-handler": "^3.1.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/credential-provider-env": { @@ -4927,9 +7146,10 @@ "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, "node_modules/axios": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", - "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -6211,12 +8431,13 @@ "dev": true }, "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", "dependencies": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, @@ -9317,9 +11538,10 @@ } }, "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", + "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", + "license": "BSD-2-Clause", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -9399,9 +11621,13 @@ "dev": true }, "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } diff --git a/source/lambda/es-proxy-layer/package.json b/source/lambda/es-proxy-layer/package.json index 1116e8483..9c11f777a 100644 --- a/source/lambda/es-proxy-layer/package.json +++ b/source/lambda/es-proxy-layer/package.json @@ -1,6 +1,6 @@ { "name": "proxy-es", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot Lambda managing querying of data store", "main": "index.js", "scripts": { @@ -14,14 +14,16 @@ }, "license": "Apache-2.0", "dependencies": { + "@aws-sdk/client-bedrock-agent-runtime": "^3.616.0", + "@aws-sdk/client-bedrock-runtime": "^3.616.0", "@aws-sdk/client-firehose": "^3.511.0", "@aws-sdk/client-sagemaker-runtime": "^3.511.0", "@aws-sdk/s3-request-presigner": "^3.511.0", "@dqbd/tiktoken": "^1.0.7", "aws4": "^1.6.0", - "axios": "^1.6.8", + "axios": "^1.7.4", "bodybuilder": "^2.5.1", - "handlebars": "^4.7.2", + "handlebars": "^4.7.8", "langchain": "^0.0.209", "linkifyjs": "^3.0.0-beta.3", "sanitize-html": "^2.13.0", @@ -35,6 +37,7 @@ "jest": "^29.7.0" }, "overrides": { - "fast-xml-parser": "^4.4.1" + "fast-xml-parser": "^4.4.1", + "uglify-js": "^3.19.2" } } diff --git a/source/lambda/es-proxy-layer/test/bedrockAgents.test.js b/source/lambda/es-proxy-layer/test/bedrockAgents.test.js index e971c9b35..ac8c37942 100644 --- a/source/lambda/es-proxy-layer/test/bedrockAgents.test.js +++ b/source/lambda/es-proxy-layer/test/bedrockAgents.test.js @@ -17,6 +17,7 @@ const bedRockAgentMock = mockClient(BedrockAgentRuntimeClient); const presigner = require('@aws-sdk/s3-request-presigner'); const qnabot = require('qnabot/logging'); const { bedrockRetrieveAndGenerate } = require('../lib/bedrock/bedrockAgents'); +const _ = require('lodash'); require('aws-sdk-client-mock-jest'); const region = process.env.AWS_REGION || 'us-east-1'; @@ -24,7 +25,7 @@ const region = process.env.AWS_REGION || 'us-east-1'; jest.mock('qnabot/logging'); jest.mock('@aws-sdk/s3-request-presigner'); - +const promptTemplate = 'test-bedrock-agent-prompt'; const req = { question: 'what is ec2?', _settings: { @@ -35,13 +36,20 @@ const req = { KNOWLEDGE_BASE_SHOW_REFERENCES: true, KNOWLEDGE_BASE_S3_SIGNED_URL_EXPIRE_SECS: 300, KNOWLEDGE_BASE_PREFIX_MESSAGE: 'Bedrock Agent:', + KNOWLEDGE_BASE_PROMPT_TEMPLATE: promptTemplate, + KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS: 1, + KNOWLEDGE_BASE_METADATA_FILTERS: '{}', + KNOWLEDGE_BASE_SEARCH_TYPE: 'DEFAULT', + KNOWLEDGE_BASE_MODEL_PARAMS: '{"temperature":0.3, "maxTokens": 245, "topP": 0.9 }', + BEDROCK_GUARDRAIL_IDENTIFIER: '', + BEDROCK_GUARDRAIL_VERSION: '', }, _preferredResponseType: 'text' } const res = { _userInfo: { - knowledgeBaseSessionId : undefined + knowledgeBaseSessionId: undefined } } @@ -79,6 +87,46 @@ const response = { } } +const expectedResult = { + a: 'Bedrock Agent:\n' + + '\n' + + 'Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud.\n' + + '\n' + + ' compute capacity in the cloud.\n' + + '\n' + + ' secure Linux or Windows Server images' + + '\n' + + '\n' + + ' Source Link: https://signedurl.s3.amazonaws.com/', + alt: { + markdown: '**Bedrock Agent:**\n' + + '\n' + + 'Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud.
' + + '\n' + + ' Context\n' + + '

\n' + + '\n' + + '***\n' + + '\n' + + '
\n' + + '\n' + + ' compute capacity in the cloud.\n' + + '\n' + + '***\n' + + '\n' + + '
\n' + + '\n' + + ' secure Linux or Windows Server images

\n' + + '
\n' + + '
' + + '\n' + + '\n' + + ' Source Link: [aws-overview.pdf](https://signedurl.s3.amazonaws.com/)', + ssml: ' Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud. ', + }, + type: 'text', + answersource: 'BEDROCK KNOWLEDGE BASE' +}; presigner.getSignedUrl.mockImplementation(() => { return 'https://signedurl.s3.amazonaws.com/' @@ -93,70 +141,50 @@ describe('bedrockAgents', () => { test('bedrockRetrieveAndGenerate returns correct body when sessionId is new', async () => { const sessionId = 'newSessionId'; response.sessionId = sessionId; - bedRockAgentMock.on(RetrieveAndGenerateCommand).resolves(response); const result = await bedrockRetrieveAndGenerate(req, res); expect(bedRockAgentMock).toHaveReceivedCommandTimes(RetrieveAndGenerateCommand, 1); expect(bedRockAgentMock).toHaveReceivedCommandWith(RetrieveAndGenerateCommand, { - input:{ + input: { text: 'what is ec2?', }, - retrieveAndGenerateConfiguration:{ - knowledgeBaseConfiguration:{ + retrieveAndGenerateConfiguration: { + knowledgeBaseConfiguration: { knowledgeBaseId: 'testKnowledgeBaseId', modelArn: `arn:aws:bedrock:${region}::foundation-model/testModel`, + retrievalConfiguration: { + vectorSearchConfiguration: { + numberOfResults: 1 + } + }, + generationConfiguration: { + promptTemplate: { + textPromptTemplate: promptTemplate, + }, + inferenceConfig: { + textInferenceConfig: { + "maxTokens": 245, + "temperature": 0.3, + "topP": 0.9 + }, + }, + }, }, type: 'KNOWLEDGE_BASE', - } + }, }); expect(result).toStrictEqual([ { - _userInfo: {knowledgeBaseSessionId: "newSessionId"}, + _userInfo: { knowledgeBaseSessionId: "newSessionId" }, + got_hits: 1, + session: { qnabot_gotanswer: true }, }, - { - a: 'Bedrock Agent:\n' + - '\n' + - 'Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud.\n' + - '\n' + - ' compute capacity in the cloud.\n' + - '\n' + - ' secure Linux or Windows Server images' + - '\n' + - '\n' + - ' Source Link: https://signedurl.s3.amazonaws.com/', - alt: { - markdown: '**Bedrock Agent:**\n' + - '\n' + - 'Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud.
' + - '\n' + - ' Context\n' + - '

\n' + - '\n' + - '***\n' + - '\n' + - '
\n' + - '\n' + - ' compute capacity in the cloud.\n' + - '\n' + - '***\n' + - '\n' + - '
\n' + - '\n' + - ' secure Linux or Windows Server images

\n' + - '
\n' + - '
' + - '\n' + - '\n' + - ' Source Link: [aws-overview.pdf](https://signedurl.s3.amazonaws.com/)', - ssml: ' Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud. ', - }, - type: 'text', - answersource: 'BEDROCK KNOWLEDGE BASE' - } + expectedResult ]); }); + test('bedrockRetrieveAndGenerate returns correct body when sessionId is existing', async () => { const sessionId = 'testSessionId'; res._userInfo.knowledgeBaseSessionId = sessionId @@ -166,13 +194,30 @@ describe('bedrockAgents', () => { const result = await bedrockRetrieveAndGenerate(req, res); expect(bedRockAgentMock).toHaveReceivedCommandTimes(RetrieveAndGenerateCommand, 1); expect(bedRockAgentMock).toHaveReceivedCommandWith(RetrieveAndGenerateCommand, { - input:{ + input: { text: 'what is ec2?', }, - retrieveAndGenerateConfiguration:{ - knowledgeBaseConfiguration:{ + retrieveAndGenerateConfiguration: { + knowledgeBaseConfiguration: { knowledgeBaseId: 'testKnowledgeBaseId', modelArn: `arn:aws:bedrock:${region}::foundation-model/testModel`, + retrievalConfiguration: { + vectorSearchConfiguration: { + numberOfResults: 1 + } + }, + generationConfiguration: { + promptTemplate: { + textPromptTemplate: promptTemplate, + }, + inferenceConfig: { + textInferenceConfig: { + "maxTokens": 245, + "temperature": 0.3, + "topP": 0.9 + }, + }, + }, }, type: 'KNOWLEDGE_BASE', }, @@ -180,48 +225,11 @@ describe('bedrockAgents', () => { }); expect(result).toStrictEqual([ { - _userInfo: {knowledgeBaseSessionId: "testSessionId"}, + _userInfo: { knowledgeBaseSessionId: "testSessionId" }, + got_hits: 1, + session: { qnabot_gotanswer: true }, }, - { - a: 'Bedrock Agent:\n' + - '\n' + - 'Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud.\n' + - '\n' + - ' compute capacity in the cloud.\n' + - '\n' + - ' secure Linux or Windows Server images' + - '\n' + - '\n' + - ' Source Link: https://signedurl.s3.amazonaws.com/', - alt: { - markdown: '**Bedrock Agent:**\n' + - '\n' + - 'Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud.
' + - '\n' + - ' Context\n' + - '

\n' + - '\n' + - '***\n' + - '\n' + - '
\n' + - '\n' + - ' compute capacity in the cloud.\n' + - '\n' + - '***\n' + - '\n' + - '
\n' + - '\n' + - ' secure Linux or Windows Server images

\n' + - '
\n' + - '
' + - '\n' + - '\n' + - ' Source Link: [aws-overview.pdf](https://signedurl.s3.amazonaws.com/)', - ssml: ' Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud. ', - }, - type: 'text', - answersource: 'BEDROCK KNOWLEDGE BASE' - } + expectedResult ]); }); @@ -232,33 +240,202 @@ describe('bedrockAgents', () => { const e = new Error('Invalid or Expired'); e.name = 'ValidationException'; - sessionId = 'newSessionId'; + sessionId = 'newSessionId'; response.sessionId = sessionId; bedRockAgentMock.on(RetrieveAndGenerateCommand).rejectsOnce(e).resolvesOnce(response); const result = await bedrockRetrieveAndGenerate(req, res); expect(bedRockAgentMock).toHaveReceivedCommandTimes(RetrieveAndGenerateCommand, 2); expect(bedRockAgentMock).toHaveReceivedNthCommandWith(1, RetrieveAndGenerateCommand, { - input:{ + input: { text: 'what is ec2?', }, - retrieveAndGenerateConfiguration:{ - knowledgeBaseConfiguration:{ + retrieveAndGenerateConfiguration: { + knowledgeBaseConfiguration: { knowledgeBaseId: 'testKnowledgeBaseId', modelArn: `arn:aws:bedrock:${region}::foundation-model/testModel`, + retrievalConfiguration: { + vectorSearchConfiguration: { + numberOfResults: 1 + } + }, + generationConfiguration: { + promptTemplate: { + textPromptTemplate: promptTemplate, + }, + inferenceConfig: { + textInferenceConfig: { + "maxTokens": 245, + "temperature": 0.3, + "topP": 0.9 + }, + }, + }, }, type: 'KNOWLEDGE_BASE', }, sessionId: 'testSessionId', }); expect(bedRockAgentMock).toHaveReceivedNthCommandWith(2, RetrieveAndGenerateCommand, { - input:{ + input: { + text: 'what is ec2?', + }, + retrieveAndGenerateConfiguration: { + knowledgeBaseConfiguration: { + knowledgeBaseId: 'testKnowledgeBaseId', + modelArn: `arn:aws:bedrock:${region}::foundation-model/testModel`, + retrievalConfiguration: { + vectorSearchConfiguration: { + numberOfResults: 1 + } + }, + generationConfiguration: { + promptTemplate: { + textPromptTemplate: promptTemplate, + }, + inferenceConfig: { + textInferenceConfig: { + "maxTokens": 245, + "temperature": 0.3, + "topP": 0.9 + } + }, + }, + }, + type: 'KNOWLEDGE_BASE', + }, + }); + expect(result).toStrictEqual([ + { + _userInfo: { knowledgeBaseSessionId: "newSessionId" }, + got_hits: 1, + session: { qnabot_gotanswer: true }, + }, + expectedResult + ]); + }); + + test('bedrockRetrieveAndGenerate modifies request and return correct body when additionalModelRequestFields is passed', async () => { + const sessionId = 'newSessionId'; + response.sessionId = sessionId; + const modifiedReq = _.cloneDeep(req) + modifiedReq._settings.KNOWLEDGE_BASE_MODEL_PARAMS = '{"temperature":0.3, "maxTokens": 245, "topP": 0.9, "top_k": 240 }' + + + bedRockAgentMock.on(RetrieveAndGenerateCommand).resolves(response); + + const result = await bedrockRetrieveAndGenerate(modifiedReq, res); + expect(bedRockAgentMock).toHaveReceivedCommandTimes(RetrieveAndGenerateCommand, 1); + expect(bedRockAgentMock).toHaveReceivedCommandWith(RetrieveAndGenerateCommand, { + input: { + text: 'what is ec2?', + }, + retrieveAndGenerateConfiguration: { + knowledgeBaseConfiguration: { + knowledgeBaseId: 'testKnowledgeBaseId', + modelArn: `arn:aws:bedrock:${region}::foundation-model/testModel`, + retrievalConfiguration: { + vectorSearchConfiguration: { + numberOfResults: 1 + } + }, + generationConfiguration: { + promptTemplate: { + textPromptTemplate: promptTemplate, + }, + inferenceConfig: { + textInferenceConfig: { + "maxTokens": 245, + "temperature": 0.3, + "topP": 0.9 + }, + }, + additionalModelRequestFields: { + "top_k": 240 + }, + }, + }, + type: 'KNOWLEDGE_BASE', + }, + }); + expect(result).toStrictEqual([ + { + _userInfo: { knowledgeBaseSessionId: "newSessionId" }, + got_hits: 1, + session: { qnabot_gotanswer: true }, + }, + expectedResult + ]); + }); + + test('bedrockRetrieveAndGenerate returns correct body when prompt template and inference parameters are empty', async () => { + const sessionId = 'newSessionId'; + response.sessionId = sessionId; + const modifiedReq = _.cloneDeep(req) + modifiedReq._settings.KNOWLEDGE_BASE_PROMPT_TEMPLATE = ''; + modifiedReq._settings.KNOWLEDGE_BASE_MODEL_PARAMS = '{}' + bedRockAgentMock.on(RetrieveAndGenerateCommand).resolves(response); + + const result = await bedrockRetrieveAndGenerate(modifiedReq, res); + expect(bedRockAgentMock).toHaveReceivedCommandTimes(RetrieveAndGenerateCommand, 1); + expect(bedRockAgentMock).toHaveReceivedCommandWith(RetrieveAndGenerateCommand, { + input: { + text: 'what is ec2?', + }, + retrieveAndGenerateConfiguration: { + knowledgeBaseConfiguration: { + knowledgeBaseId: 'testKnowledgeBaseId', + modelArn: `arn:aws:bedrock:${region}::foundation-model/testModel`, + retrievalConfiguration: { + vectorSearchConfiguration: { + numberOfResults: 1 + } + }, + }, + type: 'KNOWLEDGE_BASE', + }, + }); + expect(result).toStrictEqual([ + { + _userInfo: { knowledgeBaseSessionId: "newSessionId" }, + got_hits: 1, + session: { qnabot_gotanswer: true }, + }, + expectedResult + ]); + }); + + test('bedrockRetrieveAndGenerate returns correct body when prompt template is empty but inference parameters are not empty', async () => { + const sessionId = 'newSessionId'; + response.sessionId = sessionId; + const modifiedReq = _.cloneDeep(req) + modifiedReq._settings.KNOWLEDGE_BASE_PROMPT_TEMPLATE = ''; + bedRockAgentMock.on(RetrieveAndGenerateCommand).resolves(response); + + const result = await bedrockRetrieveAndGenerate(modifiedReq, res); + expect(bedRockAgentMock).toHaveReceivedCommandTimes(RetrieveAndGenerateCommand, 1); + expect(bedRockAgentMock).toHaveReceivedCommandWith(RetrieveAndGenerateCommand, { + input: { text: 'what is ec2?', }, - retrieveAndGenerateConfiguration:{ - knowledgeBaseConfiguration:{ + retrieveAndGenerateConfiguration: { + knowledgeBaseConfiguration: { knowledgeBaseId: 'testKnowledgeBaseId', modelArn: `arn:aws:bedrock:${region}::foundation-model/testModel`, + retrievalConfiguration: { + vectorSearchConfiguration: { + numberOfResults: 1 + } + }, + generationConfiguration: { + inferenceConfig: { + textInferenceConfig: { + "maxTokens": 245, + "temperature": 0.3, + "topP": 0.9 + }, + }, + }, }, type: 'KNOWLEDGE_BASE', }, @@ -266,47 +443,154 @@ describe('bedrockAgents', () => { expect(result).toStrictEqual([ { _userInfo: { knowledgeBaseSessionId: "newSessionId" }, + got_hits: 1, + session: { qnabot_gotanswer: true }, + }, + expectedResult + ]); + }); + + test('bedrockRetrieveAndGenerate returns correct body when prompt template and inference config are empty but additionalModelRequestFields is not empty', async () => { + const sessionId = 'newSessionId'; + response.sessionId = sessionId; + const modifiedReq = _.cloneDeep(req) + modifiedReq._settings.KNOWLEDGE_BASE_PROMPT_TEMPLATE = ''; + modifiedReq._settings.KNOWLEDGE_BASE_MODEL_PARAMS = '{"top_k": 240 }' + bedRockAgentMock.on(RetrieveAndGenerateCommand).resolves(response); + + const result = await bedrockRetrieveAndGenerate(modifiedReq, res); + expect(bedRockAgentMock).toHaveReceivedCommandTimes(RetrieveAndGenerateCommand, 1); + expect(bedRockAgentMock).toHaveReceivedCommandWith(RetrieveAndGenerateCommand, { + input: { + text: 'what is ec2?', }, + retrieveAndGenerateConfiguration: { + knowledgeBaseConfiguration: { + knowledgeBaseId: 'testKnowledgeBaseId', + modelArn: `arn:aws:bedrock:${region}::foundation-model/testModel`, + retrievalConfiguration: { + vectorSearchConfiguration: { + numberOfResults: 1 + } + }, + generationConfiguration: { + additionalModelRequestFields: { + "top_k": 240 + }, + }, + }, + type: 'KNOWLEDGE_BASE', + }, + }); + expect(result).toStrictEqual([ { - a: 'Bedrock Agent:\n' + - '\n' + - 'Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud.\n' + - '\n' + - ' compute capacity in the cloud.\n' + - '\n' + - ' secure Linux or Windows Server images' + - '\n' + - '\n' + - ' Source Link: https://signedurl.s3.amazonaws.com/', - alt: { - markdown: '**Bedrock Agent:**\n' + - '\n' + - 'Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud.
' + - '\n' + - ' Context\n' + - '

\n' + - '\n' + - '***\n' + - '\n' + - '
\n' + - '\n' + - ' compute capacity in the cloud.\n' + - '\n' + - '***\n' + - '\n' + - '
\n' + - '\n' + - ' secure Linux or Windows Server images

\n' + - '
\n' + - '
' + - '\n' + - '\n' + - ' Source Link: [aws-overview.pdf](https://signedurl.s3.amazonaws.com/)', - ssml: ' Amazon EC2 (Amazon Elastic Compute Cloud) is a web service that provides secure, resizable compute capacity in the cloud. ', + _userInfo: { knowledgeBaseSessionId: "newSessionId" }, + got_hits: 1, + session: { qnabot_gotanswer: true }, + }, + expectedResult + ]); + }); + + test('bedrockRetrieveAndGenerate returns correct body when VectorSearchConfiguration is overriden with SearchTyoe', async () => { + const sessionId = 'newSessionId'; + response.sessionId = sessionId; + const modifiedReq = _.cloneDeep(req) + modifiedReq._settings.KNOWLEDGE_BASE_SEARCH_TYPE = 'HYBRID' + bedRockAgentMock.on(RetrieveAndGenerateCommand).resolves(response); + + const result = await bedrockRetrieveAndGenerate(modifiedReq, res); + expect(bedRockAgentMock).toHaveReceivedCommandTimes(RetrieveAndGenerateCommand, 1); + expect(bedRockAgentMock).toHaveReceivedCommandWith(RetrieveAndGenerateCommand, { + input: { + text: 'what is ec2?', + }, + retrieveAndGenerateConfiguration: { + knowledgeBaseConfiguration: { + knowledgeBaseId: 'testKnowledgeBaseId', + modelArn: `arn:aws:bedrock:${region}::foundation-model/testModel`, + retrievalConfiguration: { + vectorSearchConfiguration: { + numberOfResults: 1, + overrideSearchType: 'HYBRID' + } + }, + generationConfiguration: { + promptTemplate: { + textPromptTemplate: promptTemplate, + }, + inferenceConfig: { + textInferenceConfig: { + "maxTokens": 245, + "temperature": 0.3, + "topP": 0.9 + } + }, + }, }, - type: 'text', - answersource: 'BEDROCK KNOWLEDGE BASE' - } + type: 'KNOWLEDGE_BASE', + }, + }); + expect(result).toStrictEqual([ + { + _userInfo: { knowledgeBaseSessionId: "newSessionId" }, + got_hits: 1, + session: { qnabot_gotanswer: true }, + }, + expectedResult + ]); + }); + + test('bedrockRetrieveAndGenerate returns correct body when GuardrailConfiguration is overriden', async () => { + const sessionId = 'newSessionId'; + response.sessionId = sessionId; + const modifiedReq = _.cloneDeep(req) + modifiedReq._settings.BEDROCK_GUARDRAIL_IDENTIFIER = 'ds9asa' + modifiedReq._settings.BEDROCK_GUARDRAIL_VERSION = '2' + bedRockAgentMock.on(RetrieveAndGenerateCommand).resolves(response); + + const result = await bedrockRetrieveAndGenerate(modifiedReq, res); + expect(bedRockAgentMock).toHaveReceivedCommandTimes(RetrieveAndGenerateCommand, 1); + expect(bedRockAgentMock).toHaveReceivedCommandWith(RetrieveAndGenerateCommand, { + input: { + text: 'what is ec2?', + }, + retrieveAndGenerateConfiguration: { + knowledgeBaseConfiguration: { + knowledgeBaseId: 'testKnowledgeBaseId', + modelArn: `arn:aws:bedrock:${region}::foundation-model/testModel`, + retrievalConfiguration: { + vectorSearchConfiguration: { + numberOfResults: 1, + } + }, + generationConfiguration: { + promptTemplate: { + textPromptTemplate: promptTemplate, + }, + inferenceConfig: { + textInferenceConfig: { + "maxTokens": 245, + "temperature": 0.3, + "topP": 0.9 + } + }, + guardrailConfiguration: { + guardrailId: 'ds9asa', + guardrailVersion: '2' + }, + }, + }, + type: 'KNOWLEDGE_BASE', + }, + }); + expect(result).toStrictEqual([ + { + _userInfo: { knowledgeBaseSessionId: "newSessionId" }, + got_hits: 1, + session: { qnabot_gotanswer: true }, + }, + expectedResult ]); }); @@ -316,13 +600,30 @@ describe('bedrockAgents', () => { response.sessionId = sessionId const e = new Error('Invalid or Expired'); - sessionId = 'newSessionId'; + sessionId = 'newSessionId'; response.sessionId = sessionId; bedRockAgentMock.on(RetrieveAndGenerateCommand).rejects(e); - + await expect(bedrockRetrieveAndGenerate(req, res)).rejects.toThrowError(e); expect(bedRockAgentMock).toHaveReceivedCommandTimes(RetrieveAndGenerateCommand, 1); - + expect(qnabot.log).toHaveBeenCalledTimes(4); + }); + test('bedrockRetrieveAndGenerate handles ValidationException correctly', async () => { + let sessionId = 'testSessionId'; + res._userInfo.knowledgeBaseSessionId = sessionId + response.sessionId = sessionId + + const e = new Error('Model is not valid'); + e.name = "ValidationException"; + sessionId = 'newSessionId'; + response.sessionId = sessionId; + bedRockAgentMock.on(RetrieveAndGenerateCommand).rejects(e); + + await expect(bedrockRetrieveAndGenerate(req, res)).rejects.toThrowError(e); + expect(bedRockAgentMock).toHaveReceivedCommandTimes(RetrieveAndGenerateCommand, 2); + expect(qnabot.log).toHaveBeenCalledTimes(5); + + }); }); diff --git a/source/lambda/es-proxy-layer/test/bedrockModels.test.js b/source/lambda/es-proxy-layer/test/bedrockModels.test.js index e2a65bc01..f7f66390b 100644 --- a/source/lambda/es-proxy-layer/test/bedrockModels.test.js +++ b/source/lambda/es-proxy-layer/test/bedrockModels.test.js @@ -22,13 +22,28 @@ jest.mock('qnabot/settings'); jest.mock('qnabot/logging'); jest.mock('@aws-sdk/client-bedrock-runtime'); +const guardrails = { + guardrailIdentifier: 'test_id', + guardrailVersion: 1 +}; + const llmModelBodies = { 'amazon.titan-text-express-v1': { - textGenerationConfig: { maxTokenCount: 4096, stopSequences: [], temperature: 0, topP: 1 }, + textGenerationConfig: { maxTokenCount: 256, stopSequences: [], temperature: 0, topP: 1 }, inputText: 'test prompt', }, 'amazon.titan-text-lite-v1': { - textGenerationConfig: { maxTokenCount: 4096, stopSequences: [], temperature: 0, topP: 1 }, + textGenerationConfig: { maxTokenCount: 256, stopSequences: [], temperature: 0, topP: 1 }, + inputText: 'test prompt', + }, + 'amazon.titan-embed-text-v1': { + inputText: 'test prompt', + }, + 'amazon.titan-embed-text-v2': { + inputText: 'test prompt', + }, + 'amazon.titan-text-premier-v1': { + textGenerationConfig: { maxTokenCount: 256, stopSequences: [], temperature: 0, topP: 1 }, inputText: 'test prompt', }, 'ai21.j2-ultra-v1': { @@ -91,7 +106,7 @@ const llmModelBodies = { } ], }, - 'anthropic.claude-3-sonnet-20240229-v1:0': { + 'anthropic.claude-3-sonnet-20240229-v1': { max_tokens: 256, temperature: 0, top_k: 250, @@ -111,7 +126,7 @@ const llmModelBodies = { } ], }, - 'anthropic.claude-3-haiku-20240307-v1:0': { + 'anthropic.claude-3-haiku-20240307-v1': { max_tokens: 256, temperature: 0, top_k: 250, @@ -145,9 +160,6 @@ const llmModelBodies = { top_p: 0.9, prompt: 'test prompt', }, - 'amazon.titan-embed-text-v1': { - inputText: 'test prompt', - }, 'cohere.embed-english-v3': { texts: ['test prompt'], input_type: 'search_document', @@ -159,6 +171,20 @@ const llmModelBodies = { }; const llmModelResponses = { + 'amazon.titan-embed-text-v1': { + body: Buffer.from( + JSON.stringify({ + embedding: 'test response', + }) + ) + }, + 'amazon.titan-embed-text-v2': { + body: Buffer.from( + JSON.stringify({ + embedding: 'test response', + }) + ) + }, 'amazon.titan-text-express-v1': { body: Buffer.from( JSON.stringify({ @@ -181,6 +207,17 @@ const llmModelResponses = { }) ) }, + 'amazon.titan-text-premier-v1': { + body: Buffer.from( + JSON.stringify({ + results: [ + { + outputText: 'test response' + } + ] + }) + ) + }, 'ai21.j2-ultra-v1': { body: Buffer.from( JSON.stringify({ @@ -225,7 +262,7 @@ const llmModelResponses = { }) ) }, - 'anthropic.claude-3-haiku-20240307-v1:0': { + 'anthropic.claude-3-haiku-20240307-v1': { body: Buffer.from( JSON.stringify({ content: [ @@ -236,7 +273,7 @@ const llmModelResponses = { }) ) }, - 'anthropic.claude-3-sonnet-20240229-v1:0': { + 'anthropic.claude-3-sonnet-20240229-v1': { body: Buffer.from( JSON.stringify({ content: [ @@ -265,13 +302,6 @@ const llmModelResponses = { }) ) }, - 'amazon.titan-embed-text-v1': { - body: Buffer.from( - JSON.stringify({ - embedding: 'test response', - }) - ) - }, 'cohere.embed-english-v3': { body: Buffer.from( JSON.stringify({ @@ -288,6 +318,10 @@ const llmModelResponses = { }, }; +function isEmbedding(modelId) { + return modelId.includes('embed'); +}; + describe('bedrockModels', () => { beforeEach(() => { @@ -308,7 +342,7 @@ describe('bedrockModels', () => { e.name = 'ResourceNotFoundException'; bedRockMock.on(InvokeModelCommand).rejects(e); const error = new Error('{\"message\":\"Bedrock anthropic.claude-v1 returned ResourceNotFoundException: Could not resolve the foundation model from the provided model identifier. Please retry after selecting different Bedrock model in Cloudformation stack.\",\"type\":\"Error\"}') - await expect(invokeBedrockModel(modelId, textGenerationConfig, inputText)).rejects.toThrowError(error); + await expect(invokeBedrockModel(modelId, textGenerationConfig, inputText, guardrails)).rejects.toThrowError(error); }); test('invokeBedrockModel returns correct body', async () => { @@ -321,6 +355,11 @@ describe('bedrockModels', () => { modelId, } + if (!isEmbedding(modelId)) { + expectedCall.guardrailIdentifier = "test_id", + expectedCall.guardrailVersion = 1 + } + const sendMock = jest.fn().mockImplementation(() => { const body = llmModelResponses[modelId].body; return { @@ -334,7 +373,7 @@ describe('bedrockModels', () => { }; }); - const response = await invokeBedrockModel(modelId, {}, prompt); + const response = await invokeBedrockModel(modelId, {}, prompt, guardrails); expect(response).toEqual('test response'); expect(InvokeModelCommand).toHaveBeenCalledWith(expectedCall); @@ -351,6 +390,8 @@ describe('bedrockModels', () => { body: JSON.stringify({...llmModelBodies[modelId], textGenerationConfig:{...llmModelBodies[modelId].textGenerationConfig, ...params}}), contentType: 'application/json', modelId, + guardrailIdentifier: "test_id", + guardrailVersion: 1, } const body = llmModelResponses[modelId].body; @@ -366,7 +407,7 @@ describe('bedrockModels', () => { }; }); - const response = await invokeBedrockModel(modelId, params, prompt); + const response = await invokeBedrockModel(modelId, params, prompt, guardrails); expect(response).toEqual('test response'); expect(InvokeModelCommand).toHaveBeenCalledWith(expectedCall); @@ -388,6 +429,8 @@ describe('bedrockModels', () => { body: JSON.stringify({...llmModelBodies[modelId], ...params}), contentType: 'application/json', modelId, + guardrailIdentifier: "test_id", + guardrailVersion: 1, } const body = llmModelResponses[modelId].body; @@ -403,7 +446,7 @@ describe('bedrockModels', () => { }; }); - const response = await invokeBedrockModel(modelId, params, prompt); + const response = await invokeBedrockModel(modelId, params, prompt, guardrails); expect(response).toEqual('test response'); expect(InvokeModelCommand).toHaveBeenCalledWith(expectedCall); @@ -416,7 +459,7 @@ describe('bedrockModels', () => { const modelId = 'unsupported.provider'; try { - await invokeBedrockModel(modelId, {}, prompt); + await invokeBedrockModel(modelId, {}, prompt, guardrails); expect(true).toEqual(false); } catch (err) { expect(err.message).toEqual(`Unsupported model provider: unsupported`); @@ -437,11 +480,11 @@ describe('bedrockModels', () => { }); try { - await invokeBedrockModel(modelId, {}); + await invokeBedrockModel(modelId, {}, guardrails); expect(true).toEqual(false); } catch (err) { expect(err.message).toEqual( - `Exception parsing response body: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined` + `Cannot read properties of undefined (reading 'guardrailIdentifier')` ); } }); diff --git a/source/lambda/es-proxy-layer/test/llm.fixtures.js b/source/lambda/es-proxy-layer/test/llm.fixtures.js index f15975904..526584f95 100644 --- a/source/lambda/es-proxy-layer/test/llm.fixtures.js +++ b/source/lambda/es-proxy-layer/test/llm.fixtures.js @@ -209,6 +209,8 @@ exports.req = { 'LLM_QA_NO_HITS_REGEX': 'Sorry, //remove comment to enable custom no match (no_hits) when LLM does not know the answer.', 'LLM_PROMPT_MAX_TOKEN_LIMIT': '800', + 'BEDROCK_GUARDRAIL_IDENTIFIER': '', + 'BEDROCK_GUARDRAIL_VERSION': '', 'DEFAULT_USER_POOL_JWKS_URL': 'https://cognito-idp.us-east-1.amazonaws.com/us-east-1_MqFhpJCyo/.well-known/jwks.json' }, diff --git a/source/lambda/es-proxy-layer/test/llm.test.js b/source/lambda/es-proxy-layer/test/llm.test.js index 52b7a3819..deb37a25d 100644 --- a/source/lambda/es-proxy-layer/test/llm.test.js +++ b/source/lambda/es-proxy-layer/test/llm.test.js @@ -17,7 +17,6 @@ const { SageMakerRuntime } = require('@aws-sdk/client-sagemaker-runtime'); const { BedrockRuntimeClient, InvokeModelCommand } = require('@aws-sdk/client-bedrock-runtime'); const { ChatMessageHistory } = require('langchain/memory'); const { TokenTextSplitter } = require('langchain/text_splitter'); -const { sanitize } = require('../lib/sanitizeOutput'); const { clean_context, @@ -412,7 +411,7 @@ describe('llm generate_query', () => { contentType: 'application/json', body: JSON.stringify({ textGenerationConfig: { - maxTokenCount: 4096, + maxTokenCount: 256, stopSequences: [], temperature: 0, topP: 1, @@ -676,6 +675,58 @@ describe('llm get_qa', () => { expect(response).toBe('sagemaker response'); }); + test('generates query when Bedrock guardrails are defined', async () => { + const clonedReq = _.cloneDeep(req); + clonedReq._settings.LLM_API = 'BEDROCK'; + clonedReq._settings.LLM_MODEL_ID = 'amazon.titan-text-lite-v1'; + clonedReq._settings.LLM_GENERATE_QUERY_MODEL_PARAMS = ''; + clonedReq._settings.BEDROCK_GUARDRAIL_IDENTIFIER = 'test_id'; + clonedReq._settings.BEDROCK_GUARDRAIL_VERSION = 1; + const sendMock = jest.fn().mockImplementation(() => { + return { + body: Buffer.from(JSON.stringify({ + results: [{ + outputText: 'bedrock response', + }] + })) + } + }); + + BedrockRuntimeClient.mockImplementation(() => { + return { + send: sendMock, + }; + }); + + const response = await generate_query(clonedReq); + + expect(sendMock).toBeCalled(); + expect(InvokeModelCommand).toBeCalledWith({ + accept: 'application/json', + modelId: 'amazon.titan-text-lite-v1', + contentType: 'application/json', + guardrailIdentifier: "test_id", + guardrailVersion: "1", + body: JSON.stringify({ + textGenerationConfig: { + maxTokenCount: 256, + stopSequences: [], + temperature: 0, + topP: 1, + }, + inputText: 'Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.\nChat History: \n\nFollow Up Input: How can I publish Kindle books?\nStandalone question:', + }), + }); + expect(response.question).toBe('How can I publish Kindle books? / bedrock response'); + expect(response.llm_generated_query).toStrictEqual({ + concatenated: 'How can I publish Kindle books? / bedrock response', + orig: 'How can I publish Kindle books?', + result: 'bedrock response', + timing: expect.any(String), + }); + }); + + test('throws error if prompt cannot be truncated smaller than max token count', async () => { const clonedReq = _.cloneDeep(req); clonedReq._settings.LLM_QA_PROMPT_TEMPLATE = 'Some very long prompt that cannot be truncated. '.repeat(100); @@ -861,32 +912,4 @@ describe('llm isNoHits', () => { expect(result).toBe(false); }); -}); - -describe('should be able to sanitize LLM Outputs', () => { - it('should sanitize input data correctly', () => { - const inputData = '

Hello, world!

'; - const expectedOutput = '

Hello, world!

'; - const sanitizedData = sanitize(inputData); - expect(sanitizedData).toEqual(expectedOutput); - }); - - it('should handle empty input data', () => { - const inputData = ''; - const sanitizedData = sanitize(inputData); - expect(sanitizedData).toEqual(''); - }); - - it('should allow href', () => { - const inputData = '
Some text'; - const sanitizedData = sanitize(inputData); - expect(sanitizedData).toEqual('Some text'); - }); - - it('should handle normal response', () => { - const inputData = '

Sorry I don\'t know

'; - const sanitizedData = sanitize(inputData); - expect(sanitizedData).toEqual('

Sorry I don\'t know

'); - }); - }); - \ No newline at end of file +}); \ No newline at end of file diff --git a/source/lambda/es-proxy-layer/test/sanitizeOutput.test.js b/source/lambda/es-proxy-layer/test/sanitizeOutput.test.js new file mode 100644 index 000000000..746f5f183 --- /dev/null +++ b/source/lambda/es-proxy-layer/test/sanitizeOutput.test.js @@ -0,0 +1,62 @@ +/********************************************************************************************************************* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * + * * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * + * with the License. A copy of the License is located at * + * * + * http://www.apache.org/licenses/ * + * * + * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * + * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * + * and limitations under the License. * + *********************************************************************************************************************/ + +const { sanitize, escapeHashMarkdown } = require('../lib/sanitizeOutput'); + +describe('should be able to sanitize LLM Outputs', () => { + it('should sanitize input data correctly', () => { + const inputData = '

Hello, world!

'; + const expectedOutput = '

Hello, world!

'; + const sanitizedData = sanitize(inputData); + expect(sanitizedData).toEqual(expectedOutput); + }); + + it('should handle empty input data', () => { + const inputData = ''; + const sanitizedData = sanitize(inputData); + expect(sanitizedData).toEqual(''); + }); + + it('should allow href', () => { + const inputData = 'Some text'; + const sanitizedData = sanitize(inputData); + expect(sanitizedData).toEqual('Some text'); + }); + + it('should handle normal response', () => { + const inputData = '

Sorry I don\'t know

'; + const sanitizedData = sanitize(inputData); + expect(sanitizedData).toEqual('

Sorry I don\'t know

'); + }); +}); + +describe('should be able to escape hash sybmbol to prevent markdown issue', () => { + test('escape hash sybmbol when it appears at the beginning of a line', () => { + const text1 = '# https://amazon.com/# https://docs.aws.amazon.com/# 6. first link is for amazon. 7. second link documentation.'; + const expectedOutput = '\\# https://amazon.com/# https://docs.aws.amazon.com/# 6. first link is for amazon. 7. second link documentation.'; + expect(escapeHashMarkdown(text1)).toBe(expectedOutput); + }); + + + test('should escape a # in the first word in the input string starts with multiple hash symbols', () => { + const text2 = '### three'; + const expectedOutput = '\\### three'; // jest will added extra \ so actual expectedOutput is '\### three' + expect(escapeHashMarkdown(text2)).toBe(expectedOutput); + }); + + test('should not escape hash symbols that appear in the middle of line', () => { + const text3 = 'In ### between'; + const expectedOutput = 'In ### between'; + expect(escapeHashMarkdown(text3)).toBe(expectedOutput); + }); + }); \ No newline at end of file diff --git a/source/lambda/export/index.js b/source/lambda/export/index.js index 9f837d8a4..e1a075c1c 100644 --- a/source/lambda/export/index.js +++ b/source/lambda/export/index.js @@ -21,48 +21,47 @@ const step = require('./lib/step'); const join = require('./lib/join'); const clean = require('./lib/clean'); +const outputBucket = process.env.OUTPUT_S3_BUCKET; +const step_status_ignore = ['Error', 'Completed', 'Sync Complete', 'Parsing content JSON', 'Creating FAQ'] + exports.step=async function(event,context,cb){ - console.log('step') + console.log('Initiating Export') console.log('Request',JSON.stringify(event,null,2)) - const Bucket=event.Records[0].s3.bucket.name + const inputBucket=event.Records[0].s3.bucket.name const Key=decodeURI(event.Records[0].s3.object.key) - const VersionId=_.get(event,'Records[0].s3.object.versionId') - console.log(Bucket,Key) + const initialVersionId=_.get(event,'Records[0].s3.object.versionId') try { - await waitUntilObjectExists({ - client: s3, - maxWaitTime: 10 - }, {Bucket,Key,VersionId}) - const res = await s3.send(new GetObjectCommand({Bucket,Key,VersionId})) - const readableStream = Buffer.concat(await res.Body.toArray()); - const config = JSON.parse(readableStream); - const step_status_ignore = ['Error', 'Completed', 'Sync Complete', 'Parsing content JSON', 'Creating FAQ'] - if (step_status_ignore.includes(config.status)===false) { - try { - console.log('Config:',JSON.stringify(config,null,2)) - switch(config.status){ - case 'Started': - await start(config); - break - case 'InProgress': - await step(config); - break - case 'Join': - await join(config); - break - case 'Clean': - await clean(config); - break - } - } catch (err) { - console.log(err) - config.status='Error' - config.message=_.get(err,'message',JSON.stringify(err)) - } - await s3.send(new PutObjectCommand({Bucket,Key,Body:JSON.stringify(config)})); - } - } catch (error) { + const startResult = await getStatusAndStartNextStep(inputBucket, Key, initialVersionId, start); + const stepResult = await getStatusAndStartNextStep(outputBucket, Key, startResult.VersionId, step); + const joinResult = await getStatusAndStartNextStep(outputBucket, Key, stepResult.VersionId, join); + await getStatusAndStartNextStep(outputBucket, Key, joinResult.VersionId, clean); + } + catch (error) { console.error("An error occured in S3 operations: ", error) cb(error) } } + +async function getStatusAndStartNextStep(Bucket, Key, VersionId, nextStep) { + await waitUntilObjectExists({ + client: s3, + maxWaitTime: 10 + }, {Bucket,Key,VersionId}) + const res = await s3.send(new GetObjectCommand({Bucket,Key,VersionId})) + const readableStream = Buffer.concat(await res.Body.toArray()); + const config = JSON.parse(readableStream); + if (step_status_ignore.includes(config.status)===false) { + try { + console.log(config.status) + console.log('Config:',JSON.stringify(config,null,2)) + await nextStep(config); + } catch (err) { + console.log(err) + config.status='Error' + config.message=_.get(err,'message',JSON.stringify(err)) + } + const putObjOutput = await s3.send(new PutObjectCommand({Bucket: outputBucket , Key, Body:JSON.stringify(config)})); + console.log('putObjOutput', JSON.stringify(putObjOutput, null, 2)) + return putObjOutput; + } +} diff --git a/source/lambda/export/jest.config.js b/source/lambda/export/jest.config.js index 489a971f5..2a5c8ab99 100644 --- a/source/lambda/export/jest.config.js +++ b/source/lambda/export/jest.config.js @@ -22,4 +22,8 @@ module.exports = { "/../aws-sdk-layer/" ], testTimeout: 200000 -}; \ No newline at end of file +}; + +process.env = Object.assign(process.env, { + OUTPUT_S3_BUCKET: 'contentdesigneroutputbucket' +}); \ No newline at end of file diff --git a/source/lambda/export/kendraSync.js b/source/lambda/export/kendraSync.js index 1ecfceef8..2e096e43d 100644 --- a/source/lambda/export/kendraSync.js +++ b/source/lambda/export/kendraSync.js @@ -115,7 +115,7 @@ exports.performSync = async function (event, context, cb) { async function update_status(bucket, new_stat) { const status_params = { Bucket: bucket, - Key: 'status/qna-kendra-faq.txt' + Key: 'status-export/qna-kendra-faq.txt' }; // NOSONAR TODO: check the return value of the object in case of an error... diff --git a/source/lambda/export/lib/start.js b/source/lambda/export/lib/start.js index 57be4a793..8b50366e8 100644 --- a/source/lambda/export/lib/start.js +++ b/source/lambda/export/lib/start.js @@ -19,6 +19,7 @@ module.exports = function (config) { config.status = 'InProgress'; config.startDate = (new Date()).toString(); config.parts = []; + config.bucket = process.env.OUTPUT_S3_BUCKET; return load(config, { endpoint: process.env.ES_ENDPOINT, diff --git a/source/lambda/export/package-lock.json b/source/lambda/export/package-lock.json index 7a136f73b..599d8aa29 100644 --- a/source/lambda/export/package-lock.json +++ b/source/lambda/export/package-lock.json @@ -1,12 +1,12 @@ { "name": "export", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "export", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "lodash": "^4.17.21" diff --git a/source/lambda/export/package.json b/source/lambda/export/package.json index b13ab41bc..69b05e47c 100644 --- a/source/lambda/export/package.json +++ b/source/lambda/export/package.json @@ -1,6 +1,6 @@ { "name": "export", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot Lambda handling export of QIDs", "main": "index.js", "scripts": { diff --git a/source/lambda/export/test/index.fixtures.js b/source/lambda/export/test/index.fixtures.js index 0554a7ef3..b3268dc3f 100644 --- a/source/lambda/export/test/index.fixtures.js +++ b/source/lambda/export/test/index.fixtures.js @@ -1,4 +1,4 @@ - /********************************************************************************************************************* +/********************************************************************************************************************* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * @@ -10,16 +10,20 @@ * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * * and limitations under the License. * *********************************************************************************************************************/ - - const { GetObjectCommand } = require('@aws-sdk/client-s3'); - const { Readable } = require('stream'); - const { sdkStreamMixin } = require('@smithy/util-stream'); - - function mockStream(config, s3Mock) { - const stream = new Readable(); - stream.push(JSON.stringify(config)); - stream.push(null); - const sdkStream = sdkStreamMixin(stream); - s3Mock.on(GetObjectCommand).resolves({ Body: sdkStream }); - }; - exports.mockStream = mockStream; \ No newline at end of file + +const { GetObjectCommand } = require('@aws-sdk/client-s3'); +const { Readable } = require("stream"); +const { sdkStreamMixin } = require('@smithy/util-stream'); + +function mockStream(config, s3Mock, payload = "") { + const stream = new Readable(); + stream.push(JSON.stringify(config)); + stream.push(null); + const sdkStream = sdkStreamMixin(stream); + if (payload != "") { + s3Mock.on(GetObjectCommand, payload).resolves({ Body: sdkStream }) + } else { + s3Mock.on(GetObjectCommand).resolves({ Body: sdkStream }); + } +}; +exports.mockStream = mockStream; diff --git a/source/lambda/export/test/index.test.js b/source/lambda/export/test/index.test.js index 1fae9a81c..64387eb05 100644 --- a/source/lambda/export/test/index.test.js +++ b/source/lambda/export/test/index.test.js @@ -36,7 +36,7 @@ const event = { name: "exportBucket", }, object: { - key: "status/Export.csv", + key: "status-export/Export.csv", versionId: "tLkWAhY8v2rsaSPWqg2m", } } @@ -44,6 +44,96 @@ const event = { ] }; +function generateConfigAndVersionId(currentStatus) { + const config = { status : currentStatus }; + const versionId = Math.random().toString(36).substring(3,9); + return { config: config, versionId: versionId } +} + +function initializeStartStepMocks() { + const startConfig = generateConfigAndVersionId('Started'); + s3Mock.on(PutObjectCommand, {"Body": "{\"status\":\"Started\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv"}).resolves( + { + '$metadata': { + httpStatusCode: 200, + requestId: '', + extendedRequestId: '', + cfId: undefined, + attempts: 1, + totalRetryDelay: 0 + }, + Expiration: '', + ETag: '""', + ServerSideEncryption: '', + VersionId: startConfig.versionId + }) + mockStream(startConfig.config, s3Mock, {"Bucket": "exportBucket", "Key": "status-export/Export.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}) + return { versionId: startConfig.versionId, config: startConfig.config } +} + +function initializeInProgressStepMocks(startVersionId) { + const stepConfig = generateConfigAndVersionId('InProgress'); + s3Mock.on(PutObjectCommand, {"Body": "{\"status\":\"InProgress\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv"}).resolves( + { + '$metadata': { + httpStatusCode: 200, + requestId: '', + extendedRequestId: '', + cfId: undefined, + attempts: 1, + totalRetryDelay: 0 + }, + Expiration: '', + ETag: '""', + ServerSideEncryption: '', + VersionId: stepConfig.versionId + }) + mockStream(stepConfig.config, s3Mock, {"Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv", "VersionId": startVersionId}); + return { versionId: stepConfig.versionId, config: stepConfig.config } +} + +function initializeJoinStepMocks(inProgressVersionId) { + const joinConfig = generateConfigAndVersionId('Join'); + s3Mock.on(PutObjectCommand, {"Body": "{\"status\":\"Join\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv"}).resolves( + { + '$metadata': { + httpStatusCode: 200, + requestId: '', + extendedRequestId: '', + cfId: undefined, + attempts: 1, + totalRetryDelay: 0 + }, + Expiration: '', + ETag: '""', + ServerSideEncryption: '', + VersionId: joinConfig.versionId + }) + mockStream(joinConfig.config, s3Mock, {"Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv", "VersionId": inProgressVersionId}); + return { versionId: joinConfig.versionId, config: joinConfig.config } +} + +function initializeCleanStepMocks(lexVersionId) { + const cleanConfig = generateConfigAndVersionId('Clean'); + s3Mock.on(PutObjectCommand, {"Body": "{\"status\":\"Clean\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv"}).resolves( + { + '$metadata': { + httpStatusCode: 200, + requestId: '', + extendedRequestId: '', + cfId: undefined, + attempts: 1, + totalRetryDelay: 0 + }, + Expiration: '', + ETag: '""', + ServerSideEncryption: '', + VersionId: cleanConfig.versionId + }) + mockStream(cleanConfig.config, s3Mock, {"Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv", "VersionId": lexVersionId}); + return { versionId: cleanConfig.versionId, config: cleanConfig.config } +} + describe('when calling index function', () => { beforeEach(() => { @@ -55,58 +145,28 @@ describe('when calling index function', () => { jest.clearAllMocks(); }); - it('should call start and update status correctly', async () => { - const config = { status : 'Started' }; - mockStream(config, s3Mock); + it('should call the different steps and update status as expected', async () => { + const startStepInfo = initializeStartStepMocks(); + const inProgressStepInfo = initializeInProgressStepMocks(startStepInfo.versionId); + const joinStepInfo = initializeJoinStepMocks(inProgressStepInfo.versionId); + const cleanStepInfo = initializeCleanStepMocks(joinStepInfo.versionId); await index.step(event, null, jest.fn()); expect(start).toHaveBeenCalledTimes(1); - expect(start).toHaveBeenCalledWith(config); - expect(step).toHaveBeenCalledTimes(0); - expect(join).toHaveBeenCalledTimes(0); - expect(clean).toHaveBeenCalledTimes(0); - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "exportBucket", "Key": "status/Export.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, {"Body": "{\"status\":\"Started\"}", "Bucket": "exportBucket", "Key": "status/Export.csv"}); - }); - - it('should call step and update status correctly', async () => { - const config = { status : 'InProgress' }; - mockStream(config, s3Mock); - await index.step(event, null, jest.fn()); + expect(start).toHaveBeenCalledWith(startStepInfo.config); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(1,GetObjectCommand, {"Bucket": "exportBucket", "Key": "status-export/Export.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(1,PutObjectCommand, {"Body": "{\"status\":\"Started\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv"}); expect(step).toHaveBeenCalledTimes(1); - expect(step).toHaveBeenCalledWith(config); - expect(join).toHaveBeenCalledTimes(0); - expect(clean).toHaveBeenCalledTimes(0); - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "exportBucket", "Key": "status/Export.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, {"Body": "{\"status\":\"InProgress\"}", "Bucket": "exportBucket", "Key": "status/Export.csv"}); - }); - - it('should call join and update status correctly', async () => { - const config = { status : 'Join' }; - mockStream(config, s3Mock); - await index.step(event, null, jest.fn()); + expect(step).toHaveBeenCalledWith(inProgressStepInfo.config); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(2,GetObjectCommand, {"Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv", "VersionId": startStepInfo.versionId}); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(2,PutObjectCommand, {"Body": "{\"status\":\"InProgress\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv"}); expect(join).toHaveBeenCalledTimes(1); - expect(join).toHaveBeenCalledWith(config); - expect(clean).toHaveBeenCalledTimes(0); - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "exportBucket", "Key": "status/Export.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, {"Body": "{\"status\":\"Join\"}", "Bucket": "exportBucket", "Key": "status/Export.csv"}); - }); - - it('should call clean and update status correctly', async () => { - const config = { status : 'Clean' }; - mockStream(config, s3Mock); - await index.step(event, null, jest.fn()); + expect(join).toHaveBeenCalledWith(joinStepInfo.config); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(3,GetObjectCommand, {"Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv", "VersionId": inProgressStepInfo.versionId}); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(3,PutObjectCommand, {"Body": "{\"status\":\"Join\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv"}); expect(clean).toHaveBeenCalledTimes(1); - expect(clean).toHaveBeenCalledWith(config); - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "exportBucket", "Key": "status/Export.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, {"Body": "{\"status\":\"Clean\"}", "Bucket": "exportBucket", "Key": "status/Export.csv"}); + expect(clean).toHaveBeenCalledWith(cleanStepInfo.config); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(4,GetObjectCommand, {"Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv", "VersionId": joinStepInfo.versionId}); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(4,PutObjectCommand, {"Body": "{\"status\":\"Clean\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-export/Export.csv"}); }); it('should handle an error', async () => { diff --git a/source/lambda/export/test/kendraSync.test.js b/source/lambda/export/test/kendraSync.test.js index c1a3e2a18..d9fdf43cd 100644 --- a/source/lambda/export/test/kendraSync.test.js +++ b/source/lambda/export/test/kendraSync.test.js @@ -35,7 +35,7 @@ const event = { name: 'exportBucket' }, object: { - key: 'status/testExport.csv', + key: 'status-export/testExport.csv', versionId: 'tLkWAhY8v2rsaSPWqg2m' } } @@ -110,39 +110,39 @@ describe('when calling performSync function', () => { expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 4); expect(s3Mock).toHaveReceivedNthCommandWith(2, GetObjectCommand, { 'Bucket': 'exportBucket', - 'Key': 'status/testExport.csv', + 'Key': 'status-export/testExport.csv', 'VersionId': 'tLkWAhY8v2rsaSPWqg2m' }); expect(s3Mock).toHaveReceivedNthCommandWith(3, GetObjectCommand, { 'Body': '{"status":"Parsing content JSON"}', 'Bucket': 'testExportBucket', - 'Key': 'status/qna-kendra-faq.txt' + 'Key': 'status-export/qna-kendra-faq.txt' }); expect(s3Mock).toHaveReceivedNthCommandWith(5, GetObjectCommand, { 'Body': '{"status":"Creating FAQ"}', 'Bucket': 'testExportBucket', - 'Key': 'status/qna-kendra-faq.txt' + 'Key': 'status-export/qna-kendra-faq.txt' }); expect(s3Mock).toHaveReceivedNthCommandWith(7, GetObjectCommand, { 'Body': '{"status":"Sync Complete"}', 'Bucket': 'testExportBucket', - 'Key': 'status/qna-kendra-faq.txt' + 'Key': 'status-export/qna-kendra-faq.txt' }); expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 3); expect(s3Mock).toHaveReceivedNthCommandWith(4, PutObjectCommand, { 'Body': '{"status":"Parsing content JSON"}', 'Bucket': 'testExportBucket', - 'Key': 'status/qna-kendra-faq.txt' + 'Key': 'status-export/qna-kendra-faq.txt' }); expect(s3Mock).toHaveReceivedNthCommandWith(6, PutObjectCommand, { 'Body': '{"status":"Creating FAQ"}', 'Bucket': 'testExportBucket', - 'Key': 'status/qna-kendra-faq.txt' + 'Key': 'status-export/qna-kendra-faq.txt' }); expect(s3Mock).toHaveReceivedNthCommandWith(8, PutObjectCommand, { 'Body': '{"status":"Sync Complete"}', 'Bucket': 'testExportBucket', - 'Key': 'status/qna-kendra-faq.txt' + 'Key': 'status-export/qna-kendra-faq.txt' }); }); @@ -193,29 +193,29 @@ describe('when calling performSync function', () => { expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 3); expect(s3Mock).toHaveReceivedNthCommandWith(2, GetObjectCommand, { 'Bucket': 'exportBucket', - 'Key': 'status/testExport.csv', + 'Key': 'status-export/testExport.csv', 'VersionId': 'tLkWAhY8v2rsaSPWqg2m' }); expect(s3Mock).toHaveReceivedNthCommandWith(3, GetObjectCommand, { 'Body': '{"status":"Parsing content JSON"}', 'Bucket': 'testExportBucket', - 'Key': 'status/qna-kendra-faq.txt' + 'Key': 'status-export/qna-kendra-faq.txt' }); expect(s3Mock).toHaveReceivedNthCommandWith(5, GetObjectCommand, { 'Body': '{"status":"Error"}', 'Bucket': 'testExportBucket', - 'Key': 'status/qna-kendra-faq.txt' + 'Key': 'status-export/qna-kendra-faq.txt' }); expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 2); expect(s3Mock).toHaveReceivedNthCommandWith(4, PutObjectCommand, { 'Body': '{"status":"Parsing content JSON"}', 'Bucket': 'testExportBucket', - 'Key': 'status/qna-kendra-faq.txt' + 'Key': 'status-export/qna-kendra-faq.txt' }); expect(s3Mock).toHaveReceivedNthCommandWith(6, PutObjectCommand, { 'Body': '{"status":"Error"}', 'Bucket': 'testExportBucket', - 'Key': 'status/qna-kendra-faq.txt' + 'Key': 'status-export/qna-kendra-faq.txt' }); }); diff --git a/source/lambda/export/test/lib/start.test.js b/source/lambda/export/test/lib/start.test.js index e08e0c719..c1cb99444 100644 --- a/source/lambda/export/test/lib/start.test.js +++ b/source/lambda/export/test/lib/start.test.js @@ -53,6 +53,7 @@ describe('test start function', () => { parts: ['part'] }; const expectedConfig = { + bucket: 'contentdesigneroutputbucket', index: 'index', filter: 'filter', status: 'InProgress', @@ -78,6 +79,7 @@ describe('test start function', () => { parts: ['part'] }; const expectedConfig = { + bucket: 'contentdesigneroutputbucket', index: 'index', filter: null, status: 'InProgress', diff --git a/source/lambda/fulfillment/lib/middleware/1_parse.js b/source/lambda/fulfillment/lib/middleware/1_parse.js index 398dafb15..7ebdba83c 100644 --- a/source/lambda/fulfillment/lib/middleware/1_parse.js +++ b/source/lambda/fulfillment/lib/middleware/1_parse.js @@ -40,9 +40,6 @@ function getClientType(req) { // Try to determine which Lex client is being used based on patterns in the req - best effort attempt. const voiceortext = req._preferredResponseType == 'SSML' ? 'Voice' : 'Text'; - // for LexV1 channels -- check for x-amz-lex:channel-type requestAttribute - // more information on deploying an Amazon Lex V1 Bot on a Messaging Platform: https://docs.aws.amazon.com/lex/latest/dg/example1.html - // for LexV2 channels -- check for x-amz-lex:channels:platform requestAttribute // more information on deploying an Amazon Lex V2 Bot on a Messaging Platform: https://docs.aws.amazon.com/lexv2/latest/dg/deploying-messaging-platform.html @@ -65,7 +62,7 @@ function getClientType(req) { return `LEX.GenesysCloud.${voiceortext}`; } if (/^.*-.*-\d:.*-.*-.*-.*$/.test(_.get(req, '_event.sessionId', _.get(req, '_event.userId')))) { // NOSONAR - javascript:S5852 - input is user controlled and we have a limit on the number of characters - // sessionId (LexV2) or userId (LexV1) pattern to detect lex-web-uithrough use of cognito id as sessionId/userId: e.g. us-east-1:a8e1f7b2-b20d-441c-9698-aff8b519d8d5 + // sessionId (LexV2) pattern to detect lex-web-uithrough use of cognito id as sessionId/userId: e.g. us-east-1:a8e1f7b2-b20d-441c-9698-aff8b519d8d5 // NOSONAR TODO: add another clientType indicator for lex-web-ui? return `LEX.LexWebUI.${voiceortext}`; } diff --git a/source/lambda/fulfillment/lib/middleware/3_query.js b/source/lambda/fulfillment/lib/middleware/3_query.js index ceb1ed5ff..b803d0bdc 100644 --- a/source/lambda/fulfillment/lib/middleware/3_query.js +++ b/source/lambda/fulfillment/lib/middleware/3_query.js @@ -50,10 +50,9 @@ const esquery = require('../../../../../../../../../../opt/lib/query.js'); async function specialtyBotInvocation(req, res) { const specialtyBot = _.get(req, 'session.qnabotcontext.specialtyBot', undefined); - const specialtyBotAlias = _.get(req, 'session.qnabotcontext.specialtyBotAlias', undefined); const specialtyBotChainingConfig = _.get(req, 'session.qnabotcontext.sBChainingConfig', undefined); qnabot.log('Handling specialtyBot'); - const resp = await specialtyBotRouter.routeRequest(req, res, specialtyBot, specialtyBotAlias); + const resp = await specialtyBotRouter.routeRequest(req, res, specialtyBot); qnabot.log(`SpecialtyBotRouterResp: ${JSON.stringify(resp, null, 2)}`); const isSpecialtyBotComplete = _.get(resp, 'res.session.qnabotcontext.specialtyBot', '') === ''; if (isSpecialtyBotComplete) { @@ -176,7 +175,6 @@ async function getPostQuery(queryLambdaArn, req, res, specialtyArn) { const chaining_configuration = _.get(postQuery.res, 'result.conditionalChaining', undefined); const specialtybot_hook = _.get(postQuery.res, 'result.botRouting.specialty_bot', undefined); const specialtybot_name = _.get(postQuery.res, 'result.botRouting.specialty_bot_name', undefined); - const specialtybot_alias = _.get(postQuery.res, 'result.botRouting.specialty_bot_alias', undefined); const specialtybot_attributes_to_merge = _.get(postQuery.res, 'result.botRouting.specialty_bot_session_attributes_to_merge', undefined); const specialtybot_start_up_text = _.get(postQuery.res, 'result.botRouting.specialty_bot_start_up_text', undefined); const specialtybot_attributes_to_receive = _.get(postQuery.res, 'result.botRouting.specialty_bot_session_attributes_to_receive', undefined); @@ -193,7 +191,6 @@ async function getPostQuery(queryLambdaArn, req, res, specialtyArn) { } else if (specialtybot_hook && specialtybot_name) { _.set(postQuery, 'res.session.qnabotcontext.specialtyBot', specialtybot_hook); _.set(postQuery, 'res.session.qnabotcontext.specialtyBotName', specialtybot_name); - _.set(postQuery, 'res.session.qnabotcontext.specialtyBotAlias', specialtybot_alias); _.set(postQuery, 'res.session.qnabotcontext.specialtyBotMergeAttributes', specialtybot_attributes_to_merge); _.set(postQuery, 'res.session.qnabotcontext.sBChainingConfig', chaining_configuration); _.set(postQuery, 'res.session.qnabotcontext.sBAttributesToReceive', specialtybot_attributes_to_receive); @@ -202,7 +199,6 @@ async function getPostQuery(queryLambdaArn, req, res, specialtyArn) { if (specialtybot_start_up_text) { _.set(postQuery, 'req.session.qnabotcontext.specialtyBot', specialtybot_hook); _.set(postQuery, 'req.session.qnabotcontext.specialtyBotName', specialtybot_name); - _.set(postQuery, 'req.session.qnabotcontext.specialtyBotAlias', specialtybot_alias); _.set(postQuery, 'req.session.qnabotcontext.sBMergeAttributes', specialtybot_attributes_to_merge); _.set(postQuery, 'req.session.qnabotcontext.sBChainingConfig', chaining_configuration); _.set(postQuery, 'req.session.qnabotcontext.sBAttributesToReceive', specialtybot_attributes_to_receive); diff --git a/source/lambda/fulfillment/lib/middleware/lex.js b/source/lambda/fulfillment/lib/middleware/lex.js index 5e69bfaa8..3bf6bc11b 100644 --- a/source/lambda/fulfillment/lib/middleware/lex.js +++ b/source/lambda/fulfillment/lib/middleware/lex.js @@ -28,10 +28,6 @@ function isConnectClientVoice(req) { return _.get(req, '_clientType') === 'LEX.AmazonConnect.Voice'; } -function isLexV1(req) { - return req._lexVersion === 'V1'; -} - function isElicitResponse(request, response) { let result = false; const qnabotcontextJSON = _.get(response, 'session.qnabotcontext'); @@ -68,33 +64,6 @@ function trapIgnoreWords(req, transcript) { return trs.trim().length === 0; } -function parseLexV1Event(event) { - const out = { - _type: 'LEX', - _lexVersion: 'V1', - _userId: _.get(event, 'userId', 'Unknown Lex User'), - intentname: _.get(event, 'sessionState.intent.name'), - question: _.get(event, 'inputTranscript').trim(), - session: _.mapValues( - _.get(event, 'sessionAttributes', {}), - (x) => { - try { - return JSON.parse(x); - } catch (e) { - return x; - } - }, - ), - channel: _.get(event, 'requestAttributes.\'x-amz-lex:channel-type\''), - }; - - // check if we pass in a qnabotUserId as a session attribute, if so, use it, else default - out._userId = _.get(event, 'sessionState.sessionAttributes.qnabotUserId', out._userId); - qnabot.log(`QnaBot User Id: ${out._userId}`); - - return out; -} - function parseLexV2Event(event) { const out = { _type: 'LEX', @@ -157,12 +126,7 @@ exports.parse = async function (req) { throw new Error(`Error - inputTranscript contains only words specified in setting CONNECT_IGNORE_WORDS: "${event.inputTranscript}"`); } - let out; - if (!_.get(event, 'sessionId')) { - out = parseLexV1Event(event); - } else { - out = parseLexV2Event(event); - } + const out = parseLexV2Event(event); return out; }; @@ -215,27 +179,6 @@ function isInteractiveMessage(response) { return (isCard(response.card) && (_.get(response.card, 'imageUrl', '').trim() || (_.get(response.card, 'buttons', []).length > 0))); } -function isFallbackIntent(request) { - return (_.get(request, '_event.currentIntent.name', '').toLowerCase()).includes('fallback'); -} - -function buildResponseCardV1(response) { - let responseCardV1 = null; - if (isCard(response.card) && (_.get(response.card, 'imageUrl', '').trim() || (_.get(response.card, 'buttons', []).length > 0))) { - responseCardV1 = { - version: '1', - contentType: 'application/vnd.amazonaws.card.generic', - genericAttachments: [_.pickBy({ - title: _.get(response, 'card.title', 'Title').slice(0, 80), // LexV1 title limit - subTitle: _.get(response.card, 'subTitle')?.slice(0, 80), - imageUrl: _.get(response.card, 'imageUrl'), - buttons: _.get(response.card, 'buttons'), - })], - }; - } - return responseCardV1; -} - function buildImageResponseCardV2(response) { let imageResponseCardV2 = null; if (isCard(response.card) && (_.get(response.card, 'imageUrl', '').trim() || (_.get(response.card, 'buttons', []).length > 0))) { @@ -295,13 +238,6 @@ function buildInteractiveMessageTemplate(response) { return JSON.stringify(template); } -function buildV1InteractiveMessageResponse(request, response) { - return { - contentType: 'CustomPayload', - content: buildInteractiveMessageTemplate(response), - }; -} - function buildV2InteractiveMessageResponse(request, response) { return [ { @@ -311,23 +247,6 @@ function buildV2InteractiveMessageResponse(request, response) { ]; } -function copyResponseCardtoSessionAttribute(response) { - const responseCardV1 = buildResponseCardV1(response); - if (responseCardV1) { - // copy Lex v1 response card to appContext session attribute used by lex-web-ui - // - allows repsonse card display even when using postContent (voice) with Lex (not otherwise supported by Lex) - // - allows Lex limit of 5 buttons to be exceeded when using lex-web-ui - let tmp; - try { - tmp = JSON.parse(_.get(response, 'session.appContext', '{}')); - } catch (e) { - tmp = _.get(response, 'session.appContext', '{}'); - } - tmp.responseCard = responseCardV1; - response.session.appContext = JSON.stringify(tmp); - } - return response; -} function applyLexResponseCardButtonLimits(request, response) { // Lex has limit of max 5 buttons in the responsecard. if we have more than 5, use the first 5 only. @@ -339,11 +258,9 @@ function applyLexResponseCardButtonLimits(request, response) { buttons = _.get(response.card, 'buttons', []); } - // LexV1 and V2 have different limits for button text so enforce them here - // NOTE: LexV1 documentation formally states that 15 is the max limit for - // button title; however, empirical testing shows that 80 characters are supported - const textLimit = isLexV1(request) ? 80 : 50; - const valueLimit = isLexV1(request) ? 1000 : 50; + // LexV2 Limits for button text + const textLimit = 50; + const valueLimit = 50; qnabot.log(`Limiting button text to first ${textLimit} characters to adhere to Lex limits.`); for (let i = 0; i < buttons.length; i++) { response.card.buttons[i].text = response.card.buttons[i].text.slice(0, textLimit); @@ -369,35 +286,6 @@ function applyConnectInteractiveMessageButtonLimits(response) { return response; } -function getV1CloseTemplate(request, response) { - return { - sessionAttributes: _.get(response, 'session', {}), - dialogAction: _.pickBy({ - type: 'Close', - fulfillmentState: 'Fulfilled', - message: { - contentType: response.type, - content: response.message, - }, - }), - }; -} - -function getV1ElicitTemplate(request, response) { - return { - sessionAttributes: _.get(response, 'session', {}), - dialogAction: { - type: 'ElicitSlot', - intentName: _.get(request, '_event.currentIntent.name'), - slotToElicit: 'slot', - message: { - contentType: response.type, - content: response.message, - }, - }, - }; -} - function getV2CloseTemplate(request, response) { return { sessionState: { @@ -457,25 +345,6 @@ function getV2DialogCodeHookResponseTemplate(request, response) { }; } -function assembleLexV1Response(request, response) { - let out = {}; - - if ((isConnectClientChat(request) && isInteractiveMessage(response) && !isFallbackIntent(request))) { - out = getV1ElicitTemplate(request, response); - out.dialogAction.message = buildV1InteractiveMessageResponse(request, response); - } else if (isElicitResponse(request, response) && !isFallbackIntent(request)) { - out = getV1ElicitTemplate(request, response); - } else { - out = getV1CloseTemplate(request, response); - } - - if (!isConnectClient(request)) { - response = applyLexResponseCardButtonLimits(request, response); - out.dialogAction.responseCard = buildResponseCardV1(response); - } - return out; -} - function assembleLexV2Response(request, response) { let out = {}; @@ -511,15 +380,7 @@ exports.assemble = function (request, response) { qnabot.log('filterButtons'); response = filterButtons(response); - qnabot.log('copyResponseCardToSessionAttributes'); - response = copyResponseCardtoSessionAttribute(response); - - let out; - if (isLexV1(request)) { - out = assembleLexV1Response(request, response); - } else { - out = assembleLexV2Response(request, response); - } + const out = assembleLexV2Response(request, response); qnabot.log('Lex response:', JSON.stringify(out, null, 2)); return out; diff --git a/source/lambda/fulfillment/lib/middleware/lexRouter.js b/source/lambda/fulfillment/lib/middleware/lexRouter.js index 0d6f13230..19e1e80c5 100644 --- a/source/lambda/fulfillment/lib/middleware/lexRouter.js +++ b/source/lambda/fulfillment/lib/middleware/lexRouter.js @@ -17,7 +17,6 @@ * Handle response from Lex Bot and update session attributes as needed. */ const _ = require('lodash'); -const { LexRuntimeService: LexRuntime } = require('@aws-sdk/client-lex-runtime-service') const { LexRuntimeV2 } = require('@aws-sdk/client-lex-runtime-v2'); const customSdkConfig = require('sdk-config/customSdkConfig'); const region = process.env.AWS_REGION || 'us-east-1'; @@ -94,25 +93,11 @@ async function translate_res(req, res) { } /** - * Call postText and use promise to return data response. + * Call recognizeText and use promise to return data response. * @param lexClient * @param params * @returns {*} */ -function lexV1ClientRequester(params) { - const lexV1Client = new LexRuntime(customSdkConfig('C001', { apiVersion: '2016-11-28', region })); - return new Promise((resolve, reject) => { - lexV1Client.postText(params, (err, data) => { - if (err) { - qnabot.log(err, err.stack); - reject(`Lex client request error:${err}`); - } else { - qnabot.log(`Lex client response:${JSON.stringify(data, null, 2)}`); - resolve(data); - } - }); - }); -} function lexV2ClientRequester(params) { const lexV2Client = new LexRuntimeV2(customSdkConfig('C002', { region })); return new Promise((resolve, reject) => { @@ -203,46 +188,33 @@ async function handleRequest(req, res, botName, botAlias) { // Resolve bot details from environment, if using simple name for built-in bots const botIdentity = mapFromSimpleName(botName); - // Determine if we using LexV1 or LexV2.. LexV2 bot is identified by "lexv2::BotId/BotAliasId/LocaleId" - let response = {}; - if (botIdentity.toLowerCase().startsWith('lexv2::')) { - // lex v2 response bot - const ids = botIdentity.split('::')[1]; - let [botId, botAliasId, localeId] = ids.split('/'); - localeId = localeId || 'en_US'; - const params = { - botId, - botAliasId, - localeId, - sessionId: tempBotUserID, - text: respText, + const response = {}; + // Lex V2 response bot + const ids = botIdentity.split('::')[1]; + let [botId, botAliasId, localeId] = ids.split('/'); + localeId = localeId || 'en_US'; + const params = { + botId, + botAliasId, + localeId, + sessionId: tempBotUserID, + text: respText, - }; - qnabot.log(`Lex V2 parameters: ${JSON.stringify(params)}`); - const lexv2response = await lexV2ClientRequester(params); - qnabot.log(`Lex V2 response: ${JSON.stringify(lexv2response)}`); - response.message = _.get(lexv2response, 'messages[0].content', ''); - // lex v2 FallbackIntent match means it failed to fill desired slot(s). - if (lexv2response.sessionState.intent.name === 'FallbackIntent' - || lexv2response.sessionState.intent.state === 'Failed') { - response.dialogState = 'Failed'; - } else { - response.dialogState = lexv2response.sessionState.dialogAction.type; - } - const slots = _.get(lexv2response, 'sessionState.intent.slots'); - if (slots) { - response.slots = _.mapValues(slots, (x) => _.get(x, 'value.interpretedValue')); - } + }; + qnabot.log(`Lex V2 parameters: ${JSON.stringify(params)}`); + const lexv2response = await lexV2ClientRequester(params); + qnabot.log(`Lex V2 response: ${JSON.stringify(lexv2response)}`); + response.message = _.get(lexv2response, 'messages[0].content', ''); + // lex v2 FallbackIntent match means it failed to fill desired slot(s). + if (lexv2response.sessionState.intent.name === 'FallbackIntent' + || lexv2response.sessionState.intent.state === 'Failed') { + response.dialogState = 'Failed'; } else { - // lex v1 response bot - const params = { - botAlias, - botName: mapFromSimpleName(botName), - inputText: respText, - userId: tempBotUserID, - }; - qnabot.log(`Lex V1 parameters: ${JSON.stringify(params)}`); - response = await lexV1ClientRequester(params); + response.dialogState = lexv2response.sessionState.dialogAction.type; + } + const slots = _.get(lexv2response, 'sessionState.intent.slots'); + if (slots) { + response.slots = _.mapValues(slots, (x) => _.get(x, 'value.interpretedValue')); } return response; } diff --git a/source/lambda/fulfillment/lib/middleware/specialtyBotRouter.js b/source/lambda/fulfillment/lib/middleware/specialtyBotRouter.js index 1f1decfae..0e184b036 100644 --- a/source/lambda/fulfillment/lib/middleware/specialtyBotRouter.js +++ b/source/lambda/fulfillment/lib/middleware/specialtyBotRouter.js @@ -19,7 +19,6 @@ */ const _ = require('lodash'); const { Lambda } = require('@aws-sdk/client-lambda'); -const { LexRuntimeService: LexRuntime } = require('@aws-sdk/client-lex-runtime-service'); const { LexRuntimeV2 } = require('@aws-sdk/client-lex-runtime-v2'); const customSdkConfig = require('sdk-config/customSdkConfig'); const region = process.env.AWS_REGION || 'us-east-1'; @@ -176,21 +175,6 @@ async function lambdaClientRequester(name, req) { return obj; } -function lexV1ClientRequester(params) { - const lexV1Client = new LexRuntime(customSdkConfig('C014', { apiVersion: '2016-11-28', region })); - return new Promise((resolve, reject) => { - lexV1Client.postText(params, (err, data) => { - if (err) { - qnabot.log(err, err.stack); - reject(`Lex client request error:${err}`); - } else { - qnabot.log(`Lex client response:${JSON.stringify(data, null, 2)}`); - resolve(data); - } - }); - }); -} - function lexV2ClientRequester(params) { const lexV2Client = new LexRuntimeV2(customSdkConfig('C014', { region })); return new Promise((resolve, reject) => { @@ -233,7 +217,7 @@ function mapFromSimpleName(botName) { * @param botAlias * @returns {Promise<*>} */ -async function handleRequest(req, res, botName, botAlias) { +async function handleRequest(req, res, botName) { if (botName.toLowerCase().startsWith('lambda::')) { // target bot is a Lambda Function const lambdaName = botName.split('::')[1]; @@ -250,38 +234,27 @@ async function handleRequest(req, res, botName, botAlias) { tempBotUserID = tempBotUserID.replaceAll(/[^a-zA-Z0-9\-._:]/g,'_'); // NOSONAR - javascript:S5852 - input is user controlled and we have a limit on the number of characters - // Determine if we using LexV1 or LexV2.. LexV2 bot is identified by "lexv2::BotId/BotAliasId/LocaleId" - if (botIdentity.toLowerCase().startsWith('lexv2::')) { - const res = {}; - const ids = botIdentity.split('::')[1]; - let [botId, botAliasId, localeId] = ids.split('/'); - localeId = localeId || 'en_US'; - const params = { - botId, - botAliasId, - localeId, - sessionId: tempBotUserID, - sessionState: { - sessionAttributes: generateMergedAttributes(req), - }, - text: _.get(req, 'question'), - }; - const lexv2response = await processLexV2Response(params, res); - - const slots = _.get(lexv2response, 'sessionState.intent.slots'); - if (slots) { - res.slots = _.mapValues(slots, (x) => _.get(x, 'value.interpretedValue')); - } - return res; - } + // LexV2 bot is identified by "lexv2::BotId/BotAliasId/LocaleId" + const response = {}; + const ids = botIdentity.split('::')[1]; + let [botId, botAliasId, localeId] = ids.split('/'); + localeId = localeId || 'en_US'; const params = { - botAlias, - botName: botIdentity, - inputText: _.get(req, 'question'), - sessionAttributes: generateMergedAttributes(req), - userId: getBotUserId(req), + botId, + botAliasId, + localeId, + sessionId: tempBotUserID, + sessionState: { + sessionAttributes: generateMergedAttributes(req), + }, + text: _.get(req, 'question'), }; - const response = await lexV1ClientRequester(params); + const lexv2response = await processLexV2Response(params, response); + + const slots = _.get(lexv2response, 'sessionState.intent.slots'); + if (slots) { + response.slots = _.mapValues(slots, (x) => _.get(x, 'value.interpretedValue')); + } return response; } @@ -337,7 +310,6 @@ function getDialogState(lexv2response) { function endUseOfSpecialtyBot(req, res, welcomeBackMessage) { delete res.session.qnabotcontext.specialtyBot; delete res.session.qnabotcontext.specialtyBotName; - delete res.session.qnabotcontext.specialtyBotAlias; delete res.session.qnabotcontext.specialtySessionAttributes; delete res.session.qnabotcontext.sBAttributesToReceive; delete res.session.qnabotcontext.sBAttributesToReceiveNamespace; @@ -518,7 +490,7 @@ function getRespCard(botResp) { * @param hook * @returns {Promise<{}>} */ -async function processResponse(req, res, hook, alias) { +async function processResponse(req, res, hook) { qnabot.log(`specialtyBotRouter request: ${JSON.stringify(req, null, 2)}`); qnabot.log(`specialtyBotRouter response: ${JSON.stringify(res, null, 2)}`); @@ -538,7 +510,7 @@ async function processResponse(req, res, hook, alias) { qnabot.log(`returning resp for user requested exit: ${JSON.stringify(resp, null, 2)}`); return resp; } - const botResp = await handleRequest(req, res, hook, alias); + const botResp = await handleRequest(req, res, hook); qnabot.log(`specialty botResp: ${JSON.stringify(botResp, null, 2)}`); if (botResp.message || _.get(botResp, 'dialogState', '') === 'ReadyForFulfillment') { let lexBotIsFulfilled; diff --git a/source/lambda/fulfillment/package-lock.json b/source/lambda/fulfillment/package-lock.json index 1252fe845..3ca1a1324 100644 --- a/source/lambda/fulfillment/package-lock.json +++ b/source/lambda/fulfillment/package-lock.json @@ -1,12 +1,12 @@ { "name": "fulfillment", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fulfillment", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-dynamodb": "^3.511.0", @@ -98,16 +98,16 @@ } }, "node_modules/@aws-sdk/client-dynamodb": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.622.0.tgz", - "integrity": "sha512-rzbxDj0JjWYg/t9JSjTJYp1bphSAZvX/wwHqO7FHxRuCzYTEKB9iAQC/eBrWRDJBbSEoI0PMwa0kR0V7yS+whQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.621.0.tgz", + "integrity": "sha512-aczOoVyufYwBCc/zZKJOP/xwbnojKQJ6Y8O7ZAZnxMPRyZXKXpoAxmlxLfOU6GUzXqzXdvj+Ir3VBd7MWB4KuQ==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-endpoint-discovery": "3.620.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", @@ -119,26 +119,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -318,9 +318,9 @@ } }, "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -444,16 +444,16 @@ } }, "node_modules/@aws-sdk/client-lex-models-v2": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-models-v2/-/client-lex-models-v2-3.622.0.tgz", - "integrity": "sha512-CJW3V05azrjqYVaQnWlaRUzNTRGXj5NuudpIHr3VeJcKIM3XjWeqqewdpJaRNiNyKAOJHhFg0OZqitelHwcRTg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-models-v2/-/client-lex-models-v2-3.621.0.tgz", + "integrity": "sha512-Ypt2JYZLQPJLAsBbx3iX1pMgbGkSsof8rQ4FvcpIZE7MDPeo0M7AKz3X5joIny3DJYk1AjG3xdhYmyZU2VOTkA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -464,26 +464,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -662,9 +662,9 @@ } }, "node_modules/@aws-sdk/client-lex-models-v2/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -788,16 +788,16 @@ } }, "node_modules/@aws-sdk/client-lex-runtime-service": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-runtime-service/-/client-lex-runtime-service-3.622.0.tgz", - "integrity": "sha512-XiMdKqWiIUjpItHfCp1sQEpMzhKnsaFNz/lrxfb+IPiCs8of63gKwpJ1tpi4DeEmuA8384VA4cU3bGAUgrpx5Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-runtime-service/-/client-lex-runtime-service-3.621.0.tgz", + "integrity": "sha512-QAE4OYDKzBucvLnhqoNaGVp8Mm75C/5rqcBdhiRoTpnOUP7DtUZRGVRnTqht9vuzJxqUvqUSUkkmtIfT/Jrl9g==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -808,26 +808,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1006,9 +1006,9 @@ } }, "node_modules/@aws-sdk/client-lex-runtime-service/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -1132,21 +1132,22 @@ } }, "node_modules/@aws-sdk/client-lex-runtime-v2": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-runtime-v2/-/client-lex-runtime-v2-3.622.0.tgz", - "integrity": "sha512-zNc6tyx79TZ7ORSvzDFfVm2SzkcAlx3U6jcwTTbZDv+eMgNelBvYhRowQxgVIQ9briow+0BfnAOmbHEDHD+V5Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-runtime-v2/-/client-lex-runtime-v2-3.621.0.tgz", + "integrity": "sha512-UFjOmdBlu3lbTjd36VRbzInkhRyFwW3yeQM+y0O2qZY/8wHKaYkHsqNphSnpE/KAL/QusbczVKdEtpbzt2np9A==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/eventstream-handler-node": "3.620.0", "@aws-sdk/middleware-eventstream": "3.620.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-signing": "3.620.0", "@aws-sdk/middleware-user-agent": "3.620.0", "@aws-sdk/region-config-resolver": "3.614.0", "@aws-sdk/types": "3.609.0", @@ -1154,7 +1155,7 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/eventstream-serde-browser": "^3.0.5", "@smithy/eventstream-serde-config-resolver": "^3.0.3", "@smithy/eventstream-serde-node": "^3.0.4", @@ -1163,22 +1164,21 @@ "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", "@smithy/util-stream": "^3.1.3", "@smithy/util-utf8": "^3.0.0", @@ -1355,9 +1355,9 @@ } }, "node_modules/@aws-sdk/client-lex-runtime-v2/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -1481,13 +1481,13 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.622.0.tgz", - "integrity": "sha512-DJwUqVR/O2lImbktUHOpaQ8XElNBx3JmWzTT2USg6jh3ErgG1CS6LIV+VUlgtxGl+tFN/G6AcAV8SdnnGydB8Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", + "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", + "@aws-sdk/core": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1498,26 +1498,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1529,14 +1529,14 @@ } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.622.0.tgz", - "integrity": "sha512-dwWDfN+S98npeY77Ugyv8VIHKRHN+n/70PWE4EgolcjaMrTINjvUh9a/SypFEs5JmBOAeCQt8S2QpM3Wvzp+pQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", + "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1547,26 +1547,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1577,7 +1577,7 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/abort-controller": { @@ -1747,9 +1747,9 @@ } }, "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -2039,9 +2039,9 @@ } }, "node_modules/@aws-sdk/client-sso/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -2165,15 +2165,15 @@ } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.622.0.tgz", - "integrity": "sha512-Yqtdf/wn3lcFVS42tR+zbz4HLyWxSmztjVW9L/yeMlvS7uza5nSkWqP/7ca+RxZnXLyrnA4jJtSHqykcErlhyg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", + "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -2184,26 +2184,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -2381,9 +2381,9 @@ } }, "node_modules/@aws-sdk/client-sts/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -2507,15 +2507,15 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.622.0.tgz", - "integrity": "sha512-q1Ct2AjPxGtQBKtDpqm1umu3f4cuWMnEHTuDa6zjjaj+Aq/C6yxLgZJo9SlcU0tMl8rUCN7oFonszfTtp4Y0MA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", + "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", "dependencies": { - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "fast-xml-parser": "4.4.1", @@ -2692,9 +2692,9 @@ } }, "node_modules/@aws-sdk/core/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -2855,16 +2855,16 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.622.0.tgz", - "integrity": "sha512-VUHbr24Oll1RK3WR8XLUugLpgK9ZuxEm/NVeVqyFts1Ck9gsKpRg1x4eH7L7tW3SJ4TDEQNMbD7/7J+eoL2svg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", + "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/property-provider": "^3.1.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-stream": "^3.1.3", "tslib": "^2.6.2" @@ -3040,9 +3040,9 @@ } }, "node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -3166,14 +3166,14 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.622.0.tgz", - "integrity": "sha512-cD/6O9jOfzQyo8oyAbTKnyRO89BIMSTzwaN4NxGySC6pYVTqxNSWdRwaqg/vKbwJpjbPGGYYXpXEW11kop7dlg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", + "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -3186,7 +3186,7 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/credential-provider-ini/node_modules/@smithy/property-provider": { @@ -3225,15 +3225,15 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.622.0.tgz", - "integrity": "sha512-keldwz4Q/6TYc37JH6m43HumN7Vi+R0AuGuHn5tBV40Vi7IiqEzjpiE+yvsHIN+duUheFLL3j/o0H32jb+14DQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", + "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -3332,11 +3332,11 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.622.0.tgz", - "integrity": "sha512-zrSoBVM2JlwvkBtrcUd4J/9CrG+T+hUy9r6jwo5gonFIN3QkneR/pqpbUn/n32Zy3zlzCo2VfB31g7MjG7kJmg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", + "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", "dependencies": { - "@aws-sdk/client-sso": "3.622.0", + "@aws-sdk/client-sso": "3.621.0", "@aws-sdk/token-providers": "3.614.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -3689,6 +3689,70 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.620.0.tgz", + "integrity": "sha512-gxI7rubiaanUXaLfJ4NybERa9MGPNg2Ycl/OqANsozrBnR3Pw8vqy3EuVImQOyn2pJ2IFvl8ZPoSMHf4pX56FQ==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing/node_modules/@smithy/property-provider": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing/node_modules/@smithy/protocol-http": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", + "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing/node_modules/@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing/node_modules/@smithy/util-middleware": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/middleware-user-agent": { "version": "3.620.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.620.0.tgz", @@ -5168,15 +5232,15 @@ } }, "node_modules/@smithy/core": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.2.tgz", - "integrity": "sha512-in5wwt6chDBcUv1Lw1+QzZxN9fBffi+qOixfb65yK4sDuKG7zAUO9HAFqmVzsZM3N+3tTyvZjtnDXePpvp007Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.1.tgz", + "integrity": "sha512-BC7VMXx/1BCmRPCVzzn4HGWAtsrb7/0758EtwOGFJQrlSwJBEjCcDLNZLFoL/68JexYa2s+KmgL/UfmXdG6v1w==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "tslib": "^2.6.2" @@ -5352,9 +5416,9 @@ } }, "node_modules/@smithy/core/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -5848,14 +5912,14 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.14.tgz", - "integrity": "sha512-7ZaWZJOjUxa5hgmuMspyt8v/zVsh0GXYuF7OvCmdcbVa/xbnKQoYC+uYKunAqRGTkxjOyuOCw9rmFUFOqqC0eQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/service-error-classification": "^3.0.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -6033,9 +6097,9 @@ } }, "node_modules/@smithy/middleware-retry/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -6496,12 +6560,12 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.14.tgz", - "integrity": "sha512-0iwTgKKmAIf+vFLV8fji21Jb2px11ktKVxbX6LIDPAUJyWQqGqBVfwba7xwa1f2FZUoolYQgLvxQEpJycXuQ5w==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", "dependencies": { "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -6677,9 +6741,9 @@ } }, "node_modules/@smithy/util-defaults-mode-browser/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -6803,15 +6867,15 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.14.tgz", - "integrity": "sha512-e9uQarJKfXApkTMMruIdxHprhcXivH1flYCe8JRDTzkkLx8dA3V5J8GZlST9yfDiRWkJpZJlUXGN9Rc9Ade3OQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", "dependencies": { "@smithy/config-resolver": "^3.0.5", "@smithy/credential-provider-imds": "^3.2.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, @@ -6986,9 +7050,9 @@ } }, "node_modules/@smithy/util-defaults-mode-node/node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", diff --git a/source/lambda/fulfillment/package.json b/source/lambda/fulfillment/package.json index 3513c4b10..7b69d3d94 100644 --- a/source/lambda/fulfillment/package.json +++ b/source/lambda/fulfillment/package.json @@ -1,6 +1,6 @@ { "name": "fulfillment", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot Lambda handling fulfillment of user requests", "main": "handler.js", "scripts": { diff --git a/source/lambda/fulfillment/test/lib/middleware/1_parse.fixtures.js b/source/lambda/fulfillment/test/lib/middleware/1_parse.fixtures.js index 98ea008f4..efd793487 100644 --- a/source/lambda/fulfillment/test/lib/middleware/1_parse.fixtures.js +++ b/source/lambda/fulfillment/test/lib/middleware/1_parse.fixtures.js @@ -17,7 +17,15 @@ exports.createRequestObject = function (question, outputDialogMode, version, eve "_event": { "inputTranscript": question, "outputDialogMode": outputDialogMode, - "userId": "mocked_user_id" + "userId": "mocked_user_id", + "sessionState": { + "intent": { + "name": "mock-name" + } + }, + "request": { + "locale": "mock-locale" + } }, "_setting": { "PROTECTED_UTTERANCES": "Thumbs up, Thumbs down" @@ -25,7 +33,7 @@ exports.createRequestObject = function (question, outputDialogMode, version, eve "question": question, }; if (version) { - request._event.version= version; + request._event.version = version; } if(eventRequest) { request._event.request = eventRequest; diff --git a/source/lambda/fulfillment/test/lib/middleware/1_parse.test.js b/source/lambda/fulfillment/test/lib/middleware/1_parse.test.js index b78d3b292..38e19773b 100644 --- a/source/lambda/fulfillment/test/lib/middleware/1_parse.test.js +++ b/source/lambda/fulfillment/test/lib/middleware/1_parse.test.js @@ -38,7 +38,7 @@ describe('parse function with Lex event', () => { settings.get_parameter.mockReturnValue('https://cognito-idp.us-east-1.amazonaws.com/us-east-1dsfsfjl'); }); - test('when parsing request with sentimemt & multilang support disabled', async () => { + test('when parsing request with sentiment & multilang support disabled', async () => { settings.getSettings.mockReturnValue(parseFixtures.defaultSettings); const res = {}; const parseResponse = await parse( diff --git a/source/lambda/fulfillment/test/lib/middleware/3_query.test.js b/source/lambda/fulfillment/test/lib/middleware/3_query.test.js index e72e335bd..f79281065 100644 --- a/source/lambda/fulfillment/test/lib/middleware/3_query.test.js +++ b/source/lambda/fulfillment/test/lib/middleware/3_query.test.js @@ -117,7 +117,6 @@ describe('when calling query function', () => { const expectedResponse = queryFixtures.createMockRoutingResponse("specialtyBot", ""); expectedResponse.res.session.qnabotcontext.specialtyBot = "mock_specialty_bot"; expectedResponse.res.session.qnabotcontext.specialtyBotName = "mock_specialty_bot_name"; - expectedResponse.res.session.qnabotcontext.specialtyBotAlias = "mock_specialty_bot_alias"; expect(util.invokeLambda).toHaveBeenCalled(); expect(response).toEqual(expectedResponse); }); diff --git a/source/lambda/fulfillment/test/lib/middleware/lex.fixtures.js b/source/lambda/fulfillment/test/lib/middleware/lex.fixtures.js index 557852c87..c06ef4390 100644 --- a/source/lambda/fulfillment/test/lib/middleware/lex.fixtures.js +++ b/source/lambda/fulfillment/test/lib/middleware/lex.fixtures.js @@ -54,10 +54,6 @@ exports.createRequestObject = function (question, clientType, lexVersion, curren "question": question }; - - if (lexVersion === "V1") { - request._event.sessionAttributes = { "idtokenjwt": "" } - } if (lexVersion === "V2") { request._event.invocationSource = "FulfillmentCodeHook"; request._event.sessionState.sessionAttributes = { "idtokenjwt": "" }; diff --git a/source/lambda/fulfillment/test/lib/middleware/lex.test.js b/source/lambda/fulfillment/test/lib/middleware/lex.test.js index b36b94297..6b993231d 100644 --- a/source/lambda/fulfillment/test/lib/middleware/lex.test.js +++ b/source/lambda/fulfillment/test/lib/middleware/lex.test.js @@ -38,36 +38,6 @@ describe('when calling parse function', () => { rejects.toThrowError('Error - inputTranscript contains only words specified in setting CONNECT_IGNORE_WORDS: "MockIgnore1 MockIgnore2"'); }); - test('should able to parse Lexv1 request successfully', async () => { - let parsedRequest = await lex.parse(lexFixtures.createRequestObject("What is QnABot", "LEX.LexWebUI.Text")); - expect(parsedRequest.question).toEqual("What is QnABot"); - expect(parsedRequest._lexVersion).toEqual("V1"); - expect(parsedRequest._userId).toEqual("mock_user_id"); - expect(parsedRequest.intentname).toEqual("mockIntent"); - - //Request containing some ignore words - const mockRequest = lexFixtures.createRequestObject("MockIgnore1 MockIgnore2", "LEX.AmazonConnect.Text", "V1"); - mockRequest._settings.CONNECT_IGNORE_WORDS = "MockIgnore1" - parsedRequest = await lex.parse(mockRequest); - expect(parsedRequest.question).toEqual("MockIgnore1 MockIgnore2"); - expect(parsedRequest._lexVersion).toEqual("V1"); - }); - - test('should able to parse Lexv1 request with sessionAttributes successfully', async () => { - let parsedRequest = await lex.parse(lexFixtures.createRequestObject("What is QnABot", "LEX.LexWebUI.Text", "V1")); - expect(parsedRequest.question).toEqual("What is QnABot"); - expect(parsedRequest._lexVersion).toEqual("V1"); - expect(parsedRequest._userId).toEqual("mock_user_id"); - expect(parsedRequest.intentname).toEqual("mockIntent"); - - const mockRequest = lexFixtures.createRequestObject("What is QnABot", "LEX.LexWebUI.Text", "V1"); - mockRequest._event.sessionAttributes = { "mockField": "{\"key1\": \"val1\" }" }; - parsedRequest = await lex.parse(mockRequest); - expect(parsedRequest.question).toEqual("What is QnABot"); - expect(parsedRequest._lexVersion).toEqual("V1"); - expect(parsedRequest.session).toEqual({ "mockField": { "key1": "val1" } }); - }); - test('should able to parse Lexv2 request successfully', async () => { let parsedRequest = await lex.parse(lexFixtures.createRequestObject("What is QnABot", "LEX.LexWebUI.Text", "V2")); expect(parsedRequest.question).toEqual("What is QnABot"); @@ -128,75 +98,6 @@ describe('when calling assemble function', () => { jest.clearAllMocks(); }); - // LexV1 Tests - test('should be able to assemble Lexv1 response successfully', () => { - const assembledResponse = lex.assemble(lexFixtures.createRequestObject("What is QnABot", "LEX.LexWebUI.Text", "V1"), - lexFixtures.createResponseObject()); - expect(assembledResponse.dialogAction.type).toEqual("Close"); - expect(assembledResponse.dialogAction.fulfillmentState).toEqual("Fulfilled"); - expect(assembledResponse.dialogAction.message.content).toEqual("The Q and A Bot uses Amazon Lex and Alexa to provide a natural language interface for your FAQ knowledge base, so your users can just ask a question and get a quick and relevant answer."); - - }); - - test('should be able to assemble Lexv1 with _clientType as LEX.Slack.Text', () => { - let assembledResponse = lex.assemble(lexFixtures.createRequestObject("What is QnABot", "LEX.Slack.Text", "V1"), - lexFixtures.createResponseObject()); - expect(assembledResponse.dialogAction.type).toEqual("Close"); - expect(assembledResponse.dialogAction.fulfillmentState).toEqual("Fulfilled"); - expect(assembledResponse.dialogAction.message.content).toEqual("*QnaBot*\n\nThe Q and A Bot uses and to provide a natural language interface for your FAQ knowledge base. Now your users can just ask a ​_question_​ and get a quick and relevant ​_answer_​.\n"); - - //with no markdown text - const mockResponse = lexFixtures.createResponseObject(); - mockResponse.result.alt.markdown = ""; - assembledResponse = lex.assemble(lexFixtures.createRequestObject("What is QnABot", "LEX.Slack.Text", "V1"), - mockResponse); - expect(assembledResponse.dialogAction.message.content).toEqual("The Q and A Bot uses Amazon Lex and Alexa to provide a natural language interface for your FAQ knowledge base, so your users can just ask a question and get a quick and relevant answer."); - }); - - - test('LexV1 verify copyResponseCardtoSessionAttribute', () => { - const mockResponse = lexFixtures.createResponseObject(true); - mockResponse.card.buttons = [{ "text": "mockText", "value": "mockValue" }, { "text": "", "value": "" }]; - const assembledResponse = lex.assemble(lexFixtures.createRequestObject("What is QnABot", "LEX.LexWebUI.Text", "V1"), - mockResponse); - expect(assembledResponse.dialogAction.fulfillmentState).toEqual("Fulfilled"); - expect(assembledResponse.dialogAction.message.content).toEqual("The Q and A Bot uses Amazon Lex and Alexa to provide a natural language interface for your FAQ knowledge base, so your users can just ask a question and get a quick and relevant answer."); - expect(assembledResponse.dialogAction.responseCard).toEqual({ - "version": "1", - "contentType": "application/vnd.amazonaws.card.generic", - "genericAttachments": [ - { - "title": "mock_title", "buttons": [{ "text": "mockText", "value": "mockValue" }] - } - ] - }); - }); - - test('verify LexV1 buildV1InteractiveMessageResponse', () => { - const assembledResponse = lex.assemble(lexFixtures.createRequestObject("What is QnABot", "LEX.AmazonConnect.Text", "V1", "testIntent"), - lexFixtures.createResponseObject(true)); - expect(assembledResponse.dialogAction.type).toEqual("ElicitSlot"); - expect(assembledResponse.dialogAction.intentName).toEqual("testIntent"); - expect(assembledResponse.dialogAction.message.content).toEqual('{\"templateType\":\"ListPicker\",\"version\":\"1.0\",\"data\":{\"content\":{\"title\":\"The Q and A Bot uses Amazon Lex and Alexa to provide a natural language interface for your FAQ knowledge base, so your users can just ask a question and get a quick and relevant answer.\",\"elements\":[{\"title\":\"mockText\"}],\"subtitle\":\"mock_title\"}}}'); - }); - - test('verify LexV1 elicit Response', () => { - let mockResponse = lexFixtures.createResponseObject(); - mockResponse.session.qnabotcontext = "{\"elicitResponse\": {\"responsebot\": \"mock_response_bot\", \"responsetext\": \"mock_response_text\"}}" - let assembledResponse = lex.assemble(lexFixtures.createRequestObject("What is QnABot", "LEX.LexWebUI.Text", "V1", "testIntent"), - mockResponse); - expect(assembledResponse.dialogAction.type).toEqual("ElicitSlot"); - expect(assembledResponse.dialogAction.intentName).toEqual("testIntent"); - expect(assembledResponse.dialogAction.message.content).toEqual('The Q and A Bot uses Amazon Lex and Alexa to provide a natural language interface for your FAQ knowledge base, so your users can just ask a question and get a quick and relevant answer.'); - - mockResponse.session.qnabotcontext = "{\"specialtyBot\": \"testBot\"}" - assembledResponse = lex.assemble(lexFixtures.createRequestObject("What is QnABot", "LEX.LexWebUI.Text", "V1", "testIntent"), - mockResponse); - expect(assembledResponse.dialogAction.type).toEqual("ElicitSlot"); - expect(assembledResponse.dialogAction.intentName).toEqual("testIntent"); - expect(assembledResponse.dialogAction.message.content).toEqual('The Q and A Bot uses Amazon Lex and Alexa to provide a natural language interface for your FAQ knowledge base, so your users can just ask a question and get a quick and relevant answer.'); - }); - // LexV2 Tests test('should be able to assemble Lexv2 response successfully', () => { const assembledResponse = lex.assemble(lexFixtures.createRequestObject("What is QnABot", "LEX.LexWebUI.Text", "V2"), @@ -326,8 +227,6 @@ describe('when calling assemble function', () => { }); }); - - test('verify LexV2 ImageResponseCard response', () => { const mockRequest = lexFixtures.createRequestObject("What is QnABot", "LEX.LexWebUI.Text", "V2"); const mockResponse = lexFixtures.createResponseObject(); diff --git a/source/lambda/fulfillment/test/lib/middleware/lexRouter.fixtures.js b/source/lambda/fulfillment/test/lib/middleware/lexRouter.fixtures.js index 6c71999cd..beafa6dd2 100644 --- a/source/lambda/fulfillment/test/lib/middleware/lexRouter.fixtures.js +++ b/source/lambda/fulfillment/test/lib/middleware/lexRouter.fixtures.js @@ -178,19 +178,6 @@ exports.createResponseObject = function (message) { return response; }; -exports.getLexV1Response = function (dialogState, message) { - const response = { - "botVersion": "live", - "dialogState": dialogState, - "intentName": "mockIntent", - "message": message ? message : "Mock Response", - "sentimentResponse": { - "sentimentLabel": "mockLabel", - } - } - return response; -}; - exports.getLexV2Response = function (dialogState, message, intentName, state) { return { "botVersion": "live", diff --git a/source/lambda/fulfillment/test/lib/middleware/lexRouter.test.js b/source/lambda/fulfillment/test/lib/middleware/lexRouter.test.js index a967af8f9..82329c155 100644 --- a/source/lambda/fulfillment/test/lib/middleware/lexRouter.test.js +++ b/source/lambda/fulfillment/test/lib/middleware/lexRouter.test.js @@ -13,7 +13,6 @@ const lexRouter = require('../../../lib/middleware/lexRouter'); const _ = require('lodash'); const lexRouterFixtures = require('./lexRouter.fixtures') -const { LexRuntimeService: LexRuntime } = require('@aws-sdk/client-lex-runtime-service') const { LexRuntimeV2 } = require('@aws-sdk/client-lex-runtime-v2'); const multilanguage = require('../../../lib/middleware/multilanguage'); jest.mock('../../../lib/middleware/multilanguage'); @@ -55,152 +54,6 @@ describe('when calling elicitResponse function', () => { expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("Fulfilled"); }); - test('verify response when LexV1 Bot responds with Fulfilled dialogState', async () => { - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(null, lexRouterFixtures.getLexV1Response("Fulfilled")); - }); - const response = await lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("What is QnABot"), - lexRouterFixtures.createResponseObject(), "mockBotName"); - expect(response.res.session.qnabot_gotanswer).toBe(true); - expect(response.res.message).toBe("Mock Response"); - expect(response.res.plainMessage).toBe("Mock Response"); - expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("Fulfilled"); - }); - - test('verify response call translate when Native Language is not the same', async () => { - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(null, lexRouterFixtures.getLexV1Response("Fulfilled")); - }); - const response = await lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("Que es QnABot", "", "Spanish"), - lexRouterFixtures.createResponseObject(), "mockBotName"); - expect(response.res.session.qnabot_gotanswer).toBe(true); - expect(response.res.message).toBe("Mock Response"); - expect(response.res.plainMessage).toBe("Mock Response"); - expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("Fulfilled"); - }); - - test('verify response call translate when Native Language is not the same with Speak tags', async () => { - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(null, lexRouterFixtures.getLexV1Response("Fulfilled", "AWS QnA Bot is great. I can speak very fast. I can say tomato and tomato. Visit docs.aws.amazon.com/polly/latest/dg/supportedtags for more information.")); - }); - const response = await lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("Que es QnABot", "", "Spanish"), - lexRouterFixtures.createResponseObject("The Q and A Bot uses Amazon Lex"), "mockBotName"); - expect(response.res.session.qnabot_gotanswer).toBe(true); - expect(response.res.message).toBe("AWS QnA Bot is great. I can speak very fast. I can say tomato and tomato. Visit docs.aws.amazon.com/polly/latest/dg/supportedtags for more information."); - expect(response.res.plainMessage).toBe("AWS QnA Bot is great. I can speak very fast. I can say tomato and tomato. Visit docs.aws.amazon.com/polly/latest/dg/supportedtags for more information."); - expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("Fulfilled"); - }); - - test('verify response when LexV1 Bot responds with default dialogState', async () => { - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(null, lexRouterFixtures.getLexV1Response("default")); - }); - let response = await lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("What is QnABot"), - lexRouterFixtures.createResponseObject(), "mockBotName"); - expect(response.res.session.qnabot_gotanswer).toBe(true); - expect(response.res.message).toBe("Mock Response"); - expect(response.res.plainMessage).toBe("Mock Response"); - expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("default"); - - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - const mockResponse = lexRouterFixtures.getLexV1Response("default"); - mockResponse.message = null; - callback(null, mockResponse); - }); - response = await lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("What is QnABot"), - lexRouterFixtures.createResponseObject(), "mockBotName"); - expect(response.res.message).toBe("Please try again."); - expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("default"); - }); - - test('Error from LexV1 request', async () => { - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(new Error("Mock Error"), null); - }); - await expect(lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("What is QnABot"), - lexRouterFixtures.createResponseObject(), "mockBotName")).rejects.toEqual('Lex client request error:Error: Mock Error'); - }); - - test('verify response when LexV1 Bot responds with ElicitIntent dialogState', async () => { - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(null, lexRouterFixtures.getLexV1Response("ElicitIntent")); - }); - let response = await lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("What is QnABot"), - lexRouterFixtures.createResponseObject(), "mockBotName"); - expect(response.res.session.qnabot_gotanswer).toBe(true); - expect(response.res.message).toBe("Mock Response"); - expect(response.res.plainMessage).toBe("Mock Response"); - expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("ElicitIntent"); - - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(null, lexRouterFixtures.getLexV1Response("ElicitSlot")); - }); - response = await lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("What is QnABot"), - lexRouterFixtures.createResponseObject(), "mockBotName"); - expect(response.res.message).toBe("Mock Response"); - expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("ElicitSlot"); - }); - - test('verify response when LexV1 Bot responds with ConfirmIntent dialogState', async () => { - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(null, lexRouterFixtures.getLexV1Response("ConfirmIntent")); - }); - const response = await lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("What is QnABot"), - lexRouterFixtures.createResponseObject(), "mockBotName"); - expect(response.res.session.qnabot_gotanswer).toBe(true); - expect(response.res.message).toBe("Mock Response"); - expect(response.res.plainMessage).toBe("Mock Response"); - expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("ConfirmIntent"); - expect(response.res.card).toBeDefined(); - }); - - test('verify response when LexV1 Bot responds with ConfirmIntent dialogState & ssml message type', async () => { - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(null, lexRouterFixtures.getLexV1Response("ConfirmIntent", "Mock Response")); - }); - const response = await lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("What is QnABot", "SSML"), - lexRouterFixtures.createResponseObject(), "mockBotName"); - expect(response.res.session.qnabot_gotanswer).toBe(true); - expect(response.res.message).toBe("Mock Response"); - expect(response.res.plainMessage).toBe("Mock Response"); - expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("ConfirmIntent"); - expect(response.res.card).toBeDefined(); - }); - - test('verify response when LexV1 Bot responds with Failed dialogState', async () => { - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(null, lexRouterFixtures.getLexV1Response("Failed", "Mock Response")); - }); - let response = await lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("What is QnABot", "SSML"), - lexRouterFixtures.createResponseObject(), "mockBotName"); - expect(response.res.session.qnabot_gotanswer).toBe(true); - expect(response.res.message).toBe("Please try again."); - expect(response.res.plainMessage).toBe("Please try again."); - expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("ErrorHandling"); - - const mockResponse = lexRouterFixtures.createResponseObject(); - mockResponse.session.qnabotcontext.elicitResponse = { "loopCount": 6 }; - console.log(`mockResponse :: ${JSON.stringify(mockResponse)}`); - response = await lexRouter.elicitResponse(lexRouterFixtures.createRequestObject("What is QnABot", "SSML"), - mockResponse, "mockBotName"); - expect(response.res.session.qnabot_gotanswer).toBe(true); - expect(response.res.message).toBe("Your response was not understood. Please start again."); - expect(response.res.plainMessage).toBe("Your response was not understood. Please start again."); - expect(response.res.session.qnabotcontext.elicitResponse.progress).toBe("Failed"); - }); - - test('verify response when LexV2 Bot responds with Fulfilled dialogState', async () => { jest.spyOn(LexRuntimeV2.prototype, 'recognizeText') .mockImplementation((request, callback) => { diff --git a/source/lambda/fulfillment/test/lib/middleware/specialtyBotRouter.fixtures.js b/source/lambda/fulfillment/test/lib/middleware/specialtyBotRouter.fixtures.js index 3e1bdfc8e..160e3a3f5 100644 --- a/source/lambda/fulfillment/test/lib/middleware/specialtyBotRouter.fixtures.js +++ b/source/lambda/fulfillment/test/lib/middleware/specialtyBotRouter.fixtures.js @@ -189,23 +189,6 @@ exports.createResponseObject = function (message) { return response; }; -exports.getLexV1Response = function (dialogState, message) { - const response = { - "botVersion": "live", - "dialogState": dialogState, - "intentName": "mockIntent", - "message": message ? message : "Mock Response", - "sentimentResponse": { - "sentimentLabel": "mockLabel", - }, - "sessionAttributes": [], - "slots": { - "testSlot": {"shape":"Scalar", "value": {"originalValue": "Test Value"}} - } - } - return response; -}; - exports.getLexV2Response = function (dialogState, message, intentName, slots) { const response = { "sessionState": { diff --git a/source/lambda/fulfillment/test/lib/middleware/specialtyBotRouter.test.js b/source/lambda/fulfillment/test/lib/middleware/specialtyBotRouter.test.js index 9c8c28c65..f7151dcd3 100644 --- a/source/lambda/fulfillment/test/lib/middleware/specialtyBotRouter.test.js +++ b/source/lambda/fulfillment/test/lib/middleware/specialtyBotRouter.test.js @@ -14,7 +14,6 @@ const specialtyBotRouter = require('../../../lib/middleware/specialtyBotRouter') const _ = require('lodash'); const botRouterFixtures = require('./specialtyBotRouter.fixtures') const awsMock = require('aws-sdk-client-mock'); -const { LexRuntimeService: LexRuntime } = require('@aws-sdk/client-lex-runtime-service') const { LexRuntimeV2 } = require('@aws-sdk/client-lex-runtime-v2'); const { Lambda, InvokeCommand } = require('@aws-sdk/client-lambda'); const multilanguage = require('../../../lib/middleware/multilanguage'); @@ -69,143 +68,6 @@ describe('when calling routeRequest function with Lambda as target or with exit }); -describe('when calling routeRequest function with LexV1 as target', () => { - afterEach(() => { - jest.clearAllMocks(); - }); - - test('when using Lexv1 Bot & bot returns response with dialogState ReadyForFulfillment', async () => { - let requestParams; - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - requestParams = request; - callback(null, botRouterFixtures.getLexV1Response("ReadyForFulfillment", "Test Message")); - }); - const response = await specialtyBotRouter.routeRequest(botRouterFixtures.createRequestObject("What is QnABot"), - botRouterFixtures.createResponseObject(), "test_bot", null); - expect(response.res.session.qnabotcontext.specialtyBot).not.toBeDefined(); - expect(response.res.message).toEqual('{\n "testSlot": {\n "shape": "Scalar",\n "value": {\n "originalValue": "Test Value"\n }\n }\n} Welcome back to QnABot.'); - expect(requestParams.sessionAttributes).toEqual({ "myAttribute": "test" }); - }); - - test('should not call translate when ENABLE_MULTI_LANGUAGE_SUPPORT is disabled', async () => { - let requestParams; - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - requestParams = request; - callback(null, botRouterFixtures.getLexV1Response("ReadyForFulfillment", "Test Message.")); - }); - const mockRequest = botRouterFixtures.createRequestObject("What is QnABot"); - mockRequest._settings.ENABLE_MULTI_LANGUAGE_SUPPORT = false; - const response = await specialtyBotRouter.routeRequest(mockRequest, - botRouterFixtures.createResponseObject(), "test_bot", null); - expect(response.res.session.qnabotcontext.specialtyBot).not.toBeDefined(); - expect(response.res.message).toEqual('{\n "testSlot": {\n "shape": "Scalar",\n "value": {\n "originalValue": "Test Value"\n }\n }\n} Welcome back to QnABot.'); - expect(requestParams.sessionAttributes).toEqual({ "myAttribute": "test" }); - expect(translateSpy).toBeCalledTimes(0); - }); - - test('should translate if Native Language does not match', async () => { - let requestParams; - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - requestParams = request; - callback(null, botRouterFixtures.getLexV1Response("ReadyForFulfillment", "Test Message.")); - }); - const mockRequest = botRouterFixtures.createRequestObject("Que es QnABot"); - mockRequest._settings.ENABLE_MULTI_LANGUAGE_SUPPORT = true; - mockRequest._settings.NATIVE_LANGUAGE = 'Spanish'; - const response = await specialtyBotRouter.routeRequest(mockRequest, - botRouterFixtures.createResponseObject(), "test_bot", null); - expect(response.res.session.qnabotcontext.specialtyBot).not.toBeDefined(); - expect(response.res.message).toEqual('{\n "testSlot": {\n "shape": "Scalar",\n "value": {\n "originalValue": "Test Value"\n }\n }\n} Welcome back to QnABot.'); - expect(requestParams.sessionAttributes).toEqual({ "myAttribute": "test" }); - expect(translateSpy).toBeCalledTimes(3); - }); - - test('should translate if Native Language does not match with Speak tags', async () => { - lambdaMock.on(InvokeCommand).resolves({ - "Payload": '{"message":"mockLambdaResponse", "dialogState": "Fulfilled", "sessionAttributes":[]}' - }); - const mockRequest = botRouterFixtures.createRequestObject("Que es QnABot"); - mockRequest._settings.ENABLE_MULTI_LANGUAGE_SUPPORT = true; - mockRequest._settings.NATIVE_LANGUAGE = 'Spanish'; - const response = await specialtyBotRouter.routeRequest(mockRequest, - botRouterFixtures.createResponseObject(), "lambda::mockRoutingLambda", null); - expect(response.res.session.qnabotcontext.specialtyBot).not.toBeDefined(); - expect(response.res.message).toEqual("mockLambdaResponse Welcome back to QnABot."); - expect(response.res.session.appContext.altMessages).toEqual({"html": "mockLambdaResponse Welcome back to QnABot. "}); - }); - - test('should return error if LexV1 responds with Error', async () => { - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(new Error("Mock Error"), null); - }); - await expect(specialtyBotRouter.routeRequest(botRouterFixtures.createRequestObject("What is QnABot"), - botRouterFixtures.createResponseObject(), "test_bot", null)).rejects.toEqual('Lex client request error:Error: Mock Error'); - }); - - test('when routing to Lexv1 Bot and bot response has SSML, returned response should have ssml message', async () => { - let requestParams; - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - requestParams = request; - const mockResponse = botRouterFixtures.getLexV1Response("", "Test Message."); - mockResponse.sessionAttributes.appContext = { "altMessages": { "ssml": "Test Message." } }; - callback(null, mockResponse); - }); - let response = await specialtyBotRouter.routeRequest(botRouterFixtures.createRequestObject("What is QnABot", "SSML"), - botRouterFixtures.createResponseObject(), "test_bot", null); - expect(response.res.type).toEqual("SSML"); - expect(response.res.message).toEqual("Test Message."); - expect(requestParams.sessionAttributes).toEqual({ "myAttribute": "test" }); - - - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - requestParams = request; - const mockResponse = botRouterFixtures.getLexV1Response("", "Test Message."); - mockResponse.sessionAttributes.appContext = '{ "altMessages": { "ssml": "Test Message."}}'; - callback(null, mockResponse); - }); - response = await specialtyBotRouter.routeRequest(botRouterFixtures.createRequestObject("What is QnABot", "SSML"), - botRouterFixtures.createResponseObject(), "test_bot", null); - expect(response.res.type).toEqual("SSML"); - expect(response.res.message).toEqual("Test Message."); - expect(requestParams.sessionAttributes).toEqual({ "myAttribute": "test" }); - }); - - - test('when routing to Lexv1 Bot and bot resonse has SSML, returned response should have ssml message', async () => { - let requestParams; - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - requestParams = request; - const mockResponse = botRouterFixtures.getLexV1Response("", "Test Message."); - mockResponse.sessionAttributes.appContext = { "altMessages": { "ssml": "Test Message." } }; - callback(null, mockResponse); - }); - const response = await specialtyBotRouter.routeRequest(botRouterFixtures.createRequestObject("What is QnABot", "SSML"), - botRouterFixtures.createResponseObject(), "test_bot", null); - expect(response.res.type).toEqual("SSML"); - expect(response.res.message).toEqual("Test Message."); - expect(requestParams.sessionAttributes).toEqual({ "myAttribute": "test" }); - }); - - test('when routing to Lexv1 Bot, returned response should have message type & message', async () => { - jest.spyOn(LexRuntime.prototype, 'postText') - .mockImplementation((request, callback) => { - callback(null, botRouterFixtures.getLexV1Response("", "Test Message.")); - }); - const response = await specialtyBotRouter.routeRequest(botRouterFixtures.createRequestObject("What is QnABot"), - botRouterFixtures.createResponseObject(), "test_bot", null); - expect(response.res.type).toEqual("PlainText"); - expect(response.res.message).toEqual("Test Message."); - }); -}); - - describe('when calling routeRequest function with LexV2 as target', () => { afterEach(() => { jest.clearAllMocks(); diff --git a/source/lambda/genesys/package-lock.json b/source/lambda/genesys/package-lock.json index caffdb50f..aebeea7dc 100644 --- a/source/lambda/genesys/package-lock.json +++ b/source/lambda/genesys/package-lock.json @@ -1,12 +1,12 @@ { "name": "genesys", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "genesys", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "devDependencies": { "jest": "^29.7.0" diff --git a/source/lambda/genesys/package.json b/source/lambda/genesys/package.json index 9326a5509..f35db0ba7 100644 --- a/source/lambda/genesys/package.json +++ b/source/lambda/genesys/package.json @@ -1,6 +1,6 @@ { "name": "genesys", - "version": "6.0.3", + "version": "6.1.0", "description": "Lambda function used to support the Genesys setup wizard", "repository": { "type": "git", diff --git a/source/lambda/import/index.js b/source/lambda/import/index.js index 33eefb715..4b4eef255 100644 --- a/source/lambda/import/index.js +++ b/source/lambda/import/index.js @@ -59,6 +59,8 @@ exports.step = async function (event, context, cb) { qnabot.log('Request', JSON.stringify(event, null, 2)); const Bucket = event.Records[0].s3.bucket.name; const Key = decodeURI(event.Records[0].s3.object.key); + const output_bucket = process.env.OUTPUT_S3_BUCKET; + const output_key = `status-import/${Key.split('/').pop()}` let progress; await waitUntilObjectExists( { @@ -74,85 +76,73 @@ exports.step = async function (event, context, cb) { const res = await x.Body.transformToString(); const config = JSON.parse(res); qnabot.log('Config:', JSON.stringify(config, null, 2)); - if (config.status === 'InProgress') { - // NOSONAR TODO - design a more robust way to identify target ES index for auto import of metrics and feedback - // Filenames must match across: - // aws-ai-qna-bot/templates/import/UpgradeAutoImport.js - // aws-ai-qna-bot/templates/master/UpgradeAutoExport.js - // and pattern in /aws-ai-qna-bot/lambda/import/index.js - const esindex = getOsIndex(Key); - qnabot.log('Importing to index: ', esindex); - try { - const params = { - Bucket: config.bucket, - Key: config.key, - VersionId: config.version, - Range: `bytes=${config.start}-${config.end}` - }; - const result = await s3.send(new GetObjectCommand(params)); - const response = await result.Body.transformToString(); - const settings = await get_settings(); - qnabot.log('opening file'); - let objects = []; + while (config.progress < 1 && config.time.rounds < 15) { + if (config.status === 'InProgress') { + // NOSONAR TODO - design a more robust way to identify target ES index for auto import of metrics and feedback + // Filenames must match across: + // aws-ai-qna-bot/templates/import/UpgradeAutoImport.js + // aws-ai-qna-bot/templates/master/UpgradeAutoExport.js + // and pattern in /aws-ai-qna-bot/lambda/import/index.js + const esindex = getOsIndex(Key); + qnabot.log('Importing to index: ', esindex); try { - config.buffer += response; - if (config.buffer.startsWith('PK')) { - qnabot.log('starts with PK, must be an xlsx'); - const s3Object = await s3.send(new GetObjectCommand(params)); - const readableStreamFile = Buffer.concat(await s3Object.Body.toArray()) - const questionArray = await convertxlsx.convertxlsx(readableStreamFile); - qnabot.log('number of items processed: ', questionArray.length); - questionArray.forEach((question) => { - const questionStr = JSON.stringify(question); - qnabot.log(questionStr); - objects.push(questionStr); - }); - config.buffer = ''; - } else { - objects = config.buffer.split(/\n/); - JSON.parse(objects[objects.length - 1]); - config.buffer = ''; - } - } catch (e) { - qnabot.log('An error occured while processing question array: ', e); - config.buffer = objects.pop(); - } - const { out, success, failed } = await processQuestionObjects(objects, settings, esindex, config); - config.count = success; - config.failed = failed; - qnabot.log('ContentRange: ', result.ContentRange); - const tmp = result.ContentRange.match(/bytes (.*)-(.*)\/(.*)/); // NOSONAR - javascript:S5852 - input is user controlled and we have a limit on the number of characters - progress = (parseInt(tmp[2]) + 1) / parseInt(tmp[3]); - const ES_formatted_content = `${out.join('\n')}\n`; - await delete_existing_content.delete_existing_content(esindex, config, ES_formatted_content); // check and delete existing content (if parameter to delete has been passed in the options {file} - /* - // Disable bulk load.. Instead save docs one at a time, for now, due to issues with k-nn index after bulk load - .then(function (result) { - return es_bulk_load(result) - .then(x => { - config.EsErrors.push(x.errors) - }) - }) - */ - config.start = config.end + 1; - config.end = config.start + config.stride; - config.progress = progress; - config.time.rounds += 1; - if (config.progress >= 1) { - config.status = 'Complete'; - config.time.end = new Date().toISOString(); - } - qnabot.log('EndConfig:', JSON.stringify(config, null, 2)); - await s3.send(new PutObjectCommand({ Bucket, Key, Body: JSON.stringify(config) })); - cb(null); + const params = { + Bucket: config.bucket, + Key: config.key, + VersionId: config.version, + Range: `bytes=${config.start}-${config.end}` + }; + const result = await s3.send(new GetObjectCommand(params)); + const response = await result.Body.transformToString(); + const settings = await get_settings(); + qnabot.log('opening file'); + + const {buffer, objects} = await processQuestionArray(config, response, s3, params) + config.buffer = buffer; + + const { out, success, failed } = await processQuestionObjects(objects, settings, esindex, config); + config.count = success; + config.failed = failed; + qnabot.log('ContentRange: ', result.ContentRange); + const tmp = result.ContentRange.match(/bytes (.*)-(.*)\/(.*)/); // NOSONAR - javascript:S5852 - input is user controlled and we have a limit on the number of characters + progress = (parseInt(tmp[2]) + 1) / parseInt(tmp[3]); + const ES_formatted_content = `${out.join('\n')}\n`; + await delete_existing_content.delete_existing_content(esindex, config, ES_formatted_content); // check and delete existing content (if parameter to delete has been passed in the options {file} + /* + // Disable bulk load.. Instead save docs one at a time, for now, due to issues with k-nn index after bulk load + .then(function (result) { + return es_bulk_load(result) + .then(x => { + config.EsErrors.push(x.errors) + }) + }) + */ + config.start = config.end + 1; + config.end = config.start + config.stride; + config.progress = progress; + config.time.rounds += 1; } catch (error) { qnabot.log('An error occured while config status was InProgress: ', error); config.status = error.message || 'Error' config.message = JSON.stringify(error); - await s3.send(new PutObjectCommand({ Bucket, Key, Body: JSON.stringify(config) })); + await s3.send(new PutObjectCommand({ Bucket: output_bucket, Key: output_key, Body: JSON.stringify(config) })); cb(error); + break; } } + } + try { + if (config.progress >= 1 && config.status == "InProgress") { + config.status = 'Complete'; + config.time.end = new Date().toISOString(); + qnabot.log('EndConfig:', JSON.stringify(config, null, 2)); + await s3.send(new PutObjectCommand({ Bucket: output_bucket, Key: output_key, Body: JSON.stringify(config) })); + cb(null); + } + } catch (err) { + qnabot.log('An error occured while finalizing config: ', err); + cb(err); + } } catch (err) { qnabot.log('An error occured while getting parsing for config: ', err); cb(err); @@ -193,6 +183,9 @@ exports.start = async function (event, context, cb) { Body: JSON.stringify(config) }; await s3.send(new PutObjectCommand(putParams)); + putParams.Bucket = process.env.OUTPUT_S3_BUCKET; + putParams.Key = `status-import/${decodeURI(event.Records[0].s3.object.key.split('/').pop())}`; + await s3.send(new PutObjectCommand(putParams)); cb(null); } catch (x) { qnabot.log('An error occured in start function: ', x); @@ -205,6 +198,37 @@ exports.start = async function (event, context, cb) { } }; +async function processQuestionArray(config, response, s3, s3Params) { + let objects = []; + try { + config.buffer += response; + if (config.buffer.startsWith('PK')) { + qnabot.log('starts with PK, must be an xlsx'); + const s3Object = await s3.send(new GetObjectCommand(s3Params)); + const readableStreamFile = Buffer.concat(await s3Object.Body.toArray()) + const questionArray = await convertxlsx.convertxlsx(readableStreamFile); + qnabot.log('number of items processed: ', questionArray.length); + questionArray.forEach((question) => { + const questionStr = JSON.stringify(question); + qnabot.log(questionStr); + objects.push(questionStr); + }); + config.buffer = ''; + } else { + objects = config.buffer.split(/\n/); + JSON.parse(objects[objects.length - 1]); + config.buffer = ''; + } + const modifiedBuffer = config.buffer + return {modifiedBuffer, objects}; + } catch (e) { + qnabot.log('An error occured while processing question array: ', e); + config.buffer = objects.pop(); + const modifiedBuffer = config.buffer + return {modifiedBuffer, objects}; + } +} + async function processQuestionObjects(objects, settings, esindex, config) { const out = []; let success = config.count || 0; diff --git a/source/lambda/import/package-lock.json b/source/lambda/import/package-lock.json index 7dd4ca720..76185301d 100644 --- a/source/lambda/import/package-lock.json +++ b/source/lambda/import/package-lock.json @@ -1,15 +1,15 @@ { "name": "import", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "import", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { - "read-excel-file": "^5.7.1" + "read-excel-file": "^5.8.5" }, "devDependencies": { "aws-sdk-client-mock": "^3.0.1", @@ -1793,37 +1793,20 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==" + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "license": "MIT" }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1888,22 +1871,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", - "engines": { - "node": ">=0.2.0" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1942,17 +1909,6 @@ } ] }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2050,7 +2006,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -2061,7 +2018,8 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, "node_modules/create-jest": { "version": "29.7.0", @@ -2186,6 +2144,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "license": "BSD-3-Clause", "dependencies": { "readable-stream": "^2.0.2" } @@ -2347,10 +2306,25 @@ "node": ">=8" } }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "node_modules/fsevents": { "version": "2.3.3", @@ -2366,20 +2340,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -2432,6 +2392,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2529,6 +2490,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2599,7 +2561,8 @@ "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", @@ -4099,6 +4062,18 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/just-extend": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", @@ -4129,11 +4104,6 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==" - }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -4250,6 +4220,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4257,25 +4228,6 @@ "node": "*" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -4313,8 +4265,7 @@ "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" }, "node_modules/node-releases": { "version": "2.0.14", @@ -4347,6 +4298,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -4448,6 +4400,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -4560,7 +4513,8 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" }, "node_modules/prompts": { "version": "2.4.2", @@ -4598,19 +4552,21 @@ "dev": true }, "node_modules/read-excel-file": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/read-excel-file/-/read-excel-file-5.7.1.tgz", - "integrity": "sha512-cEX+y7A0TmUESjaVqDTVts3iY2YbySG5ew2TlP0qJN+H7PY+b9MqiK3pl/vNPhx112AuyLtmhfqQc5n6+U2vQw==", + "version": "5.8.5", + "resolved": "https://registry.npmjs.org/read-excel-file/-/read-excel-file-5.8.5.tgz", + "integrity": "sha512-KDDcSsI3VzXTNUBs8q7RwTYrGRE8RZgNwGUivYq13bQtMp1KJmocyBs/EiPTJaFk4I8Ri9iDF+ht2A4GUrudMg==", + "license": "MIT", "dependencies": { "@xmldom/xmldom": "^0.8.2", "fflate": "^0.7.3", - "unzipper": "^0.10.11" + "unzipper": "^0.12.2" } }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -4677,21 +4633,11 @@ "node": ">=10" } }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", @@ -4702,11 +4648,6 @@ "semver": "bin/semver.js" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4808,6 +4749,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -4946,14 +4888,6 @@ "node": ">=8.0" } }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", - "engines": { - "node": "*" - } - }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -4987,21 +4921,26 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/unzipper": { - "version": "0.10.14", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", - "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.12.3.tgz", + "integrity": "sha512-PZ8hTS+AqcGxsaQntl3IRBw65QrBI6lxzqDEL7IAo/XCEqRTKGfOX56Vea5TH9SZczRVxuzk1re04z/YjuYCJA==", + "license": "MIT", + "dependencies": { + "bluebird": "~3.7.2", "duplexer2": "~0.1.4", - "fstream": "^1.0.12", + "fs-extra": "^11.2.0", "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" + "node-int64": "^0.4.0" } }, "node_modules/update-browserslist-db": { @@ -5037,7 +4976,8 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" }, "node_modules/v8-to-istanbul": { "version": "9.2.0", @@ -5097,7 +5037,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/write-file-atomic": { "version": "4.0.2", diff --git a/source/lambda/import/package.json b/source/lambda/import/package.json index de8c5e8e2..4b7e5546e 100644 --- a/source/lambda/import/package.json +++ b/source/lambda/import/package.json @@ -1,6 +1,6 @@ { "name": "import", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot Lambda handling import of QIDs", "main": "index.js", "scripts": { @@ -13,7 +13,7 @@ }, "license": "Apache-2.0", "dependencies": { - "read-excel-file": "^5.7.1" + "read-excel-file": "^5.8.5" }, "devDependencies": { "aws-sdk-client-mock": "^3.0.1", diff --git a/source/lambda/import/test/index.test.js b/source/lambda/import/test/index.test.js index 866b0357e..f04ecb0ee 100644 --- a/source/lambda/import/test/index.test.js +++ b/source/lambda/import/test/index.test.js @@ -77,7 +77,7 @@ describe('when calling start function', () => { it('should call start and update status correctly', async () => { await start(request, null, jest.fn()); expect(qnabot.log).toHaveBeenCalledWith('starting'); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); + expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 2); }); it('should handle an error', async () => { @@ -95,6 +95,7 @@ describe('when calling step function', () => { const OLD_ENV = process.env; process.env.ES_INDEX = 'testEsIndex'; process.env.ES_ENDPOINT = 'testEndpoint'; + process.env.OUTPUT_S3_BUCKET = 'contentDesignerOutputBucket' beforeEach(() => { process.env = { ...OLD_ENV }; s3Mock.reset(); @@ -201,7 +202,11 @@ describe('when calling step function', () => { const error = new Error('test error'); const mockOptions = { - status: 'InProgress' + 'progress': 0, + 'time': { + 'rounds': 0, + }, + 'status': 'InProgress' }; const stream1 = new Readable(); @@ -209,7 +214,14 @@ describe('when calling step function', () => { stream1.push(null); const sdkStream1 = sdkStreamMixin(stream1); - s3Mock.on(GetObjectCommand).resolvesOnce({ Body: sdkStream1 }).rejects(error); + s3Mock.on(GetObjectCommand).resolvesOnce({ Body: sdkStream1 }); + + s3Mock.on(GetObjectCommand, { + 'Bucket': undefined, + 'Key': undefined, + 'Range': 'bytes=undefined-undefined', + 'VersionId': undefined + }).rejects(error); const mockFn = jest.fn(); await step(request, null, mockFn); @@ -226,14 +238,22 @@ describe('when calling step function', () => { 'VersionId': undefined }); expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, {"Body": "{\"status\":\"test error\",\"message\":\"{}\"}", "Bucket": "qna-test-importbucket", "Key": "data/import_questions.json"}); + expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, {"Body": "{\"progress\":0,\"time\":{\"rounds\":0},\"status\":\"test error\",\"message\":\"{}\"}", "Bucket": "contentDesignerOutputBucket", "Key": "status-import/import_questions.json"}); + expect(qnabot.log).toHaveBeenCalledWith('An error occured while config status was InProgress: ', error); expect(mockFn).toHaveBeenCalledWith(error); }); it('should handle an error with buffer', async () => { + jest.spyOn(qnabotSettings, 'getSettings').mockResolvedValue({ EMBEDDINGS_ENABLE: false }); + + const mockOptions = { - status: 'InProgress' + 'progress': 0, + 'time': { + 'rounds': 0, + }, + 'status': 'InProgress' }; const errorConfig = { diff --git a/source/lambda/js_lambda_hook_sdk/package-lock.json b/source/lambda/js_lambda_hook_sdk/package-lock.json index bf4efe4ad..3fbff126f 100644 --- a/source/lambda/js_lambda_hook_sdk/package-lock.json +++ b/source/lambda/js_lambda_hook_sdk/package-lock.json @@ -1,12 +1,12 @@ { "name": "js_lambda_hook_sdk", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "js_lambda_hook_sdk", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "lodash": "^4.17.21" diff --git a/source/lambda/js_lambda_hook_sdk/package.json b/source/lambda/js_lambda_hook_sdk/package.json index cf284f5f2..5f05fdf43 100644 --- a/source/lambda/js_lambda_hook_sdk/package.json +++ b/source/lambda/js_lambda_hook_sdk/package.json @@ -1,6 +1,6 @@ { "name": "js_lambda_hook_sdk", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot convenience layer, allowing users to create custom lambda hooks", "directories": { "lambda_hook_sdk": "lambda_hook_sdk", diff --git a/source/lambda/kendra-webcrawler-schedule-updater/requirements-test.txt b/source/lambda/kendra-webcrawler-schedule-updater/requirements-test.txt index ed98b7883..4f50a96aa 100644 --- a/source/lambda/kendra-webcrawler-schedule-updater/requirements-test.txt +++ b/source/lambda/kendra-webcrawler-schedule-updater/requirements-test.txt @@ -1,4 +1,4 @@ -moto~=4.2.4 -pytest~=7.4.2 -pytest-cov~=4.1.0 +moto~=5.0.13 +pytest~=8.3.2 +pytest-cov~=5.0.0 mock~=5.1.0 \ No newline at end of file diff --git a/source/lambda/kendra-webcrawler-schedule-updater/test/test_lambda_function.py b/source/lambda/kendra-webcrawler-schedule-updater/test/test_lambda_function.py index 60b040c4a..16e653d62 100644 --- a/source/lambda/kendra-webcrawler-schedule-updater/test/test_lambda_function.py +++ b/source/lambda/kendra-webcrawler-schedule-updater/test/test_lambda_function.py @@ -14,9 +14,9 @@ import unittest import boto3 from unittest.mock import patch, MagicMock, ANY -from moto import mock_ssm +from moto import mock_aws -@mock_ssm +@mock_aws class TestLambdaFunction(unittest.TestCase): def setUp(self): self.ssm_client = boto3.client("ssm") diff --git a/source/lambda/kendra-webcrawler-status/requirements-test.txt b/source/lambda/kendra-webcrawler-status/requirements-test.txt index ed98b7883..4f50a96aa 100644 --- a/source/lambda/kendra-webcrawler-status/requirements-test.txt +++ b/source/lambda/kendra-webcrawler-status/requirements-test.txt @@ -1,4 +1,4 @@ -moto~=4.2.4 -pytest~=7.4.2 -pytest-cov~=4.1.0 +moto~=5.0.13 +pytest~=8.3.2 +pytest-cov~=5.0.0 mock~=5.1.0 \ No newline at end of file diff --git a/source/lambda/kendra-webcrawler-status/test/test_lambda_function.py b/source/lambda/kendra-webcrawler-status/test/test_lambda_function.py index d1a0773f5..f6a2dc0d0 100644 --- a/source/lambda/kendra-webcrawler-status/test/test_lambda_function.py +++ b/source/lambda/kendra-webcrawler-status/test/test_lambda_function.py @@ -14,11 +14,11 @@ import unittest import boto3 from unittest.mock import patch, MagicMock -from moto import mock_ssm +from moto import mock_aws from datetime import datetime from botocore.exceptions import ClientError -@mock_ssm +@mock_aws class TestLambdaFunction(unittest.TestCase): def setUp(self): self.ssm_client = boto3.client("ssm") diff --git a/source/lambda/kendra-webcrawler/requirements-test.txt b/source/lambda/kendra-webcrawler/requirements-test.txt index ed98b7883..4f50a96aa 100644 --- a/source/lambda/kendra-webcrawler/requirements-test.txt +++ b/source/lambda/kendra-webcrawler/requirements-test.txt @@ -1,4 +1,4 @@ -moto~=4.2.4 -pytest~=7.4.2 -pytest-cov~=4.1.0 +moto~=5.0.13 +pytest~=8.3.2 +pytest-cov~=5.0.0 mock~=5.1.0 \ No newline at end of file diff --git a/source/lambda/kendra-webcrawler/test/test_lambda_function.py b/source/lambda/kendra-webcrawler/test/test_lambda_function.py index b13512f8e..7cf403b49 100644 --- a/source/lambda/kendra-webcrawler/test/test_lambda_function.py +++ b/source/lambda/kendra-webcrawler/test/test_lambda_function.py @@ -15,10 +15,9 @@ import unittest import boto3 from unittest.mock import patch, MagicMock -from moto import mock_ssm, mock_cloudwatch +from moto import mock_aws -@mock_ssm -@mock_cloudwatch +@mock_aws class TestLambdaFunction(unittest.TestCase): def setUp(self): self.ssm_client = boto3.client("ssm") diff --git a/source/lambda/lex-build/lib/alias.js b/source/lambda/lex-build/lib/alias.js deleted file mode 100644 index 3feb821c5..000000000 --- a/source/lambda/lex-build/lib/alias.js +++ /dev/null @@ -1,26 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const run = require('./run'); - -module.exports = async function (version, data) { - const alias = await run('getBotAlias', data); - const { checksum } = alias; - - await run('putBotAlias', { - botName: data.botName, - botVersion: version, - name: data.name, - checksum, - }); -}; diff --git a/source/lambda/lex-build/lib/bot.js b/source/lambda/lex-build/lib/bot.js deleted file mode 100644 index 76b741bef..000000000 --- a/source/lambda/lex-build/lib/bot.js +++ /dev/null @@ -1,64 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const run = require('./run'); - -module.exports = async function (versionobj, data) { - if (data.intents[0].intentName && data.intents[0].intentName.startsWith('fulfilment_')) { - data.intents[0].intentVersion = versionobj.intent_version; - if (data.intents.length > 1) { - data.intents[1].intentVersion = versionobj.intentFallback_version; - } - } else { - data.intents[1].intentVersion = versionobj.intent_version; - data.intents[0].intentVersion = versionobj.intentFallback_version; - } - delete data.status; - delete data.failureReason; - delete data.lastUpdatedDate; - delete data.createdDate; - delete data.version; - - const bot = await run('putBot', data); - const { checksum } = bot; - - const result = await run('createBotVersion', { - name: data.name, - checksum, - }); - const new_version = result.version; - - await new Promise(async (res, rej) => { - await next(100); - async function next(count) { - const tmp = await run('getBot', { - name: data.name, - versionOrAlias: new_version - }); - if (count === 0) { - throw new Error('Build timeout'); - } else if (tmp.status === 'READY') { - res(); - } else if (tmp.status === 'BUILDING' || tmp.status === 'READY_BASIC_TESTING') { - await delay(5000); - await next(--count); - } else { - throw tmp; - } - } - }); - return new_version; -}; -async function delay(ms) { - return new Promise(res => setTimeout(res, ms)) -} diff --git a/source/lambda/lex-build/lib/delete.js b/source/lambda/lex-build/lib/delete.js deleted file mode 100644 index 93c9f3069..000000000 --- a/source/lambda/lex-build/lib/delete.js +++ /dev/null @@ -1,57 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const _ = require('lodash'); -const run = require('./run.js'); - -exports.bot = async function(name, version) { - try { - const res = await run('getBotVersions', { name }); - const versions = res.bots - .map(x => x.version) - .filter(x => !_.includes(['$LATEST', version], x)) - .map(x => run('deleteBotVersion', { name, version: x })); - return await Promise.all(versions); - } catch (error) { - console.error("An error occurred during getBotVersions: ", error); - throw error; - } -}; - -exports.intent = async function(name, version) { - try { - const res = await run('getIntentVersions', { name }); - const versions = res.intents - .map(x => x.version) - .filter(x => !_.includes(['$LATEST', version], x)) - .map(x => run('deleteIntentVersion', { name, version: x })); - return await Promise.all(versions); - } catch (error) { - console.error("An error occurred during getIntentVersions: ", error); - throw error; - } -}; - -exports.slot = async function(name, version) { - try { - const res = await run('getSlotTypeVersions', { name }); - const versions = res.slotTypes - .map(x => x.version) - .filter(x => !_.includes(['$LATEST', version], x)) - .map(x => run('deleteSlotTypeVersion', { name, version: x })); - return await Promise.all(versions); - } catch (error) { - console.error("An error occurred during getSlotTypeVersions: ", error); - throw error; - } -}; \ No newline at end of file diff --git a/source/lambda/lex-build/lib/index.js b/source/lambda/lex-build/lib/index.js index 835354a7b..83992b6b8 100644 --- a/source/lambda/lex-build/lib/index.js +++ b/source/lambda/lex-build/lib/index.js @@ -11,19 +11,10 @@ * and limitations under the License. * *********************************************************************************************************************/ -const getUtterances = require('./utterances'); const getQidsandquestions = require('./qidsandquestions'); module.exports = async function (params) { - const lexV1Status = process.env.STATUS_KEY; const promises = []; - if (lexV1Status) { - const utterances = await getUtterances(params); - console.log('Starting Lex V1'); - const LexV1Bot = require('./lexv1bot'); - const lexV1 = await LexV1Bot(utterances); - promises.push(lexV1); - } console.log('Starting Lex V2'); const qidsandquestions = await getQidsandquestions(params); const LexV2Bot = require('./lexv2bot'); diff --git a/source/lambda/lex-build/lib/intent.js b/source/lambda/lex-build/lib/intent.js deleted file mode 100644 index 262681126..000000000 --- a/source/lambda/lex-build/lib/intent.js +++ /dev/null @@ -1,35 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const run = require('./run.js'); - -module.exports = async function (version, result) { - // update the version of the slot for the slot named 'slot'. All other slots are unaffected - result.slots.forEach((element) => { - if (element.name === 'slot') { - element.slotTypeVersion = version; - } - }); - - delete result.lastUpdatedDate; - delete result.version; - delete result.createdDate; - - const response = await run('putIntent', result) - const checksum = response.checksum - const createIntentVersion = await run('createIntentVersion', { - name: result.name, - checksum, - }) - return createIntentVersion.version -}; diff --git a/source/lambda/lex-build/lib/intentFallback.js b/source/lambda/lex-build/lib/intentFallback.js deleted file mode 100644 index b57fd9834..000000000 --- a/source/lambda/lex-build/lib/intentFallback.js +++ /dev/null @@ -1,33 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const run = require('./run.js'); - -module.exports = async function (version, result) { - delete result.lastUpdatedDate; - delete result.version; - delete result.createdDate; - - const res = {}; - res.intent_version = version; - - const response = await run('putIntent', result) - const checksum = response.checksum - const createIntentVersion = await run('createIntentVersion', { - name: result.name, - checksum, - }) - res.intentFallback_version = createIntentVersion.version - - return res -}; diff --git a/source/lambda/lex-build/lib/lexv1bot.js b/source/lambda/lex-build/lib/lexv1bot.js deleted file mode 100644 index ab9c87981..000000000 --- a/source/lambda/lex-build/lib/lexv1bot.js +++ /dev/null @@ -1,104 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const run = require('./run'); -const Slot = require('./slot'); -const Intent = require('./intent'); -const IntentFallback = require('./intentFallback'); -const Alias = require('./alias'); -const Bot = require('./bot'); -const clean = require('./delete'); -const status = require('./statusv1'); -const wait = require('./wait'); - -module.exports = async function(utterances){ - const slottype = await run('getSlotType', { - name: process.env.SLOTTYPE, - version: '$LATEST', - }); - const intent = await run('getIntent', { - name: process.env.INTENT, - version: '$LATEST', - }); - const intentFallback = await run('getIntent', { - name: process.env.INTENTFALLBACK, - version: '$LATEST', - }); - const bot = await run('getBot', { - name: process.env.BOTNAME, - versionOrAlias: '$LATEST', - }); - - let clean_intent = null; - let clean_intentFallback = null; - const clean_slottype = null; - let clean_slot = null; - return Promise.all([utterances, slottype]) - .then(result => { - status('Rebuilding Slot'); - return result; - }) - .then(results => { - return Slot(...results); - }) - .then(result => { - status('Rebuilding Intent'); - return result; - }) - .then(slot_version=>{ - clean_intent = () => clean.intent(process.env.INTENT, slot_version); - return Promise.all([slot_version, intent]); - }) - .then(results => { - return Intent(...results); - }) - .then(result => { - status('Rebuilding IntentFallback'); - return result; - }) - .then(intent_version => { - clean_intentFallback = () => clean.intent(process.env.INTENTFALLBACK, intent_version); // NOSONAR need to retain clean_intentFallback status - return Promise.all([intent_version, intentFallback]); - }) - .then(results => { - return IntentFallback(...results); - }) - .then(result => { - status('Rebuilding Lex V1 Bot'); - return result; - }) - .then(versions=>{ - clean_slot = () => clean.slot(process.env.SLOTTYPE, versions.intent_version); // NOSONAR need to retain clean_slot status - return Promise.all([versions, bot]); - }) - .then(results => { - return Bot(...results); - }) - .then(version => { - Alias(version, { botName : process.env.BOTNAME, name : process.env.BOTALIAS}); - return version; - }) - .then(result => new Promise(res => setTimeout(res(result), 1000))) - .then(result => { - wait(); - return result; - }) - .then(version => clean.bot(process.env.BOTNAME, version)) - .then(clean_intent) - .then(clean_slottype) - .then(result => { - console.log(result); - return result; - }) - .catch(error => status('Failed', error.message)) -} diff --git a/source/lambda/lex-build/lib/run.js b/source/lambda/lex-build/lib/run.js deleted file mode 100644 index 7bc2ebc80..000000000 --- a/source/lambda/lex-build/lib/run.js +++ /dev/null @@ -1,56 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const region = process.env.AWS_REGION || 'us-east-1'; -const { LexModelBuildingService } = require('@aws-sdk/client-lex-model-building-service'); -const customSdkConfig = require('sdk-config/customSdkConfig'); -const lex = new LexModelBuildingService(customSdkConfig('C001', { region })); - -module.exports = async function run(fnc, params){ - console.log(fnc + ':request:' + JSON.stringify(params, null, 3)); - const next = async function(count){ - console.log('tries-left:' + count); - try { - const response = await lex[fnc](params); - console.log(fnc + ':result:'+ JSON.stringify(response, null, 3)); - return response - } catch (err) { - console.log(fnc + ':' + err?.name); - const retry = err?.retryAfterSeconds || 5; - console.log('retry in ' + retry); - - // NOSONAR-start - // Code written this way to reduce cognitive complexity - if(err?.name === 'ConflictException'){ - if(count === 0) throw new Error('Error'); - await retryPromise(retry*1000); - return await next(--count); - }else if(err?.name === 'ResourceInUseException'){ - if(count === 0) throw new Error('Error'); - await retryPromise(retry*1000); - return await next(--count); - }else if(err?.name === 'LimitExceededException'){ - await retryPromise(retry*1000); - return await next(count); - }else{ - throw new Error(err?.name + ':' + err?.message); - } - // NOSONAR-end - } - } - return await next(200); -} - -async function retryPromise(ms) { - return new Promise(res => setTimeout(res, ms)); -} diff --git a/source/lambda/lex-build/lib/slot.js b/source/lambda/lex-build/lib/slot.js deleted file mode 100644 index 31fc3c4bc..000000000 --- a/source/lambda/lex-build/lib/slot.js +++ /dev/null @@ -1,36 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const _ = require('lodash'); -const run = require('./run'); - -module.exports = async function (utterances, slottype) { - console.log(`utterances=${utterances}`); - - slottype.enumerationValues = _.uniqBy( - utterances.map((x) => ({ value: x })), - (x) => x.value, - ).slice(0, 10000); - - delete slottype.lastUpdatedDate; - delete slottype.createdDate; - delete slottype.version; - - const response = await run('putSlotType', slottype) - const checksum = response.checksum - const createSlotTypeVersion = await run('createSlotTypeVersion', { - name: slottype.name, - checksum, - }) - return createSlotTypeVersion.version -}; diff --git a/source/lambda/lex-build/lib/statusv1.js b/source/lambda/lex-build/lib/statusv1.js deleted file mode 100644 index e3b11ff5c..000000000 --- a/source/lambda/lex-build/lib/statusv1.js +++ /dev/null @@ -1,43 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const region = process.env.AWS_REGION || 'us-east-1'; -const { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3'); -const customSdkConfig = require('sdk-config/customSdkConfig'); -const s3 = new S3Client(customSdkConfig('C001', { region })); - -module.exports=async function(status,message){ - const bucket=process.env.STATUS_BUCKET; - const lexV1StatusFile=process.env.STATUS_KEY; - try { - const res = await s3.send(new GetObjectCommand({ - Bucket:bucket, - Key:lexV1StatusFile, - })) - const readableStream = Buffer.concat(await res.Body.toArray()); - const result = JSON.parse(readableStream); - if(message) result.message=message; - result.status=status; - console.log(result); - const params = { - Bucket:bucket, - Key:lexV1StatusFile, - Body:JSON.stringify(result) - } - await s3.send(new PutObjectCommand(params)) - - } catch (error) { - console.error("An error occured in statusv1: ", error) - throw new Error(error) - } -}; diff --git a/source/lambda/lex-build/lib/utterances.js b/source/lambda/lex-build/lib/utterances.js deleted file mode 100644 index bd414ebef..000000000 --- a/source/lambda/lex-build/lib/utterances.js +++ /dev/null @@ -1,57 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const region = process.env.AWS_REGION || 'us-east-1'; -const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3'); -const customSdkConfig = require('sdk-config/customSdkConfig'); -const s3 = new S3Client(customSdkConfig('C001', { region })); -const _ = require('lodash'); -const { con } = require('/opt/opensearch-client/connection'); - -module.exports = async function(params){ - const es = con(process.env.ADDRESS); - const searchResults = await es.search({ - index:process.env.INDEX, - scroll:'10s', - body: { - query: {match_all: {}} - } - }); - const scrollId = searchResults.body._scroll_id - const result = searchResults.body.hits.hits - while (true) { - const scrollResults = await es.scroll({ - scrollId, - scroll:'10s' - }) - const { hits } = scrollResults.body.hits; - hits.forEach(x => result.push(x)); - if (!hits.length) break - } - const esUtterances = _.compact(_.uniq(_.flatten(result - .map(qa=>qa._source.questions ? qa._source.questions.map(y=>y.q) : []) - ))); - - const s3Response = await s3.send(new GetObjectCommand({ - Bucket:process.env.UTTERANCE_BUCKET, - Key:process.env.UTTERANCE_KEY - })) - console.log(s3Response) - const readableStream = Buffer.concat(await s3Response.Body.toArray()) - - const s3Utterances = JSON.parse(readableStream) - const combinedUtterances = [esUtterances, s3Utterances ] - const utterances = _.compact(_.uniq(_.flatten(combinedUtterances))) - - return utterances -} diff --git a/source/lambda/lex-build/lib/wait.js b/source/lambda/lex-build/lib/wait.js deleted file mode 100644 index a76f91936..000000000 --- a/source/lambda/lex-build/lib/wait.js +++ /dev/null @@ -1,35 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const region = process.env.AWS_REGION || 'us-east-1'; -const { LambdaClient, InvokeCommand } = require('@aws-sdk/client-lambda'); -const customSdkConfig = require('sdk-config/customSdkConfig'); -const lambda = new LambdaClient(customSdkConfig('C001', { region })); - -module.exports = async function(status){ - console.log('calling poll lambda') - try { - const params = { - FunctionName:process.env.POLL_LAMBDA, - InvocationType:'Event', - Payload:'{}' - } - const invokeCmd = new InvokeCommand(params) - const response = await lambda.send(invokeCmd) - return response - - } catch (error) { - console.error("An error invoking lambda in wait: ", error); - throw error; - } -} \ No newline at end of file diff --git a/source/lambda/lex-build/package-lock.json b/source/lambda/lex-build/package-lock.json index 646bd685a..04f58b263 100644 --- a/source/lambda/lex-build/package-lock.json +++ b/source/lambda/lex-build/package-lock.json @@ -1,12 +1,12 @@ { "name": "lex-build", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lex-build", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-lex-model-building-service": "^3.511.0" @@ -78,16 +78,16 @@ } }, "node_modules/@aws-sdk/client-lex-model-building-service": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-model-building-service/-/client-lex-model-building-service-3.622.0.tgz", - "integrity": "sha512-h2qwJ3q8D4+Rq/6Ihgp8tt1dY5ROPuqLKbBbXy8voCT5AK4HkRVaGgo03FZG0zpA768l67Nq05KU6w3YQysbQw==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-model-building-service/-/client-lex-model-building-service-3.621.0.tgz", + "integrity": "sha512-ltD7R8AkUSmIRGi1kQ86LhN/YQ3b+jetdH/hDT7SvPHBbGig/XotFl4Jn1FszchS9QuQc3wJB8uBHScJUDHU6g==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -98,26 +98,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -263,13 +263,13 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.622.0.tgz", - "integrity": "sha512-DJwUqVR/O2lImbktUHOpaQ8XElNBx3JmWzTT2USg6jh3ErgG1CS6LIV+VUlgtxGl+tFN/G6AcAV8SdnnGydB8Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", + "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", + "@aws-sdk/core": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -280,26 +280,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -311,14 +311,14 @@ } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.622.0.tgz", - "integrity": "sha512-dwWDfN+S98npeY77Ugyv8VIHKRHN+n/70PWE4EgolcjaMrTINjvUh9a/SypFEs5JmBOAeCQt8S2QpM3Wvzp+pQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", + "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -329,26 +329,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -359,7 +359,7 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/abort-controller": { @@ -631,15 +631,15 @@ } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.622.0.tgz", - "integrity": "sha512-Yqtdf/wn3lcFVS42tR+zbz4HLyWxSmztjVW9L/yeMlvS7uza5nSkWqP/7ca+RxZnXLyrnA4jJtSHqykcErlhyg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", + "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -650,26 +650,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -815,15 +815,15 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.622.0.tgz", - "integrity": "sha512-q1Ct2AjPxGtQBKtDpqm1umu3f4cuWMnEHTuDa6zjjaj+Aq/C6yxLgZJo9SlcU0tMl8rUCN7oFonszfTtp4Y0MA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", + "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", "dependencies": { - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "fast-xml-parser": "4.4.1", @@ -882,16 +882,16 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.622.0.tgz", - "integrity": "sha512-VUHbr24Oll1RK3WR8XLUugLpgK9ZuxEm/NVeVqyFts1Ck9gsKpRg1x4eH7L7tW3SJ4TDEQNMbD7/7J+eoL2svg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", + "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/property-provider": "^3.1.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-stream": "^3.1.3", "tslib": "^2.6.2" @@ -1064,14 +1064,14 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.622.0.tgz", - "integrity": "sha512-cD/6O9jOfzQyo8oyAbTKnyRO89BIMSTzwaN4NxGySC6pYVTqxNSWdRwaqg/vKbwJpjbPGGYYXpXEW11kop7dlg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", + "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -1084,7 +1084,7 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/credential-provider-ini/node_modules/@smithy/types": { @@ -1099,15 +1099,15 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.622.0.tgz", - "integrity": "sha512-keldwz4Q/6TYc37JH6m43HumN7Vi+R0AuGuHn5tBV40Vi7IiqEzjpiE+yvsHIN+duUheFLL3j/o0H32jb+14DQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", + "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -1158,11 +1158,11 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.622.0.tgz", - "integrity": "sha512-zrSoBVM2JlwvkBtrcUd4J/9CrG+T+hUy9r6jwo5gonFIN3QkneR/pqpbUn/n32Zy3zlzCo2VfB31g7MjG7kJmg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", + "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", "dependencies": { - "@aws-sdk/client-sso": "3.622.0", + "@aws-sdk/client-sso": "3.621.0", "@aws-sdk/token-providers": "3.614.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -2990,15 +2990,15 @@ } }, "node_modules/@smithy/core": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.2.tgz", - "integrity": "sha512-in5wwt6chDBcUv1Lw1+QzZxN9fBffi+qOixfb65yK4sDuKG7zAUO9HAFqmVzsZM3N+3tTyvZjtnDXePpvp007Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.1.tgz", + "integrity": "sha512-BC7VMXx/1BCmRPCVzzn4HGWAtsrb7/0758EtwOGFJQrlSwJBEjCcDLNZLFoL/68JexYa2s+KmgL/UfmXdG6v1w==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "tslib": "^2.6.2" @@ -3225,14 +3225,14 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.14.tgz", - "integrity": "sha512-7ZaWZJOjUxa5hgmuMspyt8v/zVsh0GXYuF7OvCmdcbVa/xbnKQoYC+uYKunAqRGTkxjOyuOCw9rmFUFOqqC0eQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/service-error-classification": "^3.0.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -3570,9 +3570,9 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -3837,12 +3837,12 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.14.tgz", - "integrity": "sha512-0iwTgKKmAIf+vFLV8fji21Jb2px11ktKVxbX6LIDPAUJyWQqGqBVfwba7xwa1f2FZUoolYQgLvxQEpJycXuQ5w==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", "dependencies": { "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -3863,15 +3863,15 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.14.tgz", - "integrity": "sha512-e9uQarJKfXApkTMMruIdxHprhcXivH1flYCe8JRDTzkkLx8dA3V5J8GZlST9yfDiRWkJpZJlUXGN9Rc9Ade3OQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", "dependencies": { "@smithy/config-resolver": "^3.0.5", "@smithy/credential-provider-imds": "^3.2.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, diff --git a/source/lambda/lex-build/package.json b/source/lambda/lex-build/package.json index a756f60ee..ecc35ee40 100644 --- a/source/lambda/lex-build/package.json +++ b/source/lambda/lex-build/package.json @@ -1,6 +1,6 @@ { "name": "lex-build", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot lambda for rebuilding Amazon Lex bots", "main": "handler.js", "scripts": { diff --git a/source/lambda/lex-build/test/lib/alias.test.js b/source/lambda/lex-build/test/lib/alias.test.js deleted file mode 100644 index ae092517a..000000000 --- a/source/lambda/lex-build/test/lib/alias.test.js +++ /dev/null @@ -1,52 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const Alias = require('../../lib/alias'); -const run = require('../../lib/run'); -jest.mock('../../lib/run'); -describe('When calling alias function', () => { - - test('Should set the values correctly from version and data', async () => { - const version = '2.0'; - const data = { - botName: 'bot-test', - name: 'name-test' - }; - - const mockRun = { - 'checksum': 'checksum-test' - }; - - const runMock = run.mockImplementationOnce(() => { - return mockRun; - }).mockImplementation(() => { - return { - botName: data.botName, - botVersion: version, - name: data.name, - checksum: 'checksum-test' - }; - }); - - await Alias(version, data); - //CheckSum value is set to test-run, version is set to test, botName and name are set to bot-test and name-test respectively - //Verify Run mock is called twice, once by getBotAlias and once by putBotAlias - expect(run).toBeCalledTimes(2); - expect(run).toBeCalledWith('getBotAlias', data); - expect(run).toBeCalledWith('putBotAlias', {"botName": "bot-test", "botVersion": "2.0", "checksum": "checksum-test", "name": "name-test"}) - //verify params passed are same as data and version passed initially - expect(runMock().botName).toEqual(data.botName); - expect(runMock().name).toEqual(data.name); - expect(runMock().botVersion).toEqual(version); - }); -}); diff --git a/source/lambda/lex-build/test/lib/bot.fixtures.js b/source/lambda/lex-build/test/lib/bot.fixtures.js deleted file mode 100644 index 4296523fa..000000000 --- a/source/lambda/lex-build/test/lib/bot.fixtures.js +++ /dev/null @@ -1,73 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -exports.returnData = function(fulfillment_str, length_gt_1) { - const data_length_1 = { - 'name': 'test-bot', - 'intents': [ - { - 'intentName': '', - 'intentVersion': '' - } - ], - 'status': 'Failed', - 'failureReason': 'timeout', - 'lastUpdatedDate': '12/03/2023', - 'createdDate': '10/27/2023', - 'version': '2.0' - }; - - const data_length_2 = { - 'name': 'test-bot', - 'intents': [ - { - 'intentName': '', - 'intentVersion': '' - }, - { - 'intentName': '', - 'intentVersion': '' - } - ], - 'status': 'Failed', - 'failureReason': 'timeout', - 'lastUpdatedDate': '12/03/2023', - 'createdDate': '10/27/2023', - 'version': '2.0' - }; - - if (fulfillment_str) { - data_length_1.intents[0].intentName = 'fulfilment_test'; - data_length_2.intents[0].intentName = 'fulfilment_test'; - if (length_gt_1) { - data_length_2.intents[1].intentName = 'test'; - } - } else { - data_length_1.intents[0].intentName = 'test'; - data_length_2.intents[0].intentName = 'test'; - data_length_2.intents[1].intentName = 'fulfilment_test'; - } - - if (length_gt_1 || !fulfillment_str) { - return data_length_2; - } else { - return data_length_1; - } -} - -exports.returnVersionObj = { - 'intent_version': '2.0', - 'intentFallback_version': '1.0' -}; - -exports.returnNewVersionValue = '3.0'; diff --git a/source/lambda/lex-build/test/lib/bot.test.js b/source/lambda/lex-build/test/lib/bot.test.js deleted file mode 100644 index 5d918ac86..000000000 --- a/source/lambda/lex-build/test/lib/bot.test.js +++ /dev/null @@ -1,135 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const Bot = require('../../lib/bot'); -const run = require('../../lib/run'); -const botFixtures = require('./bot.fixtures'); -jest.mock('../../lib/run'); - -describe('When calling bot function', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - test('Should return new_version when intentName[0] startsWith fulfillment_ and status is READY', async () => { - const runMock = { - 'checksum': 'checksum-test', - 'version': '3.0' - }; - run.mockImplementationOnce(() => { - return runMock; - }).mockImplementationOnce(() => { - return runMock; - }).mockImplementation(() => { - return { - status: 'READY' - }; - }); - - jest.useFakeTimers(); - jest.spyOn(global, 'setTimeout'); - - const dataObj = botFixtures.returnData(true, false); - - const newVersion = await Bot(botFixtures.returnVersionObj, dataObj); - - expect(run).toHaveBeenCalledTimes(3); - expect(run).toHaveBeenCalledWith("putBot", dataObj); - expect(run).toHaveBeenCalledWith("createBotVersion", {"checksum": "checksum-test", "name": "test-bot"}); - expect(run).toHaveBeenCalledWith("getBot", {"name": "test-bot", "versionOrAlias": "3.0"}); - expect(dataObj.status).toBeUndefined(); - expect(dataObj.failureReason).toBeUndefined(); - expect(dataObj.lastUpdatedDate).toBeUndefined(); - expect(dataObj.createdDate).toBeUndefined(); - expect(dataObj.version).toBeUndefined(); - expect(newVersion).toEqual(botFixtures.returnNewVersionValue); - - //Status is ready, so no need to delay - expect(setTimeout).toHaveBeenCalledTimes(0); - }, 10000); - - test('Should return new_version when intentName[0]startsWith fulfillment_ and length gt 1', async () => { - const runMock = { - 'checksum': 'checksum-test', - 'version': '3.0' - }; - - run.mockImplementationOnce(() => { - return runMock; - }).mockImplementationOnce(() => { - return runMock; - }).mockImplementation(() => { - return { - status: 'READY' - }; - }); - - jest.useFakeTimers(); - jest.spyOn(global, 'setTimeout'); - - const dataObj = botFixtures.returnData(true, true); - - const newVersion = await Bot(botFixtures.returnVersionObj, dataObj); - - expect(run).toHaveBeenCalledTimes(3); - expect(run).toHaveBeenCalledWith("putBot", dataObj); - expect(run).toHaveBeenCalledWith("createBotVersion", {"checksum": "checksum-test", "name": "test-bot"}); - expect(run).toHaveBeenCalledWith("getBot", {"name": "test-bot", "versionOrAlias": "3.0"}); - expect(dataObj.status).toBeUndefined(); - expect(dataObj.failureReason).toBeUndefined(); - expect(dataObj.lastUpdatedDate).toBeUndefined(); - expect(dataObj.createdDate).toBeUndefined(); - expect(dataObj.version).toBeUndefined(); - expect(newVersion).toEqual(botFixtures.returnNewVersionValue); - - //Status is ready, so no need to delay - expect(setTimeout).toHaveBeenCalledTimes(0); - }, 10000); - - test('Should return new_version when intentName[0] does not startsWith fulfillment_', async () => { - const runMock = { - 'checksum': 'checksum-test', - 'version': '3.0' - }; - run.mockImplementationOnce(() => { - return runMock; - }).mockImplementationOnce(() => { - return runMock; - }).mockImplementation(() => { - return { - status: 'READY' - }; - }); - - jest.useFakeTimers(); - jest.spyOn(global, 'setTimeout'); - - const dataObj = botFixtures.returnData(false, false); - - const newVersion = await Bot(botFixtures.returnVersionObj, dataObj); - - expect(run).toHaveBeenCalledTimes(3); - expect(run).toHaveBeenCalledWith("putBot", dataObj); - expect(run).toHaveBeenCalledWith("createBotVersion", {"checksum": "checksum-test", "name": "test-bot"}); - expect(run).toHaveBeenCalledWith("getBot", {"name": "test-bot", "versionOrAlias": "3.0"}); - expect(dataObj.status).toBeUndefined(); - expect(dataObj.failureReason).toBeUndefined(); - expect(dataObj.lastUpdatedDate).toBeUndefined(); - expect(dataObj.createdDate).toBeUndefined(); - expect(dataObj.version).toBeUndefined(); - expect(newVersion).toEqual(botFixtures.returnNewVersionValue); - - //Status is ready, so no need to delay - expect(setTimeout).toHaveBeenCalledTimes(0); - }, 10000); -}); diff --git a/source/lambda/lex-build/test/lib/delete.test.js b/source/lambda/lex-build/test/lib/delete.test.js deleted file mode 100644 index 8b0eb043d..000000000 --- a/source/lambda/lex-build/test/lib/delete.test.js +++ /dev/null @@ -1,219 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - - -const { bot } = require('../../lib/delete'); -const { intent } = require('../../lib/delete'); -const { slot } = require('../../lib/delete'); -const run = require('../../lib/run'); -jest.mock('../../lib/run'); - -describe('When calling delete function', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - test('Should return all versions if everything passess successfully for bot', async () => { - //Latest version is 4.0, $LATEST = 4.0 - const curVersion = 2.0; - const arrToBeDeleted = []; - const runMock = { - 'bots': [ - { - 'version': 1.0 - }, - { - 'version': 2.0 - }, - { - 'version': 3.0 - }, - { - 'version': 3.0 - }, - { - 'version': 4.0 - } - ] - }; - - run.mockImplementationOnce(() => { - return runMock; - }).mockImplementation((functionName, params) => { - //Do not push if version is equal to latest (4.0) - if (params.version === 4.0) { - return arrToBeDeleted; - } else { - arrToBeDeleted.push(params.version); - return arrToBeDeleted; - } - }); - - await bot('test-bot', curVersion); - - expect(run).toBeCalledTimes(5); - expect(run).toBeCalledWith('getBotVersions', {"name": "test-bot"}); - expect(run).toBeCalledWith('deleteBotVersion', {"name": "test-bot", "version": 1}); - expect(run).toBeCalledWith('deleteBotVersion', {"name": "test-bot", "version": 3}); - //The only values present in ArrToBeDeleted are 1, 3 and 3. - expect(arrToBeDeleted.length).toEqual(3); - expect(arrToBeDeleted).toEqual([1,3,3]); - - }); - - test('Should return all versions if everything passess successfully for intent', async () => { - //Latest version is 4.0, $LATEST = 4.0 - const curVersion = 2.0; - const arrToBeDeleted = []; - const runMock = { - 'intents': [ - { - 'version': 1.0 - }, - { - 'version': 2.0 - }, - { - 'version': 3.0 - }, - { - 'version': 3.0 - }, - { - 'version': 4.0 - } - ] - }; - - run.mockImplementationOnce(() => { - return runMock; - }).mockImplementation((functionName, params) => { - //Do not push if version is equal to latest (4.0) - if (params.version === 4.0) { - return arrToBeDeleted; - } else { - arrToBeDeleted.push(params.version); - return arrToBeDeleted; - } - }); - - await intent('test-intent', curVersion); - - expect(run).toBeCalledTimes(5); - expect(run).toBeCalledWith('getIntentVersions', {"name": "test-intent"}); - expect(run).toBeCalledWith('deleteIntentVersion', {"name": "test-intent", "version": 1}); - expect(run).toBeCalledWith('deleteIntentVersion', {"name": "test-intent", "version": 3}); - - //The only values present in ArrToBeDeleted are 1, 3 and 3. - expect(arrToBeDeleted.length).toEqual(3); - expect(arrToBeDeleted).toEqual([1,3,3]); - - }); - - test('Should return all versions if everything passess successfully for slot', async () => { - //Latest version is 4.0, $LATEST = 4.0 - const curVersion = 2.0; - const arrToBeDeleted = []; - const runMock = { - 'slotTypes': [ - { - 'version': 1.0 - }, - { - 'version': 2.0 - }, - { - 'version': 3.0 - }, - { - 'version': 3.0 - }, - { - 'version': 4.0 - } - ] - }; - - run.mockImplementationOnce(() => { - return runMock; - }).mockImplementation((functionName, params) => { - //Do not push if version is equal to latest (4.0) - if (params.version === 4.0) { - return arrToBeDeleted; - } else { - arrToBeDeleted.push(params.version); - return arrToBeDeleted; - } - }); - - await slot('test-slot', curVersion); - - expect(run).toBeCalledTimes(5); - expect(run).toBeCalledWith('getSlotTypeVersions', {"name": "test-slot"}); - expect(run).toBeCalledWith('deleteSlotTypeVersion', {"name": "test-slot", "version": 1}); - expect(run).toBeCalledWith('deleteSlotTypeVersion', {"name": "test-slot", "version": 3}); - - //The only values present in ArrToBeDeleted are 1, 3 and 3. - expect(arrToBeDeleted.length).toEqual(3); - expect(arrToBeDeleted).toEqual([1,3,3]); - - }); - - test('Should throw error for bot', async () => { - const curVersion = 2.0; - //const error = new Error('Test Bot Error'); - - run.mockImplementation(() => { - throw new Error('Test Bot Error'); - }); - - await expect(async () => { - await bot('test-bot', curVersion); - }).rejects.toThrowError(); - - expect(run).toBeCalledTimes(1); - expect(run).toBeCalledWith('getBotVersions', {"name": "test-bot"}); - }); - - test('Should throw error for intent', async () => { - const curVersion = 2.0; - //const error = new Error('Test Bot Error'); - - run.mockImplementation(() => { - throw new Error('Test Intent Error'); - }); - - await expect(async () => { - await intent('test-intent', curVersion); - }).rejects.toThrowError(); - - expect(run).toBeCalledTimes(1); - expect(run).toBeCalledWith('getIntentVersions', {"name": "test-intent"}); - }); - - test('Should throw error for slot', async () => { - const curVersion = 2.0; - //const error = new Error('Test Bot Error'); - - run.mockImplementation(() => { - throw new Error('Test Slot Error'); - }); - - await expect(async () => { - await slot('test-slot', curVersion); - }).rejects.toThrowError(); - - expect(run).toBeCalledTimes(1); - expect(run).toBeCalledWith('getSlotTypeVersions', {"name": "test-slot"}); - }); -}); diff --git a/source/lambda/lex-build/test/lib/index.test.js b/source/lambda/lex-build/test/lib/index.test.js index 6b1e7763b..0c2c21013 100644 --- a/source/lambda/lex-build/test/lib/index.test.js +++ b/source/lambda/lex-build/test/lib/index.test.js @@ -13,14 +13,10 @@ const index = require('../../lib/index'); -const utterances = require('../../lib/utterances'); const qids = require('../../lib/qidsandquestions'); -const lexV1 = require('../../lib/lexv1bot'); const lexV2 = require('../../lib/lexv2bot'); const originalEnv = process.env; -jest.mock('../../lib/utterances'); jest.mock('../../lib/qidsandquestions'); -jest.mock('../../lib/lexv1bot'); jest.mock('../../lib/lexv2bot'); describe('When running index function', () => { @@ -28,45 +24,10 @@ describe('When running index function', () => { jest.clearAllMocks(); }); - test('Should execute lexV1 and lexV2 when STATUS_KEY is true', async () => { + test('Should execute only lexV2', async () => { process.env = { ...originalEnv, - STATUS_KEY: 'test-key' - }; - - const params = {name: 'test-index'}; - const sampleUtterance = { - qid: '1', - type: 'qna' - }; - const sampleQid = { - q: 'What is QnABot' - }; - utterances.mockImplementation(() => { - return sampleUtterance; - }); - qids.mockImplementation(() => { - return sampleQid; - }); - - await index(params); - - expect(utterances).toBeCalledTimes(1); - expect(utterances).toBeCalledWith(params); - expect(qids).toBeCalledTimes(1); - expect(qids).toBeCalledWith(params); - expect(lexV1).toBeCalledTimes(1); - expect(lexV1).toBeCalledWith(sampleUtterance); - expect(lexV2).toBeCalledTimes(1); - expect(lexV2).toBeCalledWith(sampleQid); - }); - - test('Should execute only lexV2 when STATUS_KEY is undefined', async () => { - - process.env = { - ...originalEnv, - STATUS_KEY: undefined }; const params = {name: 'test-index'}; @@ -79,10 +40,8 @@ describe('When running index function', () => { }); await index(params); - expect(utterances).toBeCalledTimes(0); expect(qids).toBeCalledTimes(1); expect(qids).toBeCalledWith(params); - expect(lexV1).toBeCalledTimes(0); expect(lexV2).toBeCalledTimes(1); expect(lexV2).toBeCalledWith(sampleQid); }); diff --git a/source/lambda/lex-build/test/lib/intent.test.js b/source/lambda/lex-build/test/lib/intent.test.js deleted file mode 100644 index 6eca106d5..000000000 --- a/source/lambda/lex-build/test/lib/intent.test.js +++ /dev/null @@ -1,81 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - - -const intent = require('../../lib/intent'); -const run = require('../../lib/run'); -const intentFixtures = require('./intent.fixtures'); -jest.mock('../../lib/run'); - -describe('When running intent function', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - test('Should return intentVersion when slot name is slot', async () => { - const runMock = { - 'name': 'mock-test', - 'checksum': 'checksum-test', - 'version': '3.0' - }; - run.mockResolvedValue(runMock); - - const version = '2.0'; - const result = intentFixtures.returnResult(true); - const intentVersion = await intent(version, result); - - expect(run).toBeCalledTimes(2); - expect(run).toBeCalledWith('putIntent', {"failureReason": "timeout", "name": "test-index", "slots": [{"name": "slot", "slotTypeVersion": "2.0"}, {"name": "notSlot", "slotTypeVersion": "1.0"}], "status": "Failed"}); - expect(run).toBeCalledWith('createIntentVersion', {"name": 'test-index', "checksum": 'checksum-test' }); - //Deleted Fields set to UnDefined - expect(result.lastUpdatedDate).toBeUndefined(); - expect(result.version).toBeUndefined(); - expect(result.createdDate).toBeUndefined(); - - //Modify the version in slot[0] with name 'slot' - expect(result.slots[0].slotTypeVersion).toEqual('2.0'); - //Other slot version remains unchanged - expect(result.slots[1].slotTypeVersion).toEqual('1.0'); - - //intentVersion is equal to the version returned by run mock - expect(intentVersion).toEqual('3.0'); - }); - - test('Should return intentVersion when slot name is notSlot', async () => { - const runMock = { - 'name': 'mock-test', - 'checksum': 'checksum-test', - 'version': '3.0' - }; - run.mockResolvedValue(runMock); - - const version = '2.0'; - const result = intentFixtures.returnResult(false); - const intentVersion = await intent(version, result); - - expect(run).toBeCalledTimes(2); - expect(run).toBeCalledWith('putIntent', {"failureReason": "timeout", "name": "test-index", "slots": [{"name": "notSlot", "slotTypeVersion": "1.0"}, {"name": "notSlot", "slotTypeVersion": "1.0"}], "status": "Failed"}); - expect(run).toBeCalledWith('createIntentVersion', {"name": 'test-index', "checksum": 'checksum-test' }); - //Deleted Fields set to UnDefined - expect(result.lastUpdatedDate).toBeUndefined(); - expect(result.version).toBeUndefined(); - expect(result.createdDate).toBeUndefined(); - - //Both slots remains unchanged - expect(result.slots[0].slotTypeVersion).toEqual('1.0'); - expect(result.slots[1].slotTypeVersion).toEqual('1.0'); - - //intentVersion is equal to the version returned by run mock - expect(intentVersion).toEqual('3.0'); - }); -}); diff --git a/source/lambda/lex-build/test/lib/intentFallback.test.js b/source/lambda/lex-build/test/lib/intentFallback.test.js deleted file mode 100644 index 58d69aca2..000000000 --- a/source/lambda/lex-build/test/lib/intentFallback.test.js +++ /dev/null @@ -1,60 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - - -const intentFallback = require('../../lib/intentFallback'); -const run = require('../../lib/run'); -jest.mock('../../lib/run'); - -describe('When calling intentFallback function', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - test('Should return intentFallback version', async () => { - const runMock = { - 'name': 'mock-test', - 'checksum': 'checksum-test', - 'version': '3.0' - }; - run.mockResolvedValue(runMock); - - const version = '2.0'; - const result = { - 'name': 'test', - 'status': 'Failed', - 'failureReason': 'timeout', - 'lastUpdatedDate': '12/03/2023', - 'createdDate': '10/27/2023', - 'version': '2.0' - }; - - const res = await intentFallback(version, result); - - expect(run).toBeCalledTimes(2); - expect(run).toBeCalledWith('putIntent', {"failureReason": "timeout", "name": "test", "status": "Failed"}); - expect(run).toBeCalledWith('createIntentVersion', {"checksum": "checksum-test", "name": "test"}); - - //Deleted Fields set to UnDefined - expect(result.lastUpdatedDate).toBeUndefined(); - expect(result.version).toBeUndefined(); - expect(result.createdDate).toBeUndefined(); - - //IntentVersion set to original version passed in func - expect(res.intent_version).toEqual('2.0'); - - //IntentFallback version set to RunMock version - expect(res.intentFallback_version).toEqual('3.0'); - }); - -}); diff --git a/source/lambda/lex-build/test/lib/lexv1bot.test.js b/source/lambda/lex-build/test/lib/lexv1bot.test.js deleted file mode 100644 index 9439f53e7..000000000 --- a/source/lambda/lex-build/test/lib/lexv1bot.test.js +++ /dev/null @@ -1,128 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const run = require('../../lib/run'); -const slot= require('../../lib/slot'); -const intent = require('../../lib/intent'); -const intentFallback = require('../../lib/intentFallback'); -const alias = require('../../lib/alias'); -const bot = require('../../lib/bot'); -const status = require('../../lib/statusv1'); -const wait = require('../../lib/wait'); -const lexV1 = require('../../lib/lexv1bot'); -jest.mock('../../lib/run'); -jest.mock('../../lib/slot'); -jest.mock('../../lib/intent'); -jest.mock('../../lib/intentFallback'); -jest.mock('../../lib/alias'); -jest.mock('../../lib/bot'); -jest.mock('../../lib/delete'); -jest.mock('../../lib/statusv1'); -jest.mock('../../lib/wait'); - -describe('When calling lexV1bot function', () => { - beforeEach(() => { - jest.clearAllMocks(); - process.env.SLOTTYPE = 'test-slot'; - process.env.INTENT = 'test-intent'; - process.env.INTENTFALLBACK = 'test-intentFallback'; - process.env.BOTNAME = 'test-bot'; - process.env.BOTALIAS = 'test-alias'; - }); - - test('Should return successful response', async () => { - run.mockImplementationOnce(() => { - return { - slots: [1, 3, 3], - version: '3.0' - }; - }).mockImplementationOnce(() => { - return { - intentVersion: '3.0', - status: 'success' - }; - }).mockImplementationOnce(() => { - return { - intentFallbackVersion: '2.0', - status: 'success' - }; - }).mockImplementation(() => { - return { - version: '3.0', - status: 'READY' - }; - }); - - jest.useFakeTimers(); - jest.spyOn(global, 'setTimeout'); - - await expect(lexV1({})).resolves.not.toThrow(); - - expect(status).toHaveBeenCalledTimes(4); - expect(status).toHaveBeenCalledWith('Rebuilding Slot'); - expect(status).toHaveBeenCalledWith('Rebuilding Intent'); - expect(status).toHaveBeenCalledWith('Rebuilding IntentFallback'); - expect(status).toHaveBeenCalledWith('Rebuilding Lex V1 Bot'); - expect(run).toHaveBeenCalledTimes(4); - expect(run).toHaveBeenCalledWith('getSlotType', {"name": "test-slot", "version": "$LATEST"}); - expect(run).toHaveBeenCalledWith('getIntent', {"name": "test-intent", "version": "$LATEST"}); - expect(run).toHaveBeenCalledWith('getIntent', {"name": "test-intentFallback", "version": "$LATEST"}); - expect(run).toHaveBeenCalledWith('getBot', {"name": "test-bot", "versionOrAlias": "$LATEST"}); - expect(slot).toHaveBeenCalledTimes(1); - expect(slot).toHaveBeenCalledWith({}, {"slots": [1, 3, 3], "version": "3.0"}); - expect(intent).toHaveBeenCalledTimes(1); - expect(intent).toHaveBeenCalledWith(undefined, {"intentVersion": "3.0", "status": "success"}); - expect(intentFallback).toHaveBeenCalledTimes(1); - expect(intentFallback).toHaveBeenCalledWith(undefined, {"intentFallbackVersion": "2.0", "status": "success"}); - expect(bot).toHaveBeenCalledTimes(1); - expect(bot).toHaveBeenCalledWith(undefined, {"status": "READY", "version": "3.0"}); - expect(alias).toHaveBeenCalledTimes(1); - expect(alias).toHaveBeenCalledWith(undefined, {"botName": "test-bot", "name": "test-alias"}); - expect(wait).toHaveBeenCalledTimes(1); - expect(setTimeout).toHaveBeenCalledTimes(1); - }); - - test('Should return error', async () => { - run.mockImplementation(() => { - return { - slots: [1, 3, 3], - version: '3.0' - }; - }) - const error = new Error('Error building lexV1bot'); - slot.mockRejectedValue(error); - - jest.useFakeTimers(); - jest.spyOn(global, 'setTimeout'); - - await lexV1({}) - - expect(status).toHaveBeenCalledTimes(2); - expect(status).toHaveBeenCalledWith('Rebuilding Slot'); - expect(status).toHaveBeenCalledWith('Failed', 'Error building lexV1bot'); - expect(run).toHaveBeenCalledTimes(4); - expect(run).toHaveBeenCalledWith('getSlotType', {"name": "test-slot", "version": "$LATEST"}); - expect(run).toHaveBeenCalledWith('getIntent', {"name": "test-intent", "version": "$LATEST"}); - expect(run).toHaveBeenCalledWith('getIntent', {"name": "test-intentFallback", "version": "$LATEST"}); - expect(run).toHaveBeenCalledWith('getBot', {"name": "test-bot", "versionOrAlias": "$LATEST"}); - expect(slot).toHaveBeenCalledTimes(1); - expect(slot).toHaveBeenCalledWith({}, {"slots": [1, 3, 3], "version": "3.0"}); - expect(intent).toHaveBeenCalledTimes(0); - expect(intentFallback).toHaveBeenCalledTimes(0); - expect(bot).toHaveBeenCalledTimes(0); - expect(alias).toHaveBeenCalledTimes(0); - expect(wait).toHaveBeenCalledTimes(0); - expect(setTimeout).toHaveBeenCalledTimes(0); - }); -}); - diff --git a/source/lambda/lex-build/test/lib/run.test.js b/source/lambda/lex-build/test/lib/run.test.js deleted file mode 100644 index 45556163b..000000000 --- a/source/lambda/lex-build/test/lib/run.test.js +++ /dev/null @@ -1,92 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const run = require('../../lib/run'); -const { LexModelBuildingServiceClient, - CreateBotVersionCommand -} = require('@aws-sdk/client-lex-model-building-service'); -const { mockClient } = require('aws-sdk-client-mock'); -const lexModelBuildingServiceClientMock = mockClient(LexModelBuildingServiceClient); - - -describe('When calling run function', () => { - const lexCreateBotResponse = { - "$metadata": { - "httpStatusCode": 201, "requestId": "429fe1b2-c69f-4a41-aa14-146a85677fb3", "attempts": 1, - "totalRetryDelay": 0 - }, - "locale": "en-US", "name": "test_bot", "status": "BUILDING", "version": "1" - }; - - beforeEach(() => { - lexModelBuildingServiceClientMock.reset(); - }); - - test('should successfully invoke function passed in parameter and return response', async () => { - lexModelBuildingServiceClientMock.on(CreateBotVersionCommand).resolves(lexCreateBotResponse); - const response = await run('createBotVersion', { "name": "test_bot", "checksum": "test_checksum" }); - expect(response).toEqual(lexCreateBotResponse); - - }); - - test('when lex service returns ConflictException and retry is successful, it should return response', async () => { - lexModelBuildingServiceClientMock.on(CreateBotVersionCommand).callsFakeOnce(() => { - const error = new Error("ConflictException"); - error.name = "ConflictException"; - throw error; - }).resolvesOnce(lexCreateBotResponse); - const response = await run('createBotVersion', { "name": "test_bot", "checksum": "test_checksum" }); - expect(response).toEqual(lexCreateBotResponse); - }, 10000); - - test('when lex service returns ResourceInUseException with retryAfterSeconds value set and retry is successful, it should return response', async () => { - lexModelBuildingServiceClientMock.on(CreateBotVersionCommand).callsFakeOnce(() => { - const error = new Error("ResourceInUseException"); - error.name = "ResourceInUseException"; - error.retryAfterSeconds = 3; - throw error; - }).resolvesOnce(lexCreateBotResponse); - const response = await run('createBotVersion', { "name": "test_bot", "checksum": "test_checksum" }); - expect(response).toEqual(lexCreateBotResponse); - }, 10000); - - test('when lex service returns ResourceInUseException and retry is successful, it should return response', async () => { - lexModelBuildingServiceClientMock.on(CreateBotVersionCommand).callsFakeOnce(() => { - const error = new Error("ResourceInUseException"); - error.name = "ResourceInUseException"; - throw error; - }).resolvesOnce(lexCreateBotResponse); - const response = await run('createBotVersion', { "name": "test_bot", "checksum": "test_checksum" }); - expect(response).toEqual(lexCreateBotResponse); - }, 10000); - - test('when lex service returns LimitExceededException and retry is successful, it should return response', async () => { - lexModelBuildingServiceClientMock.on(CreateBotVersionCommand).callsFakeOnce(() => { - const error = new Error("LimitExceededException"); - error.name = "LimitExceededException"; - throw error; - }).resolvesOnce(lexCreateBotResponse); - const response = await run('createBotVersion', { "name": "test_bot", "checksum": "test_checksum" }); - expect(response).toEqual(lexCreateBotResponse); - }, 10000); - - test('should throw error when the error from lex service is not in retry error list', async () => { - lexModelBuildingServiceClientMock.on(CreateBotVersionCommand).callsFakeOnce(() => { - const error = new Error("Test Error"); - error.name = "TestError"; - throw error; - }); - await expect(run('createBotVersion', { "name": "test_bot", "checksum": "test_checksum" })).rejects.toThrow('TestError:Test Error'); - }); -} -); \ No newline at end of file diff --git a/source/lambda/lex-build/test/lib/slot.test.js b/source/lambda/lex-build/test/lib/slot.test.js deleted file mode 100644 index c2ed96276..000000000 --- a/source/lambda/lex-build/test/lib/slot.test.js +++ /dev/null @@ -1,60 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - - -const slot = require('../../lib/slot'); -const run = require('../../lib/run'); -jest.mock('../../lib/run'); - -describe('When running slot function', () => { - test('Should return slotTypeVersion', async () => { - const runMock = { - 'name': 'mock-test', - 'checksum': 'checksum-test', - 'version': '3.0' - }; - run.mockResolvedValue(runMock); - - const utterances = [2, 2, 1]; - const slottype = { - 'name': 'test-slot', - 'status': 'Failed', - 'failureReason': 'timeout', - 'lastUpdatedDate': '12/03/2023', - 'createdDate': '10/27/2023', - 'version': '2.0', - 'enumerationValues': [], - }; - - const responseVersion = await slot(utterances, slottype); - - expect(run).toBeCalledTimes(2); - expect(run).toBeCalledWith('putSlotType', {"name": "test-slot", "enumerationValues": [{"value": 2}, {"value": 1}], "failureReason": "timeout", "status": "Failed"}); - expect(run).toBeCalledWith('createSlotTypeVersion', {"checksum": "checksum-test", "name": "test-slot"}); - - //Deleted Fields set to UnDefined - expect(slottype.lastUpdatedDate).toBeUndefined(); - expect(slottype.version).toBeUndefined(); - expect(slottype.createdDate).toBeUndefined(); - - //Verify slottype.enumerationValues contains distinct values - const valueArr = [ - {'value': 2}, - {'value': 1} - ]; - expect(slottype.enumerationValues).toEqual(valueArr); - - //final version is set to mock-run's version - expect(responseVersion).toEqual('3.0'); - }); -}); diff --git a/source/lambda/lex-build/test/lib/statusv1.test.js b/source/lambda/lex-build/test/lib/statusv1.test.js deleted file mode 100644 index f6a9e131a..000000000 --- a/source/lambda/lex-build/test/lib/statusv1.test.js +++ /dev/null @@ -1,138 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - - -const { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3'); -const { mockClient } = require('aws-sdk-client-mock'); -const s3Mock = mockClient(S3Client); -require('aws-sdk-client-mock-jest'); -const statusV1 = require('../../lib/statusv1'); -const { sdkStreamMixin } = require('@smithy/util-stream'); -const {Readable} = require('stream'); - -describe('When calling statusV1 function', () => { - beforeEach(() => { - s3Mock.reset(); - process.env.STATUS_KEY = 'testKey'; - process.env.STATUS_BUCKET = 'testBucket'; - }); - - test('Should successfully send PutObjectCommand to s3 with no errors with status and message', async () => { - const message = 'test-message'; - const status = 'success'; - const mockResponse = { - 'name': 'test-statusv1', - 'lastUpdatedDate': '12/03/2023', - 'createdDate': '10/27/2023', - 'version': '2.0'}; - - const stream = new Readable(); - stream.push(JSON.stringify(mockResponse)); - stream.push(null); - - s3Mock.on(GetObjectCommand).resolves( - { - Body: sdkStreamMixin(stream) - } - ); - - const verifyMessage = {}; - - //Add status and message fields to mockResponse if required - const statusAndMessageMock = jest.fn().mockImplementation(() => { - if(message) verifyMessage.message=message; - verifyMessage.status=status; - return verifyMessage; - }) - - await statusV1(status, message); - - const putParams = { - Body: "{\"name\":\"test-statusv1\",\"lastUpdatedDate\":\"12/03/2023\",\"createdDate\":\"10/27/2023\",\"version\":\"2.0\",\"message\":\"test-message\",\"status\":\"success\"}", - Bucket: 'testBucket', - Key: 'testKey' - }; - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "testBucket", "Key": "testKey"}); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, putParams); - - //Verify Status and message present - expect(statusAndMessageMock().status).toEqual(status); - expect(statusAndMessageMock().message).toEqual(message) - - }); - - test('Should successfully send PutObjectCommand to s3 with no errors with status only', async () => { - const message = undefined; - const status = 'success'; - const mockResponse = { - 'name': 'test-statusv1-noMessage', - 'lastUpdatedDate': '12/03/2023', - 'createdDate': '10/27/2023', - 'version': '2.0'}; - - const stream = new Readable(); - stream.push(JSON.stringify(mockResponse)); - stream.push(null); - - s3Mock.on(GetObjectCommand).resolves( - { - Body: sdkStreamMixin(stream) - } - ); - - const verifyMessage = {}; - - //Add status and message fields to mockResponse if required - const statusAndMessageMock = jest.fn().mockImplementation(() => { - if(message) verifyMessage.message=message; - verifyMessage.status=status; - return verifyMessage; - }) - - await statusV1(status, message); - - const putParams = { - Body: "{\"name\":\"test-statusv1-noMessage\",\"lastUpdatedDate\":\"12/03/2023\",\"createdDate\":\"10/27/2023\",\"version\":\"2.0\",\"status\":\"success\"}", - Bucket: 'testBucket', - Key: 'testKey' - }; - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "testBucket", "Key": "testKey"}); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, putParams); - - - //Verify Status and message present - expect(statusAndMessageMock().status).toEqual(status); - expect(statusAndMessageMock().message).toBeUndefined(); - }); - - - test('Should throw error', async () => { - const message = 'test-message'; - const status = 'success'; - - s3Mock.on(GetObjectCommand).rejects(new Error("Error with PutObject Command")); - - await expect(async () => { - await statusV1(status, message) - }).rejects.toThrowError(); - - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "testBucket", "Key": "testKey"}); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 0); - }); - -}); diff --git a/source/lambda/lex-build/test/lib/utterances.test.js b/source/lambda/lex-build/test/lib/utterances.test.js deleted file mode 100644 index 67893b38f..000000000 --- a/source/lambda/lex-build/test/lib/utterances.test.js +++ /dev/null @@ -1,82 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - - -const utterances = require('../../lib/utterances'); -const { con } = require('/opt/opensearch-client/connection'); -const esFixtures = require('./es.fixtures'); -const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3'); -const { mockClient } = require('aws-sdk-client-mock'); -const { Readable } = require('stream'); -const { sdkStreamMixin } = require('@smithy/util-stream'); -const s3Mock = mockClient(S3Client); -require('aws-sdk-client-mock-jest'); -jest.mock('/opt/opensearch-client/connection'); - -describe('When calling utterances function', () => { - beforeEach(() => { - jest.clearAllMocks(); - s3Mock.reset(); - process.env.INDEX = 'test-index'; - process.env.UTTERANCE_BUCKET = 'test-bucket'; - process.env.UTTERANCE_KEY = 'test-key'; - process.env.ADDRESS = 'test-address'; - }); - - test('Should return combined utterances successfully', async () => { - const params = { - address: 'test-address' - }; - - const mockEs = jest.fn().mockImplementation(() => { - return esFixtures.returnEsMock('qna'); - }); - const mockResponse = mockEs(); - - con.mockImplementation(() => { - return mockResponse; - }); - - const s3MockResponse = 'Sample Mock question from S3'; - - const stream = new Readable(); - stream.push(JSON.stringify(s3MockResponse)); - stream.push(null); - - s3Mock.on(GetObjectCommand).resolves( - { - Body: sdkStreamMixin(stream) - } - ); - - const combinedUtterances = await utterances(params); - - expect(con).toBeCalledTimes(1); - expect(con).toBeCalledWith('test-address'); - expect(mockResponse.search).toHaveBeenCalledTimes(1); - expect(mockResponse.search).toHaveBeenCalledWith({"body": {"query": {"match_all": {}}}, "index": "test-index", "scroll": "10s"}); - expect(mockResponse.scroll).toHaveBeenCalledTimes(2); - expect(mockResponse.scroll).toHaveBeenCalledWith({"scroll": "10s", "scrollId": "1.0"}); - - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "test-bucket", "Key": "test-key"}); - - //Total size of combinedUtterances is 5, 2 from search, 2 from scroll and 1 from s3 - expect(combinedUtterances.length).toEqual(5); - expect(combinedUtterances[0]).toEqual('What is QnABot?'); - expect(combinedUtterances[1]).toEqual('How is weather today?'); - expect(combinedUtterances[2]).toEqual('What is best place to see northern lights?'); - expect(combinedUtterances[3]).toEqual('What is Best Indian restaurant in US?'); - expect(combinedUtterances[4]).toEqual('Sample Mock question from S3'); - }); -}) diff --git a/source/lambda/lex-build/test/lib/wait.test.js b/source/lambda/lex-build/test/lib/wait.test.js deleted file mode 100644 index 7d5433804..000000000 --- a/source/lambda/lex-build/test/lib/wait.test.js +++ /dev/null @@ -1,51 +0,0 @@ -/********************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - *********************************************************************************************************************/ - -const { LambdaClient, InvokeCommand } = require('@aws-sdk/client-lambda'); -const { mockClient } = require('aws-sdk-client-mock'); -const lambdaMock = mockClient(LambdaClient); -const wait = require('../../lib/wait'); -require('aws-sdk-client-mock-jest'); - -describe('When calling wait function', () => { - beforeEach(() => { - lambdaMock.reset(); - process.env.POLL_LAMBDA = 'test-wait'; - }); - - test('Should return successful response', async () => { - const testResponse = { - 'name': 'test-wait-response', - 'question': 'what is QnABot' - }; - - lambdaMock.on(InvokeCommand).resolves(testResponse); - - const response = await wait('Success'); - - expect(lambdaMock).toHaveReceivedCommandTimes(InvokeCommand, 1); - expect(lambdaMock).toHaveReceivedCommandWith(InvokeCommand, {"FunctionName": "test-wait", "InvocationType": "Event", "Payload": "{}"}); - expect(response).toMatchObject(testResponse); - }); - - test('Should return error', async () => { - - const error = new Error('wait error'); - lambdaMock.on(InvokeCommand).rejects(error); - - await expect(wait('Fail')).rejects.toThrowError(error); - - expect(lambdaMock).toHaveReceivedCommandTimes(InvokeCommand, 1); - expect(lambdaMock).toHaveReceivedCommandWith(InvokeCommand, {"FunctionName": "test-wait", "InvocationType": "Event", "Payload": "{}"}); - }); -}); diff --git a/source/lambda/lexv2-build/requirements-test.txt b/source/lambda/lexv2-build/requirements-test.txt index ed98b7883..4f50a96aa 100644 --- a/source/lambda/lexv2-build/requirements-test.txt +++ b/source/lambda/lexv2-build/requirements-test.txt @@ -1,4 +1,4 @@ -moto~=4.2.4 -pytest~=7.4.2 -pytest-cov~=4.1.0 +moto~=5.0.13 +pytest~=8.3.2 +pytest-cov~=5.0.0 mock~=5.1.0 \ No newline at end of file diff --git a/source/lambda/lexv2-build/requirements.txt b/source/lambda/lexv2-build/requirements.txt index 83a876f05..bcffde562 100644 --- a/source/lambda/lexv2-build/requirements.txt +++ b/source/lambda/lexv2-build/requirements.txt @@ -1,2 +1,2 @@ -boto3==1.26.3 +boto3==1.35.5 crhelper==2.0.10 \ No newline at end of file diff --git a/source/lambda/lexv2-build/test/test_lambda_function.py b/source/lambda/lexv2-build/test/test_lambda_function.py index 700529db2..eed851cff 100644 --- a/source/lambda/lexv2-build/test/test_lambda_function.py +++ b/source/lambda/lexv2-build/test/test_lambda_function.py @@ -15,10 +15,9 @@ import boto3 import json from unittest.mock import patch, MagicMock -from moto import mock_iam, mock_s3 +from moto import mock_aws -@mock_iam -@mock_s3 +@mock_aws class TestLambdaFunction(unittest.TestCase): def setUp(self): self.iam_client = boto3.client("iam") diff --git a/source/lambda/proxy-es/package-lock.json b/source/lambda/proxy-es/package-lock.json index f884237ed..2b78a7e40 100644 --- a/source/lambda/proxy-es/package-lock.json +++ b/source/lambda/proxy-es/package-lock.json @@ -1,12 +1,12 @@ { "name": "proxy-es", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "proxy-es", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0" } } diff --git a/source/lambda/proxy-es/package.json b/source/lambda/proxy-es/package.json index 9dde02e93..5299726a0 100644 --- a/source/lambda/proxy-es/package.json +++ b/source/lambda/proxy-es/package.json @@ -1,6 +1,6 @@ { "name": "proxy-es", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot Lambda function is used to proxy request from ApiGateway to OpenSearch", "main": "index.js", "author": { diff --git a/source/lambda/qnabot-common-layer/package-lock.json b/source/lambda/qnabot-common-layer/package-lock.json index e0f360182..9c956785b 100644 --- a/source/lambda/qnabot-common-layer/package-lock.json +++ b/source/lambda/qnabot-common-layer/package-lock.json @@ -1,12 +1,12 @@ { "name": "qnabot-common-layer", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "qnabot-common-layer", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-ssm": "^3.511.0", @@ -146,16 +146,16 @@ } }, "node_modules/@aws-sdk/client-ssm": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.622.0.tgz", - "integrity": "sha512-/FyBz+Fy9+72TfK0uYTUnZYdnuUNFSsUV83bIw3IOtOEumzoSxF2drq4d80cUVALDjctfDkbftN6Og1GaKlIqg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.621.0.tgz", + "integrity": "sha512-E4OM7HH9qU2TZGDrX2MlBlBr9gVgDm573Qa1CTFih58dUZyaPEOiZSYLUNOyw4nMyVLyDMR/5zQ4wAorNwKVPw==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -166,26 +166,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -199,13 +199,13 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.622.0.tgz", - "integrity": "sha512-DJwUqVR/O2lImbktUHOpaQ8XElNBx3JmWzTT2USg6jh3ErgG1CS6LIV+VUlgtxGl+tFN/G6AcAV8SdnnGydB8Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", + "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", + "@aws-sdk/core": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -216,26 +216,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -247,14 +247,14 @@ } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.622.0.tgz", - "integrity": "sha512-dwWDfN+S98npeY77Ugyv8VIHKRHN+n/70PWE4EgolcjaMrTINjvUh9a/SypFEs5JmBOAeCQt8S2QpM3Wvzp+pQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", + "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -265,26 +265,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -295,19 +295,19 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.622.0.tgz", - "integrity": "sha512-Yqtdf/wn3lcFVS42tR+zbz4HLyWxSmztjVW9L/yeMlvS7uza5nSkWqP/7ca+RxZnXLyrnA4jJtSHqykcErlhyg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", + "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -318,26 +318,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -349,15 +349,15 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.622.0.tgz", - "integrity": "sha512-q1Ct2AjPxGtQBKtDpqm1umu3f4cuWMnEHTuDa6zjjaj+Aq/C6yxLgZJo9SlcU0tMl8rUCN7oFonszfTtp4Y0MA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", + "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", "dependencies": { - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "fast-xml-parser": "4.4.1", @@ -382,16 +382,16 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.622.0.tgz", - "integrity": "sha512-VUHbr24Oll1RK3WR8XLUugLpgK9ZuxEm/NVeVqyFts1Ck9gsKpRg1x4eH7L7tW3SJ4TDEQNMbD7/7J+eoL2svg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", + "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/property-provider": "^3.1.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-stream": "^3.1.3", "tslib": "^2.6.2" @@ -401,14 +401,14 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.622.0.tgz", - "integrity": "sha512-cD/6O9jOfzQyo8oyAbTKnyRO89BIMSTzwaN4NxGySC6pYVTqxNSWdRwaqg/vKbwJpjbPGGYYXpXEW11kop7dlg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", + "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -421,19 +421,19 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.622.0.tgz", - "integrity": "sha512-keldwz4Q/6TYc37JH6m43HumN7Vi+R0AuGuHn5tBV40Vi7IiqEzjpiE+yvsHIN+duUheFLL3j/o0H32jb+14DQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", + "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -462,11 +462,11 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.622.0.tgz", - "integrity": "sha512-zrSoBVM2JlwvkBtrcUd4J/9CrG+T+hUy9r6jwo5gonFIN3QkneR/pqpbUn/n32Zy3zlzCo2VfB31g7MjG7kJmg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", + "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", "dependencies": { - "@aws-sdk/client-sso": "3.622.0", + "@aws-sdk/client-sso": "3.621.0", "@aws-sdk/token-providers": "3.614.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -1712,15 +1712,15 @@ } }, "node_modules/@smithy/core": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.2.tgz", - "integrity": "sha512-in5wwt6chDBcUv1Lw1+QzZxN9fBffi+qOixfb65yK4sDuKG7zAUO9HAFqmVzsZM3N+3tTyvZjtnDXePpvp007Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.1.tgz", + "integrity": "sha512-BC7VMXx/1BCmRPCVzzn4HGWAtsrb7/0758EtwOGFJQrlSwJBEjCcDLNZLFoL/68JexYa2s+KmgL/UfmXdG6v1w==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "tslib": "^2.6.2" @@ -1821,14 +1821,14 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.14.tgz", - "integrity": "sha512-7ZaWZJOjUxa5hgmuMspyt8v/zVsh0GXYuF7OvCmdcbVa/xbnKQoYC+uYKunAqRGTkxjOyuOCw9rmFUFOqqC0eQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/service-error-classification": "^3.0.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1983,9 +1983,9 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -2075,12 +2075,12 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.14.tgz", - "integrity": "sha512-0iwTgKKmAIf+vFLV8fji21Jb2px11ktKVxbX6LIDPAUJyWQqGqBVfwba7xwa1f2FZUoolYQgLvxQEpJycXuQ5w==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", "dependencies": { "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -2090,15 +2090,15 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.14.tgz", - "integrity": "sha512-e9uQarJKfXApkTMMruIdxHprhcXivH1flYCe8JRDTzkkLx8dA3V5J8GZlST9yfDiRWkJpZJlUXGN9Rc9Ade3OQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", "dependencies": { "@smithy/config-resolver": "^3.0.5", "@smithy/credential-provider-imds": "^3.2.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, diff --git a/source/lambda/qnabot-common-layer/package.json b/source/lambda/qnabot-common-layer/package.json index 950ae79f2..9d65e60c9 100644 --- a/source/lambda/qnabot-common-layer/package.json +++ b/source/lambda/qnabot-common-layer/package.json @@ -1,6 +1,6 @@ { "name": "qnabot-common-layer", - "version": "6.0.3", + "version": "6.1.0", "description": "Lambda layers used to provide common logging and utility functions", "repository": { "type": "git", diff --git a/source/lambda/s3-clean/requirements-test.txt b/source/lambda/s3-clean/requirements-test.txt index ea995fb0f..643e20825 100644 --- a/source/lambda/s3-clean/requirements-test.txt +++ b/source/lambda/s3-clean/requirements-test.txt @@ -1,7 +1,7 @@ boto3 -botocore==1.31.68 +botocore==1.35.5 coverage -pytest~=7.4.2 -pytest-cov~=4.1.0 +pytest~=8.3.2 +pytest-cov~=5.0.0 mock~=5.1.0 -moto~=4.2.4 +moto~=5.0.13 diff --git a/source/lambda/s3-clean/requirements.txt b/source/lambda/s3-clean/requirements.txt index 6e211317c..bd077b574 100644 --- a/source/lambda/s3-clean/requirements.txt +++ b/source/lambda/s3-clean/requirements.txt @@ -1,3 +1,3 @@ boto3 -botocore==1.31.68 +botocore==1.35.5 crhelper==2.0.11 \ No newline at end of file diff --git a/source/lambda/s3-clean/test/test_lambda_function.py b/source/lambda/s3-clean/test/test_lambda_function.py index 50cc0521e..da7af3e37 100644 --- a/source/lambda/s3-clean/test/test_lambda_function.py +++ b/source/lambda/s3-clean/test/test_lambda_function.py @@ -14,7 +14,7 @@ import unittest from unittest import mock import boto3 -from moto import mock_s3 +from moto import mock_aws bucket_name = 'test-bucket' object_key = f'{bucket_name}/test-key' @@ -42,7 +42,7 @@ def mocked_cf_event_non_existent_bucket(*args, **kwargs): } } -@mock_s3 +@mock_aws class LambdaTest(unittest.TestCase): def setUp(self): diff --git a/source/lambda/schema/package-lock.json b/source/lambda/schema/package-lock.json index e682292c4..42d3f34e7 100644 --- a/source/lambda/schema/package-lock.json +++ b/source/lambda/schema/package-lock.json @@ -1,12 +1,12 @@ { "name": "schema", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "schema", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "devDependencies": { "jest": "^29.7.0" diff --git a/source/lambda/schema/package.json b/source/lambda/schema/package.json index 245ce181e..e636020ac 100644 --- a/source/lambda/schema/package.json +++ b/source/lambda/schema/package.json @@ -1,6 +1,6 @@ { "name": "schema", - "version": "6.0.3", + "version": "6.1.0", "description": "Lambda function used to provide the schemas for the various qid types", "repository": { "type": "git", diff --git a/source/lambda/schema/qna.js b/source/lambda/schema/qna.js index 57267eddb..ec4dd5d37 100644 --- a/source/lambda/schema/qna.js +++ b/source/lambda/schema/qna.js @@ -247,7 +247,7 @@ module.exports = { properties: { responsebot_hook: { title: 'Elicit Response: ResponseBot Hook', - description: 'To capture the next utterance as a response, provide the name of a Lex bot to parse the response and return at least one slot value, e.g. (QNAYesNo, QNADate, etc.). For Lex V2 use "lexv2::Botid/BotAliasId/LocaleId". For Lex V1 use a bot name starting with "QNA".', + description: 'To capture the next utterance as a response, provide the name of a Lex bot to parse the response and return at least one slot value, e.g. (QNAYesNo, QNADate, etc.). For Lex V2 use "lexv2::Botid/BotAliasId/LocaleId".', type: 'string', maxLength: 100, propertyOrder: 0, @@ -282,8 +282,8 @@ module.exports = { propertyOrder: 18, properties: { specialty_bot: { - title: 'Bot Routing: LexV1 BotName OR lexv2::Botid/BotAliasId/LocaleId OR Lambda Function', - description: 'The target specialty Lex Bot or Lambda Function to route requests to. For Lex V2 bot names use the format "lexv2::BotId/BotAliasId/LocaleId". For Lex V1 bot the names should start with "QNA". Lambda functions can be specified as "Lambda::FunctionName" or "Lambda::FunctionARN" - Lambda function names must start with "QNA-".', + title: 'Bot Routing: lexv2::Botid/BotAliasId/LocaleId OR Lambda Function', + description: 'The target specialty Lex Bot or Lambda Function to route requests to. For Lex V2 bot names use the format "lexv2::BotId/BotAliasId/LocaleId". Lambda functions can be specified as "Lambda::FunctionName" or "Lambda::FunctionARN" - Lambda function names must start with "QNA-".', type: 'string', maxLength: 100, propertyOrder: 0, @@ -295,13 +295,6 @@ module.exports = { maxLength: 100, propertyOrder: 1, }, - specialty_bot_alias: { - title: 'The Bot alias to use for the Specialty Bot. (Required for other Lex/QnA Bot targets - Not utilized when Lambda Function is used.)', - description: 'For Lex V2 leave empty. For Lex V1 specialty bots, enter a string for the Specialty Bot\'s Lex alias.', - type: 'string', - maxLength: 100, - propertyOrder: 2, - }, specialty_bot_session_attributes_to_merge: { title: 'Session attributes to forward to a Lex specialty bot.', description: 'An optional comma separated list of session attributes to pass to a Lex specialty bot. Default is an empty string.', diff --git a/source/lambda/solution-helper/.coveragerc b/source/lambda/solution-helper/.coveragerc index a9cdba2c8..6b58a5717 100644 --- a/source/lambda/solution-helper/.coveragerc +++ b/source/lambda/solution-helper/.coveragerc @@ -3,12 +3,8 @@ omit = test/* .venv-*/* */__init__.py - certifi/* - charset_normalizer/* - crhelper/* - idna/* - requests/* - urllib3/* - ./test_lambda_function.py + py_modules/* + .pytest_cache/* + __pycache__/* source = . \ No newline at end of file diff --git a/source/lambda/solution-helper/.gitignore b/source/lambda/solution-helper/.gitignore deleted file mode 100755 index 281c161c6..000000000 --- a/source/lambda/solution-helper/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -# exclude python 3rd party modules -*.dist-info/ -bin -certifi/ -charset_normalizer/ -crhelper/ -idna/ -requests/ -## crhelper tests directory -tests/ -urllib3/ diff --git a/source/lambda/solution-helper/README.md b/source/lambda/solution-helper/README.md new file mode 100644 index 000000000..7d1c3066d --- /dev/null +++ b/source/lambda/solution-helper/README.md @@ -0,0 +1,11 @@ +# Solution Helper Lambda +This lambda handles sending anonymized operational metrics to AWS. The sample data collection: +``` +{'InstallLexResponseBots': 'true', 'EmbeddingsBedrockModelId': 'amazon.titan-embed-text-v1', 'PublicOrPrivate': 'PRIVATE', 'LLMApi': 'BEDROCK', 'OpenSearchEBSVolumeSize': '10', 'LexBotVersion': 'LexV2 Only', 'EmbeddingsApi': 'BEDROCK', 'Language': 'English', 'Version': 'v6.1.0', 'OpenSearchNodeCount': '1', 'LLMBedrockModelId': 'anthropic.claude-instant-v1', 'Region': 'us-east-1', 'OpenSearchInstanceType': 'm6g.large.search', 'FulfillmentConcurrency': '1', 'RequestType': 'Delete', 'BEDROCK_GUARDRAIL_ENABLE': 'false', 'ENABLE_MULTI_LANGUAGE_SUPPORT': 'false', 'LLM_GENERATE_QUERY_ENABLE': 'true', 'KNOWLEDGE_BASE_SEARCH_TYPE': 'DEFAULT', 'PII_REJECTION_ENABLED': 'false', 'EMBEDDINGS_ENABLE': 'true', 'LLM_QA_ENABLE': 'true'} +``` + +## Tests +Unit test are run using: +```shell +python -m pytest +``` diff --git a/source/lambda/solution-helper/lambda_function.py b/source/lambda/solution-helper/lambda_function.py index 34d965517..c24ecd3d8 100644 --- a/source/lambda/solution-helper/lambda_function.py +++ b/source/lambda/solution-helper/lambda_function.py @@ -11,21 +11,59 @@ # and limitations under the License. # ###################################################################################################################### +import json import os import sys root = os.environ["LAMBDA_TASK_ROOT"] + "/py_modules" sys.path.insert(0, root) import logging, uuid, requests +import boto3 +from botocore.exceptions import ClientError from copy import copy from crhelper import CfnResource -from datetime import datetime +from datetime import datetime, timezone logger = logging.getLogger(__name__) helper = CfnResource(json_logging=True, log_level="INFO") REQUST_TIMEOUT = 10 # in seconds +ssm_client = boto3.client('ssm') +solution_parameter = os.environ["SOLUTION_PARAMETER"] +custom_settings_parameter = os.environ["CUSTOM_SETTINGS"] + +def get_parameter(parameter_name): + try: + response = ssm_client.get_parameter( + Name=parameter_name, + WithDecryption=True + ) + parameter_value = response['Parameter']['Value'] + print(f"Current value of {parameter_name}: {parameter_value}") + return parameter_value + except ClientError as e: + message = e.response['Error']['Message'] + code = e.response['Error']['Code'] + logger.exception(f"Error while getting parameter {parameter_name}: {code}:{message}") + raise e + +def update_parameter(parameter_name, new_parameter_value): + try: + response = ssm_client.put_parameter( + Name=parameter_name, + Value=new_parameter_value, + Type='SecureString', + Overwrite=True + ) + code = response['ResponseMetadata']['HTTPStatusCode'] + logger.info(f"Parameter updated with status {code}") + except ClientError as e: + message = e.response['Error']['Message'] + code = e.response['Error']['Code'] + logger.exception(f"Error while updating parameter {parameter_name}: {code}:{message}") + raise e + def _sanitize_data(resource_properties): # Remove ServiceToken (lambda arn) to avoid sending AccountId resource_properties.pop("ServiceToken", None) @@ -37,6 +75,22 @@ def _sanitize_data(resource_properties): return resource_properties +def custom_map(settings): + # Build a anonymized custom setting map + c_map = {} + if settings.get('BEDROCK_GUARDRAIL_IDENTIFIER') and settings.get('BEDROCK_GUARDRAIL_VERSION'): + c_map['BEDROCK_GUARDRAIL_ENABLE'] = 'true' + else: + c_map['BEDROCK_GUARDRAIL_ENABLE'] = 'false' + + c_map['ENABLE_MULTI_LANGUAGE_SUPPORT'] = settings.get('ENABLE_MULTI_LANGUAGE_SUPPORT', 'false') + c_map['LLM_GENERATE_QUERY_ENABLE'] = settings.get('LLM_GENERATE_QUERY_ENABLE', 'true') + c_map['KNOWLEDGE_BASE_SEARCH_TYPE'] = settings.get('KNOWLEDGE_BASE_SEARCH_TYPE', 'DEFAULT') + c_map['PII_REJECTION_ENABLED'] = settings.get('PII_REJECTION_ENABLED', 'false') + c_map['EMBEDDINGS_ENABLE'] = settings.get('EMBEDDINGS_ENABLE', 'true') + c_map['LLM_QA_ENABLE'] = settings.get('LLM_QA_ENABLE', 'true') + + return c_map @helper.create @helper.update @@ -51,24 +105,27 @@ def custom_resource(event, _): if request_type == "Create": random_id = str(uuid.uuid4()) helper.Data.update({"UUID": random_id}) + update_parameter(solution_parameter, random_id) elif resource == "AnonymizedMetric": try: metrics_data = _sanitize_data(copy(resource_properties)) metrics_data["RequestType"] = request_type - headers = {"Content-Type": "application/json"} - payload = { - "Solution": resource_properties["SolutionId"], - "UUID": resource_properties["UUID"], - "TimeStamp": datetime.utcnow().isoformat(), - "Data": metrics_data, - } + solutionId = resource_properties["SolutionId"] + solution_uuid = resource_properties["UUID"] + update_parameter(solution_parameter, solution_uuid) + send_metrics_request(metrics_data, solutionId, solution_uuid) - logger.info(f"Sending payload: {payload}") - response = requests.post( - "https://metrics.awssolutionsbuilder.com/generic", json=payload, headers=headers, timeout=REQUST_TIMEOUT - ) - logger.info(f"Response from metrics endpoint: {response.status_code} {response.reason}") + # also send the settings as 'event': 'UPDATE_SETTINGS' + try: + custom_settings = get_parameter(custom_settings_parameter) + custom_settings_data = json.loads(custom_settings) + custom_data = custom_map(custom_settings_data) + custom_data["event"]="UPDATE_SETTINGS" + send_metrics_request(custom_data, solutionId, solution_uuid) + except (ValueError, TypeError): + print("Error parsing custom settings, skipping custom data sending.") + except requests.exceptions.RequestException: logger.exception("Could not send usage data") except KeyError: @@ -76,6 +133,28 @@ def custom_resource(event, _): else: raise ValueError(f"Unknown resource: {resource}") +def send_metrics_request(metrics_data, solutionId, solution_uuid): + headers = {"Content-Type": "application/json"} + payload = { + "Solution": solutionId, + "UUID": solution_uuid, + "TimeStamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f"), + "Data": metrics_data, + } + + logger.info(f"Sending payload: {payload}") + response = requests.post( + "https://metrics.awssolutionsbuilder.com/generic", json=payload, headers=headers, timeout=REQUST_TIMEOUT + ) + logger.info(f"Response from metrics endpoint: {response.status_code} {response.reason}") + def handler(event, context): - helper(event, context) + logger.info(f"Received event: {event}") + if "ResourceProperties" in event: + helper(event, context) + else: + if "event" in event: + solutionId = os.environ["SOLUTION_ID"] + solution_uuid = get_parameter(solution_parameter) + send_metrics_request(event, solutionId, solution_uuid) \ No newline at end of file diff --git a/source/lambda/solution-helper/pytest.ini b/source/lambda/solution-helper/pytest.ini new file mode 100644 index 000000000..54fc9ba9d --- /dev/null +++ b/source/lambda/solution-helper/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +testpaths = test \ No newline at end of file diff --git a/source/lambda/solution-helper/requirements-test.txt b/source/lambda/solution-helper/requirements-test.txt index 9dab1c638..c79e0de46 100644 --- a/source/lambda/solution-helper/requirements-test.txt +++ b/source/lambda/solution-helper/requirements-test.txt @@ -1,6 +1,7 @@ boto3 -botocore==1.31.68 +botocore==1.35.5 coverage -pytest~=7.4.2 -pytest-cov~=4.1.0 +pytest~=8.3.2 +pytest-cov~=5.0.0 mock~=5.1.0 +moto~=5.0.13 \ No newline at end of file diff --git a/source/lambda/solution-helper/requirements.txt b/source/lambda/solution-helper/requirements.txt index 8fc40dd51..beef49866 100644 --- a/source/lambda/solution-helper/requirements.txt +++ b/source/lambda/solution-helper/requirements.txt @@ -1,2 +1,3 @@ crhelper==2.0.11 -requests==2.32.3 \ No newline at end of file +requests==2.32.3 +boto3 \ No newline at end of file diff --git a/source/lambda/solution-helper/conftest.py b/source/lambda/solution-helper/test/conftest.py similarity index 91% rename from source/lambda/solution-helper/conftest.py rename to source/lambda/solution-helper/test/conftest.py index 8128b2557..d6ca83813 100644 --- a/source/lambda/solution-helper/conftest.py +++ b/source/lambda/solution-helper/test/conftest.py @@ -18,3 +18,6 @@ def aws_environment_variables(): """Mocked AWS evivronment variables such as AWS credentials and region""" os.environ["LAMBDA_TASK_ROOT"] = f"{os.path.dirname(os.path.realpath(__file__))}/.." + os.environ["SOLUTION_ID"] = "SO1234" + os.environ["SOLUTION_PARAMETER"] = "some-parameter" + os.environ["CUSTOM_SETTINGS"] = "some-custom-settings" \ No newline at end of file diff --git a/source/lambda/solution-helper/test/test_lambda_function.py b/source/lambda/solution-helper/test/test_lambda_function.py new file mode 100644 index 000000000..aa64e9b39 --- /dev/null +++ b/source/lambda/solution-helper/test/test_lambda_function.py @@ -0,0 +1,220 @@ +###################################################################################################################### +# Copyright 2020-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # +# with the License. A copy of the License is located at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES # +# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # +# and limitations under the License. # +###################################################################################################################### + +import os +import boto3 +import unittest, requests +from unittest import mock +from unittest.mock import patch +from moto import mock_aws +from botocore.exceptions import ClientError + +def mocked_requests_post(*args, **kwargs): + class MockResponse: + def __init__(self, status_code, reason): + self.status_code = status_code + self.reason = reason + + return MockResponse(200, 'OK') +@mock_aws +class LambdaTest(unittest.TestCase): + def setUp(self): + self.mock_aws = mock_aws() + self.mock_aws.start() + self.ssm_client = boto3.client('ssm') + self.ssm_client.put_parameter(Name=os.environ["SOLUTION_PARAMETER"], Type="SecureString", Value='some-uuid', Overwrite=True) + + #send an empty custom settings to test the default values + self.ssm_client.put_parameter(Name=os.environ["CUSTOM_SETTINGS"], Overwrite=True, Type="String", Value='{}') + def test_create_unique_id(self): + import lambda_function + + event = { + 'RequestType': 'Create', + 'ResourceProperties': { 'Resource': 'UUID' } + } + + lambda_function.custom_resource(event, None) + self.assertIsNotNone(lambda_function.helper.Data.get('UUID')) + + @mock.patch('requests.post', side_effect=mocked_requests_post) + def test_send_metrics_successful(self, mock_post): + event = { + 'RequestType': 'Create', + 'ResourceProperties': { + 'Resource': 'AnonymizedMetric', + 'SolutionId': 'SO1234', + 'UUID': 'some-uuid', + 'Foo': 'Bar' + } + } + + from lambda_function import custom_resource + custom_resource(event, None) + + # Assert the first mock call + first_call_args = mock_post.call_args_list[0] + expected_metrics_endpoint = 'https://metrics.awssolutionsbuilder.com/generic' + actual_metrics_endpoint = first_call_args.args[0] + self.assertEqual(expected_metrics_endpoint, actual_metrics_endpoint) + + expected_headers = {'Content-Type': 'application/json'} + actual_headers = first_call_args.kwargs['headers'] + self.assertEqual(expected_headers, actual_headers) + + actual_payload = first_call_args.kwargs['json'] + self.assertIn('Solution', actual_payload) + self.assertIn('UUID', actual_payload) + self.assertIn('TimeStamp', actual_payload) + self.assertIn('Data', actual_payload) + + # Assert the default values in the payload + self.assertEqual(actual_payload['Data'], {'Foo': 'Bar', 'RequestType': 'Create'}) + + # Assert the second mock call + second_call_args = mock_post.call_args_list[1] + expected_metrics_endpoint = 'https://metrics.awssolutionsbuilder.com/generic' + actual_metrics_endpoint = second_call_args.args[0] + self.assertEqual(expected_metrics_endpoint, actual_metrics_endpoint) + + expected_headers = {'Content-Type': 'application/json'} + actual_headers = second_call_args.kwargs['headers'] + self.assertEqual(expected_headers, actual_headers) + + actual_payload = second_call_args.kwargs['json'] + self.assertIn('Solution', actual_payload) + self.assertIn('UUID', actual_payload) + self.assertIn('TimeStamp', actual_payload) + self.assertIn('Data', actual_payload) + + # Assert the payload values for the second call + self.assertEqual(actual_payload['Data'], {'BEDROCK_GUARDRAIL_ENABLE': 'false', 'ENABLE_MULTI_LANGUAGE_SUPPORT': 'false', 'LLM_GENERATE_QUERY_ENABLE': 'true', 'KNOWLEDGE_BASE_SEARCH_TYPE': 'DEFAULT', 'PII_REJECTION_ENABLED': 'false', 'EMBEDDINGS_ENABLE': 'true', 'LLM_QA_ENABLE': 'true', 'event': 'UPDATE_SETTINGS'}) + + @mock.patch('requests.post') + def test_send_metrics_connection_error(self, mock_post): + mock_post.side_effect = requests.exceptions.ConnectionError() + + event = { + 'RequestType': 'Update', + 'ResourceProperties': { + 'Resource': 'AnonymizedMetric', + 'SolutionId': 'SO1234', + 'UUID': 'some-uuid' + } + } + + try: + from lambda_function import custom_resource + custom_resource(event, None) + except requests.exceptions.RequestException: + self.fail('Exception should not be raised when metrics cannot be sent') + + @mock.patch('requests.post') + def test_send_metrics_other_error(self, mock_post): + try: + invalid_event = { + 'RequestType': 'Delete', + 'ResourceProperties': { + 'Resource': 'AnonymizedMetric', + 'UUID': 'some-uuid' + } + } + mock_parameter_value = '{}' + with patch('lambda_function.ssm_client.get_parameter') as mock_get_parameter: + mock_get_parameter.return_value = mock_parameter_value + + from lambda_function import custom_resource + custom_resource(invalid_event, None) + except requests.exceptions.RequestException: + self.fail('Exception should not be raised when metrics cannot be sent') + + def test_sanitize_data(self): + from lambda_function import _sanitize_data + + resource_properties = { + 'ServiceToken': 'lambda-fn-arn', + 'Resource': 'AnonymizedMetric', + 'SolutionId': 'SO1234', + 'UUID': 'some-uuid', + 'Region': 'us-east-1', + 'Foo': 'Bar' + } + + expected_response = { + 'Region': 'us-east-1', + 'Foo': 'Bar' + } + + actual_response = _sanitize_data(resource_properties) + self.assertCountEqual(expected_response, actual_response) + + @mock.patch('requests.post', side_effect=mocked_requests_post) + def test_send_metrics_successful_when_event(self, mock_post): + from lambda_function import handler + + event = { + 'event': 'UPDATE_SETTINGS', + 'BEDROCK_GUARDRAIL_ENABLE': 'true', + 'ENABLE_MULTI_LANGUAGE_SUPPORT': 'false', + 'LLM_GENERATE_QUERY_ENABLE': 'true', + 'KNOWLEDGE_BASE_SEARCH_TYPE': 'DEFAULT', + 'PII_REJECTION_ENABLED': 'false', + 'EMBEDDINGS_ENABLE': 'true', + 'LLM_QA_ENABLE': 'true' + } + + mock_parameter_value = "some-uuid" + with patch('lambda_function.ssm_client.get_parameter') as mock_get_parameter: + mock_get_parameter.return_value = mock_parameter_value + + + handler(event, None) + + expected_metrics_endpoint = 'https://metrics.awssolutionsbuilder.com/generic' + actual_metrics_endpoint = mock_post.call_args.args[0] + self.assertEqual(expected_metrics_endpoint, actual_metrics_endpoint) + + expected_headers = {'Content-Type': 'application/json'} + actual_headers = mock_post.call_args.kwargs['headers'] + self.assertEqual(expected_headers, actual_headers) + + actual_payload = mock_post.call_args.kwargs['json'] + self.assertIn('Solution', actual_payload) + self.assertIn('UUID', actual_payload) + self.assertIn('TimeStamp', actual_payload) + + self.assertIn('Data', actual_payload) + self.assertEqual(actual_payload['Data'], event) + + def test_get_settings_parameter_not_found(self): + parameter_name = 'unknown' + from lambda_function import get_parameter + with patch('lambda_function.ssm_client.get_parameter') as mock_get_parameter: + mock_get_parameter.side_effect = ClientError( + {'Error': {'Code': 'ParameterNotFound', 'Message': 'Parameter not found'}}, 'GetParameter') + with self.assertRaises(ClientError) as context: + get_parameter(parameter_name) + self.assertEqual(context.exception.response['Error']['Code'], 'ParameterNotFound') + self.assertEqual(context.exception.response['Error']['Message'], 'Parameter not found') + + def test_update_parameter_not_found(self): + parameter_name = 'unknown' + parameter_value = 'some-value' + from lambda_function import update_parameter + with patch('lambda_function.ssm_client.put_parameter') as mock_put_parameter: + mock_put_parameter.side_effect = ClientError( + {'Error': {'Code': 'ParameterNotFound', 'Message': 'Parameter not found'}}, 'GetParameter') + with self.assertRaises(ClientError) as context: + update_parameter(parameter_name, parameter_value) + self.assertEqual(context.exception.response['Error']['Code'], 'ParameterNotFound') + self.assertEqual(context.exception.response['Error']['Message'], 'Parameter not found') \ No newline at end of file diff --git a/source/lambda/solution-helper/test_lambda_function.py b/source/lambda/solution-helper/test_lambda_function.py deleted file mode 100644 index 2762a014e..000000000 --- a/source/lambda/solution-helper/test_lambda_function.py +++ /dev/null @@ -1,121 +0,0 @@ -###################################################################################################################### -# Copyright 2020-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # -# with the License. A copy of the License is located at # -# # -# http://www.apache.org/licenses/LICENSE-2.0 # -# # -# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES # -# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # -# and limitations under the License. # -###################################################################################################################### - -import unittest, requests -from unittest import mock - -def mocked_requests_post(*args, **kwargs): - class MockResponse: - def __init__(self, status_code, reason): - self.status_code = status_code - self.reason = reason - - return MockResponse(200, 'OK') - -class LambdaTest(unittest.TestCase): - def test_create_unique_id(self): - import lambda_function - - event = { - 'RequestType': 'Create', - 'ResourceProperties': { 'Resource': 'UUID' } - } - - lambda_function.custom_resource(event, None) - self.assertIsNotNone(lambda_function.helper.Data.get('UUID')) - - @mock.patch('requests.post', side_effect=mocked_requests_post) - def test_send_metrics_successful(self, mock_post): - event = { - 'RequestType': 'Create', - 'ResourceProperties': { - 'Resource': 'AnonymizedMetric', - 'SolutionId': 'SO1234', - 'UUID': 'some-uuid', - 'Foo': 'Bar' - } - } - - from lambda_function import custom_resource - custom_resource(event, None) - - expected_metrics_endpoint = 'https://metrics.awssolutionsbuilder.com/generic' - actual_metrics_endpoint = mock_post.call_args.args[0] - self.assertEqual(expected_metrics_endpoint, actual_metrics_endpoint) - - expected_headers = {'Content-Type': 'application/json'} - actual_headers = mock_post.call_args.kwargs['headers'] - self.assertEqual(expected_headers, actual_headers) - - actual_payload = mock_post.call_args.kwargs['json'] - self.assertIn('Solution', actual_payload) - self.assertIn('UUID', actual_payload) - self.assertIn('TimeStamp', actual_payload) - - self.assertIn('Data', actual_payload) - self.assertEqual(actual_payload['Data'], {'Foo': 'Bar', 'RequestType': 'Create'}) - - @mock.patch('requests.post') - def test_send_metrics_connection_error(self, mock_post): - mock_post.side_effect = requests.exceptions.ConnectionError() - - event = { - 'RequestType': 'Update', - 'ResourceProperties': { - 'Resource': 'AnonymizedMetric', - 'SolutionId': 'SO1234', - 'UUID': 'some-uuid' - } - } - - try: - from lambda_function import custom_resource - custom_resource(event, None) - except requests.exceptions.RequestException: - self.fail('Exception should not be raised when metrics cannot be sent') - - @mock.patch('requests.post') - def test_send_metrics_other_error(self, mock_post): - try: - invalid_event = { - 'RequestType': 'Delete', - 'ResourceProperties': { - 'Resource': 'AnonymizedMetric', - 'UUID': 'some-uuid' - } - } - - from lambda_function import custom_resource - custom_resource(invalid_event, None) - except requests.exceptions.RequestException: - self.fail('Exception should not be raised when metrics cannot be sent') - - def test_sanitize_data(self): - from lambda_function import _sanitize_data - - resource_properties = { - 'ServiceToken': 'lambda-fn-arn', - 'Resource': 'AnonymizedMetric', - 'SolutionId': 'SO1234', - 'UUID': 'some-uuid', - 'Region': 'us-east-1', - 'Foo': 'Bar' - } - - expected_response = { - 'Region': 'us-east-1', - 'Foo': 'Bar' - } - - actual_response = _sanitize_data(resource_properties) - self.assertCountEqual(expected_response, actual_response) diff --git a/source/lambda/testall/index.js b/source/lambda/testall/index.js index 60ea7cab8..642340c7e 100644 --- a/source/lambda/testall/index.js +++ b/source/lambda/testall/index.js @@ -21,52 +21,49 @@ const step = require('./lib/step'); const lex = require('./lib/lex'); const clean = require('./lib/clean'); +const outputBucket = process.env.OUTPUT_S3_BUCKET; + exports.step = async function (event, context, cb) { - console.log('step'); + console.log('Initiating TestAll'); console.log('Request', JSON.stringify(event, null, 2)); - const Bucket = event.Records[0].s3.bucket.name; + const inputBucket = event.Records[0].s3.bucket.name; const Key = decodeURI(event.Records[0].s3.object.key); - const VersionId = _.get(event, 'Records[0].s3.object.versionId'); - console.log(Bucket, Key); + const initialVersionId = _.get(event, 'Records[0].s3.object.versionId'); try { - await waitUntilObjectExists({ - client: s3, - maxWaitTime: 30 - }, { Bucket, Key, VersionId }); - const getObjCmd = new GetObjectCommand({ Bucket, Key, VersionId }); - const s3GetObj = await s3.send(getObjCmd); - const readableStream = Buffer.concat(await s3GetObj.Body.toArray()); - const config = JSON.parse(readableStream); - - if (config.status !== 'Error' && config.status !== 'Completed') { - try { - const config_redacted = { ...config, token: 'REDACTED' }; - console.log('Config:', JSON.stringify(config_redacted, null, 2)); - - switch (config.status) { - case 'Started': - await start(config); - break; - case 'InProgress': - await step(config); - break; - case 'Lex': - await lex(config); - break; - case 'Clean': - await clean(config); - break; - } - } catch (err) { - console.error('An error occured within switch cases: ', err); - config.status = 'Error'; - config.message = _.get(err, 'message', JSON.stringify(err)); - } - const putObjCmd = new PutObjectCommand({ Bucket, Key, Body: JSON.stringify(config) }) - await s3.send(putObjCmd); - } + const startResult = await getStatusAndStartNextStep(inputBucket, Key, initialVersionId, start); + const stepResult = await getStatusAndStartNextStep(outputBucket, Key, startResult.VersionId, step); + const lexResult = await getStatusAndStartNextStep(outputBucket, Key, stepResult.VersionId, lex); + await getStatusAndStartNextStep(outputBucket, Key, lexResult.VersionId, clean); } catch (error) { console.error('An error occured in S3 operations: ', error); cb(error); } }; + +async function getStatusAndStartNextStep(Bucket, Key, VersionId, nextStep) { + await waitUntilObjectExists({ + client: s3, + maxWaitTime: 30 + }, { Bucket, Key, VersionId }); + const getObjCmd = new GetObjectCommand({ Bucket, Key, VersionId }); + const s3GetObj = await s3.send(getObjCmd); + const readableStream = Buffer.concat(await s3GetObj.Body.toArray()); + const config = JSON.parse(readableStream); + + if (config.status !== 'Error' && config.status !== 'Completed') { + try { + const config_redacted = { ...config, token: 'REDACTED' }; + console.log('Config:', JSON.stringify(config_redacted, null, 2)); + await nextStep(config); + } catch (err) { + console.error('An error occured within the step '+config.status+': ', err); + config.status = 'Error'; + config.message = _.get(err, 'message', JSON.stringify(err)); + } + + const putObjCmd = new PutObjectCommand({ Bucket: outputBucket, Key, Body: JSON.stringify(config) }) + const putObjOutput = await s3.send(putObjCmd); + return putObjOutput; + } + +} \ No newline at end of file diff --git a/source/lambda/testall/jest.config.js b/source/lambda/testall/jest.config.js index dddc16129..c3f96b018 100644 --- a/source/lambda/testall/jest.config.js +++ b/source/lambda/testall/jest.config.js @@ -8,4 +8,8 @@ module.exports = { modulePaths: [ "/../aws-sdk-layer/" ] -}; \ No newline at end of file +}; + +process.env = Object.assign(process.env, { + OUTPUT_S3_BUCKET: 'contentdesigneroutputbucket' +}); \ No newline at end of file diff --git a/source/lambda/testall/lib/start.js b/source/lambda/testall/lib/start.js index b4273d2a6..1dffcac43 100644 --- a/source/lambda/testall/lib/start.js +++ b/source/lambda/testall/lib/start.js @@ -20,6 +20,7 @@ module.exports = async function (config) { config.status = 'InProgress'; config.startDate = (new Date()).toString(); config.parts = []; + config.bucket = process.env.OUTPUT_S3_BUCKET; return await load(config, { endpoint: process.env.ES_ENDPOINT, diff --git a/source/lambda/testall/package-lock.json b/source/lambda/testall/package-lock.json index c6497417b..e0919dd1e 100644 --- a/source/lambda/testall/package-lock.json +++ b/source/lambda/testall/package-lock.json @@ -1,12 +1,12 @@ { "name": "testall", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "testall", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-lex-runtime-v2": "^3.511.0" @@ -91,21 +91,22 @@ } }, "node_modules/@aws-sdk/client-lex-runtime-v2": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-runtime-v2/-/client-lex-runtime-v2-3.622.0.tgz", - "integrity": "sha512-zNc6tyx79TZ7ORSvzDFfVm2SzkcAlx3U6jcwTTbZDv+eMgNelBvYhRowQxgVIQ9briow+0BfnAOmbHEDHD+V5Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-runtime-v2/-/client-lex-runtime-v2-3.621.0.tgz", + "integrity": "sha512-UFjOmdBlu3lbTjd36VRbzInkhRyFwW3yeQM+y0O2qZY/8wHKaYkHsqNphSnpE/KAL/QusbczVKdEtpbzt2np9A==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/eventstream-handler-node": "3.620.0", "@aws-sdk/middleware-eventstream": "3.620.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-signing": "3.620.0", "@aws-sdk/middleware-user-agent": "3.620.0", "@aws-sdk/region-config-resolver": "3.614.0", "@aws-sdk/types": "3.609.0", @@ -113,7 +114,7 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/eventstream-serde-browser": "^3.0.5", "@smithy/eventstream-serde-config-resolver": "^3.0.3", "@smithy/eventstream-serde-node": "^3.0.4", @@ -122,22 +123,21 @@ "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", "@smithy/util-stream": "^3.1.3", "@smithy/util-utf8": "^3.0.0", @@ -311,13 +311,13 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.622.0.tgz", - "integrity": "sha512-DJwUqVR/O2lImbktUHOpaQ8XElNBx3JmWzTT2USg6jh3ErgG1CS6LIV+VUlgtxGl+tFN/G6AcAV8SdnnGydB8Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", + "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", + "@aws-sdk/core": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -328,26 +328,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -359,14 +359,14 @@ } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.622.0.tgz", - "integrity": "sha512-dwWDfN+S98npeY77Ugyv8VIHKRHN+n/70PWE4EgolcjaMrTINjvUh9a/SypFEs5JmBOAeCQt8S2QpM3Wvzp+pQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", + "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -377,26 +377,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -407,7 +407,7 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/abort-controller": { @@ -679,15 +679,15 @@ } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.622.0.tgz", - "integrity": "sha512-Yqtdf/wn3lcFVS42tR+zbz4HLyWxSmztjVW9L/yeMlvS7uza5nSkWqP/7ca+RxZnXLyrnA4jJtSHqykcErlhyg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", + "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -698,26 +698,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -863,15 +863,15 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.622.0.tgz", - "integrity": "sha512-q1Ct2AjPxGtQBKtDpqm1umu3f4cuWMnEHTuDa6zjjaj+Aq/C6yxLgZJo9SlcU0tMl8rUCN7oFonszfTtp4Y0MA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", + "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", "dependencies": { - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "fast-xml-parser": "4.4.1", @@ -930,16 +930,16 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.622.0.tgz", - "integrity": "sha512-VUHbr24Oll1RK3WR8XLUugLpgK9ZuxEm/NVeVqyFts1Ck9gsKpRg1x4eH7L7tW3SJ4TDEQNMbD7/7J+eoL2svg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", + "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/property-provider": "^3.1.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-stream": "^3.1.3", "tslib": "^2.6.2" @@ -1112,14 +1112,14 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.622.0.tgz", - "integrity": "sha512-cD/6O9jOfzQyo8oyAbTKnyRO89BIMSTzwaN4NxGySC6pYVTqxNSWdRwaqg/vKbwJpjbPGGYYXpXEW11kop7dlg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", + "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -1132,7 +1132,7 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/credential-provider-ini/node_modules/@smithy/types": { @@ -1147,15 +1147,15 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.622.0.tgz", - "integrity": "sha512-keldwz4Q/6TYc37JH6m43HumN7Vi+R0AuGuHn5tBV40Vi7IiqEzjpiE+yvsHIN+duUheFLL3j/o0H32jb+14DQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", + "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -1206,11 +1206,11 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.622.0.tgz", - "integrity": "sha512-zrSoBVM2JlwvkBtrcUd4J/9CrG+T+hUy9r6jwo5gonFIN3QkneR/pqpbUn/n32Zy3zlzCo2VfB31g7MjG7kJmg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", + "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", "dependencies": { - "@aws-sdk/client-sso": "3.622.0", + "@aws-sdk/client-sso": "3.621.0", "@aws-sdk/token-providers": "3.614.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -1421,6 +1421,46 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.620.0.tgz", + "integrity": "sha512-gxI7rubiaanUXaLfJ4NybERa9MGPNg2Ycl/OqANsozrBnR3Pw8vqy3EuVImQOyn2pJ2IFvl8ZPoSMHf4pX56FQ==", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing/node_modules/@smithy/protocol-http": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", + "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "dependencies": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing/node_modules/@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/middleware-user-agent": { "version": "3.620.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.620.0.tgz", @@ -3100,15 +3140,15 @@ } }, "node_modules/@smithy/core": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.2.tgz", - "integrity": "sha512-in5wwt6chDBcUv1Lw1+QzZxN9fBffi+qOixfb65yK4sDuKG7zAUO9HAFqmVzsZM3N+3tTyvZjtnDXePpvp007Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.1.tgz", + "integrity": "sha512-BC7VMXx/1BCmRPCVzzn4HGWAtsrb7/0758EtwOGFJQrlSwJBEjCcDLNZLFoL/68JexYa2s+KmgL/UfmXdG6v1w==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "tslib": "^2.6.2" @@ -3463,14 +3503,14 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.14.tgz", - "integrity": "sha512-7ZaWZJOjUxa5hgmuMspyt8v/zVsh0GXYuF7OvCmdcbVa/xbnKQoYC+uYKunAqRGTkxjOyuOCw9rmFUFOqqC0eQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/service-error-classification": "^3.0.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -3808,9 +3848,9 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -4075,12 +4115,12 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.14.tgz", - "integrity": "sha512-0iwTgKKmAIf+vFLV8fji21Jb2px11ktKVxbX6LIDPAUJyWQqGqBVfwba7xwa1f2FZUoolYQgLvxQEpJycXuQ5w==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", "dependencies": { "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -4101,15 +4141,15 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.14.tgz", - "integrity": "sha512-e9uQarJKfXApkTMMruIdxHprhcXivH1flYCe8JRDTzkkLx8dA3V5J8GZlST9yfDiRWkJpZJlUXGN9Rc9Ade3OQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", "dependencies": { "@smithy/config-resolver": "^3.0.5", "@smithy/credential-provider-imds": "^3.2.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, diff --git a/source/lambda/testall/package.json b/source/lambda/testall/package.json index 81eb33b8c..285035059 100644 --- a/source/lambda/testall/package.json +++ b/source/lambda/testall/package.json @@ -1,6 +1,6 @@ { "name": "testall", - "version": "6.0.3", + "version": "6.1.0", "description": "Lambda function that reads QnAs from opensearch and performs test validation against each question defined in qna against current Lex bot", "main": "index.js", "scripts": { diff --git a/source/lambda/testall/test/index.fixtures.js b/source/lambda/testall/test/index.fixtures.js index 8d6528202..b3268dc3f 100644 --- a/source/lambda/testall/test/index.fixtures.js +++ b/source/lambda/testall/test/index.fixtures.js @@ -15,11 +15,15 @@ const { GetObjectCommand } = require('@aws-sdk/client-s3'); const { Readable } = require("stream"); const { sdkStreamMixin } = require('@smithy/util-stream'); -function mockStream(config, s3Mock) { +function mockStream(config, s3Mock, payload = "") { const stream = new Readable(); stream.push(JSON.stringify(config)); stream.push(null); const sdkStream = sdkStreamMixin(stream); - s3Mock.on(GetObjectCommand).resolves({ Body: sdkStream }); + if (payload != "") { + s3Mock.on(GetObjectCommand, payload).resolves({ Body: sdkStream }) + } else { + s3Mock.on(GetObjectCommand).resolves({ Body: sdkStream }); + } }; exports.mockStream = mockStream; diff --git a/source/lambda/testall/test/index.test.js b/source/lambda/testall/test/index.test.js index 410441489..bd244d667 100644 --- a/source/lambda/testall/test/index.test.js +++ b/source/lambda/testall/test/index.test.js @@ -36,7 +36,7 @@ const event = { name: "testallbucket", }, object: { - key: "status/TestAll.csv", + key: "status-testall/TestAll.csv", versionId: "tLkWAhY8v2rsaSPWqg2m", } } @@ -44,8 +44,100 @@ const event = { ] }; +function generateConfigAndVersionId(currentStatus) { + const config = { status : currentStatus }; + const versionId = Math.random().toString(36).substring(3,9); + return { config: config, versionId: versionId } +} + +function initializeStartStepMocks() { + const startConfig = generateConfigAndVersionId('Started'); + s3Mock.on(PutObjectCommand, {"Body": "{\"status\":\"Started\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv"}).resolves( + { + '$metadata': { + httpStatusCode: 200, + requestId: '', + extendedRequestId: '', + cfId: undefined, + attempts: 1, + totalRetryDelay: 0 + }, + Expiration: '', + ETag: '""', + ServerSideEncryption: '', + VersionId: startConfig.versionId + }) + mockStream(startConfig.config, s3Mock, {"Bucket": "testallbucket", "Key": "status-testall/TestAll.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}) + return { versionId: startConfig.versionId, config: startConfig.config } +} + +function initializeInProgressStepMocks(startVersionId) { + const stepConfig = generateConfigAndVersionId('InProgress'); + s3Mock.on(PutObjectCommand, {"Body": "{\"status\":\"InProgress\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv"}).resolves( + { + '$metadata': { + httpStatusCode: 200, + requestId: '', + extendedRequestId: '', + cfId: undefined, + attempts: 1, + totalRetryDelay: 0 + }, + Expiration: '', + ETag: '""', + ServerSideEncryption: '', + VersionId: stepConfig.versionId + }) + mockStream(stepConfig.config, s3Mock, {"Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv", "VersionId": startVersionId}); + return { versionId: stepConfig.versionId, config: stepConfig.config } +} + +function initializeLexStepMocks(inProgressVersionId) { + const lexConfig = generateConfigAndVersionId('Lex'); + s3Mock.on(PutObjectCommand, {"Body": "{\"status\":\"Lex\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv"}).resolves( + { + '$metadata': { + httpStatusCode: 200, + requestId: '', + extendedRequestId: '', + cfId: undefined, + attempts: 1, + totalRetryDelay: 0 + }, + Expiration: '', + ETag: '""', + ServerSideEncryption: '', + VersionId: lexConfig.versionId + }) + mockStream(lexConfig.config, s3Mock, {"Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv", "VersionId": inProgressVersionId}); + return { versionId: lexConfig.versionId, config: lexConfig.config } +} + +function initializeCleanStepMocks(lexVersionId) { + const cleanConfig = generateConfigAndVersionId('Clean'); + s3Mock.on(PutObjectCommand, {"Body": "{\"status\":\"Clean\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv"}).resolves( + { + '$metadata': { + httpStatusCode: 200, + requestId: '', + extendedRequestId: '', + cfId: undefined, + attempts: 1, + totalRetryDelay: 0 + }, + Expiration: '', + ETag: '""', + ServerSideEncryption: '', + VersionId: cleanConfig.versionId + }) + mockStream(cleanConfig.config, s3Mock, {"Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv", "VersionId": lexVersionId}); + return { versionId: cleanConfig.versionId, config: cleanConfig.config } +} + + describe('when calling index function', () => { + beforeEach(() => { s3Mock.reset(); }); @@ -55,58 +147,28 @@ describe('when calling index function', () => { jest.clearAllMocks(); }); - it('should call start and update status correctly', async () => { - const config = { status : 'Started' }; - mockStream(config, s3Mock); + it('should call the different steps and update status as expected', async () => { + const startStepInfo = initializeStartStepMocks(); + const inProgressStepInfo = initializeInProgressStepMocks(startStepInfo.versionId); + const lexStepInfo = initializeLexStepMocks(inProgressStepInfo.versionId); + const cleanStepInfo = initializeCleanStepMocks(lexStepInfo.versionId); await index.step(event, null, jest.fn()); expect(start).toHaveBeenCalledTimes(1); - expect(start).toHaveBeenCalledWith(config); - expect(step).toHaveBeenCalledTimes(0); - expect(lex).toHaveBeenCalledTimes(0); - expect(clean).toHaveBeenCalledTimes(0); - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "testallbucket", "Key": "status/TestAll.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, {"Body": "{\"status\":\"Started\"}", "Bucket": "testallbucket", "Key": "status/TestAll.csv"}); - }); - - it('should call step and update status correctly', async () => { - const config = { status : 'InProgress' }; - mockStream(config, s3Mock); - await index.step(event, null, jest.fn()); + expect(start).toHaveBeenCalledWith(startStepInfo.config); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(1, GetObjectCommand, {"Bucket": "testallbucket", "Key": "status-testall/TestAll.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(1, PutObjectCommand, {"Body": "{\"status\":\"Started\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv"}); expect(step).toHaveBeenCalledTimes(1); - expect(step).toHaveBeenCalledWith(config); - expect(lex).toHaveBeenCalledTimes(0); - expect(clean).toHaveBeenCalledTimes(0); - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "testallbucket", "Key": "status/TestAll.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, {"Body": "{\"status\":\"InProgress\"}", "Bucket": "testallbucket", "Key": "status/TestAll.csv"}); - }); - - it('should call lex and update status correctly', async () => { - const config = { status : 'Lex' }; - mockStream(config, s3Mock); - await index.step(event, null, jest.fn()); + expect(step).toHaveBeenCalledWith(inProgressStepInfo.config); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(2, GetObjectCommand, {"Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv", "VersionId": startStepInfo.versionId}); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(2, PutObjectCommand, {"Body": "{\"status\":\"InProgress\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv"}); expect(lex).toHaveBeenCalledTimes(1); - expect(lex).toHaveBeenCalledWith(config); - expect(clean).toHaveBeenCalledTimes(0); - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "testallbucket", "Key": "status/TestAll.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, {"Body": "{\"status\":\"Lex\"}", "Bucket": "testallbucket", "Key": "status/TestAll.csv"}); - }); - - it('should call clean and update status correctly', async () => { - const config = { status : 'Clean' }; - mockStream(config, s3Mock); - await index.step(event, null, jest.fn()); + expect(lex).toHaveBeenCalledWith(lexStepInfo.config); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(3, GetObjectCommand, {"Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv", "VersionId": inProgressStepInfo.versionId}); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(3, PutObjectCommand, {"Body": "{\"status\":\"Lex\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv"}); expect(clean).toHaveBeenCalledTimes(1); - expect(clean).toHaveBeenCalledWith(config); - expect(s3Mock).toHaveReceivedCommandTimes(GetObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(GetObjectCommand, {"Bucket": "testallbucket", "Key": "status/TestAll.csv", "VersionId": "tLkWAhY8v2rsaSPWqg2m"}); - expect(s3Mock).toHaveReceivedCommandTimes(PutObjectCommand, 1); - expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, {"Body": "{\"status\":\"Clean\"}", "Bucket": "testallbucket", "Key": "status/TestAll.csv"}); + expect(clean).toHaveBeenCalledWith(cleanStepInfo.config); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(4,GetObjectCommand, {"Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv", "VersionId": lexStepInfo.versionId}); + expect(s3Mock).toHaveReceivedNthSpecificCommandWith(4, PutObjectCommand, {"Body": "{\"status\":\"Clean\"}", "Bucket": "contentdesigneroutputbucket", "Key": "status-testall/TestAll.csv"}); }); it('should handle an error', async () => { diff --git a/source/lambda/testall/test/lib/start.test.js b/source/lambda/testall/test/lib/start.test.js index 1f2c64f60..06178fc68 100644 --- a/source/lambda/testall/test/lib/start.test.js +++ b/source/lambda/testall/test/lib/start.test.js @@ -53,6 +53,7 @@ describe('when calling start function', () => { parts: ['part'] }; const expectedConfig = { + bucket: 'contentdesigneroutputbucket', index: 'index', filter: 'filter', status: 'InProgress', @@ -80,6 +81,7 @@ describe('when calling start function', () => { parts: ['part'] }; const expectedConfig = { + bucket: 'contentdesigneroutputbucket', index: 'index', filter: null, status: 'InProgress', diff --git a/source/lambda/translate/package-lock.json b/source/lambda/translate/package-lock.json index 75fe71d0d..d5869d48e 100644 --- a/source/lambda/translate/package-lock.json +++ b/source/lambda/translate/package-lock.json @@ -1,12 +1,12 @@ { "name": "translate", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "translate", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "devDependencies": { "aws-sdk-client-mock": "^3.0.1", diff --git a/source/lambda/translate/package.json b/source/lambda/translate/package.json index e080ba435..4fd6a70b7 100644 --- a/source/lambda/translate/package.json +++ b/source/lambda/translate/package.json @@ -1,6 +1,6 @@ { "name": "translate", - "version": "6.0.3", + "version": "6.1.0", "description": "Lambda function used to import custom terminologies into AWS Translate", "repository": { "type": "git", diff --git a/source/package-lock.json b/source/package-lock.json index 6a2fba7c6..45c63fc44 100644 --- a/source/package-lock.json +++ b/source/package-lock.json @@ -1,12 +1,12 @@ { "name": "qnabot-on-aws", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "qnabot-on-aws", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "os": [ "darwin", @@ -31,12 +31,11 @@ "@vue/compat": "^3.3.8", "@vue/eslint-config-standard": "^8.0.1", "ajv": "^6.10.2", - "alexa-sdk": "^1.0.25", "async-mutex": "^0.1.3", "autosize": "^3.0.21", "aws-lex-web-ui": "git+https://github.com/aws-samples/aws-lex-web-ui.git#feature/qnabot-sdkv3", "aws4": "^1.7.0", - "axios": "^1.6.8", + "axios": "^1.7.4", "body-parser": "^1.18.3", "bowser": "^1.9.3", "cfn-response": "^1.0.1", @@ -50,7 +49,7 @@ "express": "^4.19.2", "faker": "^4.1.0", "file-saver": "^1.3.8", - "handlebars": "^4.7.7", + "handlebars": "^4.7.8", "handlebars-loader": "^1.7.3", "highlight.js": "^10.4.1", "idle-js": "^1.2.0", @@ -77,7 +76,7 @@ "quick-lru": "^1.1.0", "range": "0.0.3", "raw-text": "^1.1.0", - "read-excel-file": "^5.7.1", + "read-excel-file": "^5.8.5", "recursive-readdir": "^2.2.2", "require-dir": "^0.3.2", "roboto-fontface": "^0.8.0", @@ -314,16 +313,16 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-cloudformation": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudformation/-/client-cloudformation-3.622.0.tgz", - "integrity": "sha512-prwXTkHJC/ESvcEBmnFMK7pMQRz5ycHokpucCOdBu47pYcOy6SxHsqckJQl/wZ7vQfVOrqy1TAzv1ByJE+C7yA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudformation/-/client-cloudformation-3.621.0.tgz", + "integrity": "sha512-GqFpLV5l/zxLuxtOa3lOr9TCObIei+CLLYoTVrO1z+q/+wvJGV/NgV0K3iYuG8+HXnTjb0WetUKPeFyOmL6dPw==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -334,26 +333,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -419,16 +418,16 @@ } }, "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.622.0.tgz", - "integrity": "sha512-VE4Mi6HMrs0Fpq8Nhgt3wBm5i7SyfTYD+FFW+Ofq1zMRWWePPqbs9HMSp6mLwynWL0SNcefYoIKqz2H/2e4mwQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.621.0.tgz", + "integrity": "sha512-FpXia5qFf6ijcNDWenVq+mP9r1LbiW/+52i9wrv2+Afi6Nn1ROf8W7St8WvE9TEZ3t78y+vis4CwqfGts+uiKA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -439,26 +438,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -470,16 +469,16 @@ } }, "node_modules/@aws-sdk/client-cognito-identity-provider": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity-provider/-/client-cognito-identity-provider-3.622.0.tgz", - "integrity": "sha512-WFFCuAQ5esGaGhPb3PyjxxhMqgUFyKM6yrG8Hsdr2mwEfXPKoMXz+s5tnk/VDfB3qZnNX+AghLT90s2GAAXLiA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity-provider/-/client-cognito-identity-provider-3.621.0.tgz", + "integrity": "sha512-Tu2m18zW87gJwme6J74p/ZrfC5eJ3kv4yXpCAkfOz1JBO0vfxdoZIkkZ94G5tuCpiS5kljwS6GXpsKOojpVXcg==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -490,26 +489,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -601,16 +600,16 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-kms": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-kms/-/client-kms-3.622.0.tgz", - "integrity": "sha512-ioNJcbFK6yQvlMaCfTzB7ltnB8pu7l2lM3vvd1fmvzc/XUnL04YTr6A7mhSY6mv4V7nW2a9hlgAJhtnthvPPnA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-kms/-/client-kms-3.621.0.tgz", + "integrity": "sha512-JFCivEF+Yvi+gAz+qIp8FLnpyDWpoZ5rYNO5lScapwJKX+EQMOxbqAWCL957fosn22xR7GoWvm78D49QKJQGpg==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -621,26 +620,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -692,16 +691,16 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-lambda": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.622.0.tgz", - "integrity": "sha512-hAR8LehlBkqFeXdqi3U46Q3zb1YO8eeEKJCe8II4r3I4bhdzFJDVXNoUZSDayDXmzmntmGqWZfihXQCmbTjdjw==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.621.0.tgz", + "integrity": "sha512-QD3FOMOLc9CQqfYOEzpTlB9LZbpN+0BrLUpc4+kNa+IheD5kes6gRRLB3Y1OLY4GIRTfPnYPTeFnW8AsSbcNzQ==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -712,7 +711,7 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/eventstream-serde-browser": "^3.0.5", "@smithy/eventstream-serde-config-resolver": "^3.0.3", "@smithy/eventstream-serde-node": "^3.0.4", @@ -721,20 +720,20 @@ "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -788,16 +787,16 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-lex-model-building-service": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-model-building-service/-/client-lex-model-building-service-3.622.0.tgz", - "integrity": "sha512-h2qwJ3q8D4+Rq/6Ihgp8tt1dY5ROPuqLKbBbXy8voCT5AK4HkRVaGgo03FZG0zpA768l67Nq05KU6w3YQysbQw==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-model-building-service/-/client-lex-model-building-service-3.621.0.tgz", + "integrity": "sha512-ltD7R8AkUSmIRGi1kQ86LhN/YQ3b+jetdH/hDT7SvPHBbGig/XotFl4Jn1FszchS9QuQc3wJB8uBHScJUDHU6g==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -808,26 +807,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -879,16 +878,16 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-lex-models-v2": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-models-v2/-/client-lex-models-v2-3.622.0.tgz", - "integrity": "sha512-CJW3V05azrjqYVaQnWlaRUzNTRGXj5NuudpIHr3VeJcKIM3XjWeqqewdpJaRNiNyKAOJHhFg0OZqitelHwcRTg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-models-v2/-/client-lex-models-v2-3.621.0.tgz", + "integrity": "sha512-Ypt2JYZLQPJLAsBbx3iX1pMgbGkSsof8rQ4FvcpIZE7MDPeo0M7AKz3X5joIny3DJYk1AjG3xdhYmyZU2VOTkA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -899,26 +898,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -971,16 +970,16 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-lex-runtime-service": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-runtime-service/-/client-lex-runtime-service-3.622.0.tgz", - "integrity": "sha512-XiMdKqWiIUjpItHfCp1sQEpMzhKnsaFNz/lrxfb+IPiCs8of63gKwpJ1tpi4DeEmuA8384VA4cU3bGAUgrpx5Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-runtime-service/-/client-lex-runtime-service-3.621.0.tgz", + "integrity": "sha512-QAE4OYDKzBucvLnhqoNaGVp8Mm75C/5rqcBdhiRoTpnOUP7DtUZRGVRnTqht9vuzJxqUvqUSUkkmtIfT/Jrl9g==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -991,26 +990,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1063,21 +1062,22 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-lex-runtime-v2": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-runtime-v2/-/client-lex-runtime-v2-3.622.0.tgz", - "integrity": "sha512-zNc6tyx79TZ7ORSvzDFfVm2SzkcAlx3U6jcwTTbZDv+eMgNelBvYhRowQxgVIQ9briow+0BfnAOmbHEDHD+V5Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lex-runtime-v2/-/client-lex-runtime-v2-3.621.0.tgz", + "integrity": "sha512-UFjOmdBlu3lbTjd36VRbzInkhRyFwW3yeQM+y0O2qZY/8wHKaYkHsqNphSnpE/KAL/QusbczVKdEtpbzt2np9A==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/eventstream-handler-node": "3.620.0", "@aws-sdk/middleware-eventstream": "3.620.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-signing": "3.620.0", "@aws-sdk/middleware-user-agent": "3.620.0", "@aws-sdk/region-config-resolver": "3.614.0", "@aws-sdk/types": "3.609.0", @@ -1085,7 +1085,7 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/eventstream-serde-browser": "^3.0.5", "@smithy/eventstream-serde-config-resolver": "^3.0.3", "@smithy/eventstream-serde-node": "^3.0.4", @@ -1094,22 +1094,21 @@ "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", - "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", "@smithy/util-stream": "^3.1.3", "@smithy/util-utf8": "^3.0.0", @@ -1160,16 +1159,16 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-opensearch": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-opensearch/-/client-opensearch-3.622.0.tgz", - "integrity": "sha512-8e/mp27WZpRi8cEr+hBkly+y++XNwpYiIGOHz2jll+E1UDUDjqoAEJt3kGaOSE02g2ffcXlJ0qjW0tZSKVzE2Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-opensearch/-/client-opensearch-3.621.0.tgz", + "integrity": "sha512-zSPQ9uV6bPrhx2TYQlRyAWi+iGmDoEgFfuMvqfPQR3e9sZeBHukcnAnBTai08dhVWz27Z6paYXaLEN3y12J7IA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1180,26 +1179,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1251,16 +1250,16 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-polly": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-polly/-/client-polly-3.622.0.tgz", - "integrity": "sha512-9KCxAqRZR9PCUALZuv5XfhRe3X1AvfWFythCEJpWtbx9FDtSBhMcxBR6vWLw/4YO7x9TPOwTMx4JYc+zMlv8Kg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-polly/-/client-polly-3.621.0.tgz", + "integrity": "sha512-piJBMyTkqcfCHlNpiTAKl7BeJvYiCUfZVfKTpUbHRn5Ijl4RMmWHfygRCcpIxnhbRkzcz+Ri/mHXbMalkSFiAA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1271,26 +1270,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1343,17 +1342,17 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-s3": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.622.0.tgz", - "integrity": "sha512-2lpvuQn/qymQPfwR2SxLyRy/Wi/RrEYpbQyoc9SYfhartw9TBY8c34yZkd8zNU7Y/KG3h+PLrCmNpncocuB3YA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.621.0.tgz", + "integrity": "sha512-YhGkd2HQTM4HCYJIAVWvfbUMpOF7XUr1W/e2LN3CFP0WTF4zcCJKesJ2iNHrExqC0Ek1+qarMxiXBK95itfjYQ==", "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-bucket-endpoint": "3.620.0", "@aws-sdk/middleware-expect-continue": "3.620.0", "@aws-sdk/middleware-flexible-checksums": "3.620.0", @@ -1361,19 +1360,19 @@ "@aws-sdk/middleware-location-constraint": "3.609.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", - "@aws-sdk/middleware-sdk-s3": "3.622.0", + "@aws-sdk/middleware-sdk-s3": "3.621.0", "@aws-sdk/middleware-signing": "3.620.0", "@aws-sdk/middleware-ssec": "3.609.0", "@aws-sdk/middleware-user-agent": "3.620.0", "@aws-sdk/region-config-resolver": "3.614.0", - "@aws-sdk/signature-v4-multi-region": "3.622.0", + "@aws-sdk/signature-v4-multi-region": "3.621.0", "@aws-sdk/types": "3.609.0", "@aws-sdk/util-endpoints": "3.614.0", "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@aws-sdk/xml-builder": "3.609.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/eventstream-serde-browser": "^3.0.5", "@smithy/eventstream-serde-config-resolver": "^3.0.3", "@smithy/eventstream-serde-node": "^3.0.4", @@ -1385,20 +1384,20 @@ "@smithy/md5-js": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-retry": "^3.0.3", "@smithy/util-stream": "^3.1.3", @@ -1451,16 +1450,16 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-ssm": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.622.0.tgz", - "integrity": "sha512-/FyBz+Fy9+72TfK0uYTUnZYdnuUNFSsUV83bIw3IOtOEumzoSxF2drq4d80cUVALDjctfDkbftN6Og1GaKlIqg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.621.0.tgz", + "integrity": "sha512-E4OM7HH9qU2TZGDrX2MlBlBr9gVgDm573Qa1CTFih58dUZyaPEOiZSYLUNOyw4nMyVLyDMR/5zQ4wAorNwKVPw==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1471,26 +1470,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1556,13 +1555,13 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.622.0.tgz", - "integrity": "sha512-DJwUqVR/O2lImbktUHOpaQ8XElNBx3JmWzTT2USg6jh3ErgG1CS6LIV+VUlgtxGl+tFN/G6AcAV8SdnnGydB8Q==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", + "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", + "@aws-sdk/core": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1573,26 +1572,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1604,14 +1603,14 @@ } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.622.0.tgz", - "integrity": "sha512-dwWDfN+S98npeY77Ugyv8VIHKRHN+n/70PWE4EgolcjaMrTINjvUh9a/SypFEs5JmBOAeCQt8S2QpM3Wvzp+pQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", + "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1622,26 +1621,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1652,7 +1651,7 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/is-array-buffer": { @@ -1736,15 +1735,15 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/client-sts": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.622.0.tgz", - "integrity": "sha512-Yqtdf/wn3lcFVS42tR+zbz4HLyWxSmztjVW9L/yeMlvS7uza5nSkWqP/7ca+RxZnXLyrnA4jJtSHqykcErlhyg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", + "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.622.0", - "@aws-sdk/core": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -1755,26 +1754,26 @@ "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", "@smithy/middleware-content-length": "^3.0.5", "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.14", - "@smithy/util-defaults-mode-node": "^3.0.14", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1826,15 +1825,15 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/core": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.622.0.tgz", - "integrity": "sha512-q1Ct2AjPxGtQBKtDpqm1umu3f4cuWMnEHTuDa6zjjaj+Aq/C6yxLgZJo9SlcU0tMl8rUCN7oFonszfTtp4Y0MA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", + "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", "dependencies": { - "@smithy/core": "^2.3.2", + "@smithy/core": "^2.3.1", "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "fast-xml-parser": "4.4.1", @@ -1850,11 +1849,11 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.622.0.tgz", - "integrity": "sha512-WXfTA1Q1bntE/KgoW+Vo2L2hgwr9YCHrfXgZLGQzCZwKQpW9iMWMxylSdn0NAHldN3fwiV/Oj6DqN0Tc8ScgNQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.621.0.tgz", + "integrity": "sha512-Q+3awvTVJSqIGRjCUQflRwKPKlZ0TfmL3EQHgFLhZZrToeBapEA62+FY+T70aTKAZZZZprlvYeFPtBloNd5ziA==", "dependencies": { - "@aws-sdk/client-cognito-identity": "3.622.0", + "@aws-sdk/client-cognito-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", "@smithy/types": "^3.3.0", @@ -1889,16 +1888,16 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.622.0.tgz", - "integrity": "sha512-VUHbr24Oll1RK3WR8XLUugLpgK9ZuxEm/NVeVqyFts1Ck9gsKpRg1x4eH7L7tW3SJ4TDEQNMbD7/7J+eoL2svg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", + "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/node-http-handler": "^3.1.4", "@smithy/property-provider": "^3.1.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-stream": "^3.1.3", "tslib": "^2.6.2" @@ -1913,14 +1912,14 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.622.0.tgz", - "integrity": "sha512-cD/6O9jOfzQyo8oyAbTKnyRO89BIMSTzwaN4NxGySC6pYVTqxNSWdRwaqg/vKbwJpjbPGGYYXpXEW11kop7dlg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", + "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -1933,7 +1932,7 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.622.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/credential-provider-ini/node_modules/tslib": { @@ -1942,15 +1941,15 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.622.0.tgz", - "integrity": "sha512-keldwz4Q/6TYc37JH6m43HumN7Vi+R0AuGuHn5tBV40Vi7IiqEzjpiE+yvsHIN+duUheFLL3j/o0H32jb+14DQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", + "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -1989,11 +1988,11 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.622.0.tgz", - "integrity": "sha512-zrSoBVM2JlwvkBtrcUd4J/9CrG+T+hUy9r6jwo5gonFIN3QkneR/pqpbUn/n32Zy3zlzCo2VfB31g7MjG7kJmg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", + "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", "dependencies": { - "@aws-sdk/client-sso": "3.622.0", + "@aws-sdk/client-sso": "3.621.0", "@aws-sdk/token-providers": "3.614.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -2033,20 +2032,20 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/credential-providers": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.622.0.tgz", - "integrity": "sha512-ImfpItaPwnwNBRG04x6iDwRAclvtW2+kSu4amGiMWF+EvnjnRTnyejAA/7rdBuxA4nwM4nb8jed0jnRkZyTu7A==", - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.622.0", - "@aws-sdk/client-sso": "3.622.0", - "@aws-sdk/client-sts": "3.622.0", - "@aws-sdk/credential-provider-cognito-identity": "3.622.0", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.621.0.tgz", + "integrity": "sha512-FQbC7I8ae/72ZekLBa45jWJ+Q3d+YPhc3bW/rCks6RrldM6RgLTGr8pTOPCxHl828ky10RjkBiBmVU818rliyw==", + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.621.0", + "@aws-sdk/client-sso": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/credential-provider-cognito-identity": "3.621.0", "@aws-sdk/credential-provider-env": "3.620.1", - "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.622.0", - "@aws-sdk/credential-provider-node": "3.622.0", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.622.0", + "@aws-sdk/credential-provider-sso": "3.621.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -2275,16 +2274,16 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.622.0.tgz", - "integrity": "sha512-tX9wZ2ALx5Ez4bkY+SvSj6DpNZ6TmY4zlsVsdgV95LZFLjNwqnZkKkS+uKnsIyLBiBp6g92JVQwnUEIp7ov2Zw==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.621.0.tgz", + "integrity": "sha512-CJrQrtKylcqvyPkRR16JmPZkHroCkWwLErQrg30ZcBPNNok8xbfX6cYqG16XDTnu4lSYzv2Yqc4w4oOBv8xerQ==", "dependencies": { "@aws-sdk/types": "3.609.0", "@aws-sdk/util-arn-parser": "3.568.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/signature-v4": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-config-provider": "^3.0.0", "@smithy/util-stream": "^3.1.3", @@ -2417,11 +2416,11 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.622.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.622.0.tgz", - "integrity": "sha512-K7ddofVNzwTFRjmLZLfs/v+hiE9m5LguajHk8WULxXQgkcDI3nPgOfmMMGuslYohaQhRwW+ic+dzYlateLUudQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.621.0.tgz", + "integrity": "sha512-u+ulCaHFveqHaTxgiYrEAyfBVP6GRKjnmDut67CtjhjslshPWYpo/ndtlCW1zc0RDne3uUeK13Pqp7dp7p1d6g==", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.622.0", + "@aws-sdk/middleware-sdk-s3": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/protocol-http": "^4.1.0", "@smithy/signature-v4": "^4.1.0", @@ -5513,15 +5512,15 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@smithy/core": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.2.tgz", - "integrity": "sha512-in5wwt6chDBcUv1Lw1+QzZxN9fBffi+qOixfb65yK4sDuKG7zAUO9HAFqmVzsZM3N+3tTyvZjtnDXePpvp007Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.1.tgz", + "integrity": "sha512-BC7VMXx/1BCmRPCVzzn4HGWAtsrb7/0758EtwOGFJQrlSwJBEjCcDLNZLFoL/68JexYa2s+KmgL/UfmXdG6v1w==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "tslib": "^2.6.2" @@ -5903,14 +5902,14 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.14.tgz", - "integrity": "sha512-7ZaWZJOjUxa5hgmuMspyt8v/zVsh0GXYuF7OvCmdcbVa/xbnKQoYC+uYKunAqRGTkxjOyuOCw9rmFUFOqqC0eQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/service-error-classification": "^3.0.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -6167,9 +6166,9 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -6334,12 +6333,12 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.14.tgz", - "integrity": "sha512-0iwTgKKmAIf+vFLV8fji21Jb2px11ktKVxbX6LIDPAUJyWQqGqBVfwba7xwa1f2FZUoolYQgLvxQEpJycXuQ5w==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", "dependencies": { "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -6359,15 +6358,15 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.14.tgz", - "integrity": "sha512-e9uQarJKfXApkTMMruIdxHprhcXivH1flYCe8JRDTzkkLx8dA3V5J8GZlST9yfDiRWkJpZJlUXGN9Rc9Ade3OQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", "dependencies": { "@smithy/config-resolver": "^3.0.5", "@smithy/credential-provider-imds": "^3.2.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, @@ -8934,31 +8933,6 @@ "prettier": "^1.18.2 || ^2.0.0" } }, - "node_modules/@vue/component-compiler-utils/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true, - "peer": true - }, - "node_modules/@vue/component-compiler-utils/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "peer": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, "node_modules/@vue/devtools-api": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.1.tgz", @@ -9594,16 +9568,6 @@ "ajv": "^6.9.1" } }, - "node_modules/alexa-sdk": { - "version": "1.0.25", - "resolved": "https://registry.npmjs.org/alexa-sdk/-/alexa-sdk-1.0.25.tgz", - "integrity": "sha512-+FVFNi+mxBZm2HL+oi5u4JTNjQ2uDs4Tp9eqcWIxL3AAD+AU4a6gWpu6LEjxIVCqaI1Ro/RyDm3mnJZA9g6G8w==", - "dependencies": { - "aws-sdk": "^2.4.7", - "i18next": "^3.4.1", - "i18next-sprintf-postprocessor": "^0.2.2" - } - }, "node_modules/amazon-cognito-auth-js": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/amazon-cognito-auth-js/-/amazon-cognito-auth-js-1.3.3.tgz", @@ -10268,6 +10232,7 @@ "version": "2.1552.0", "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1552.0.tgz", "integrity": "sha512-sRuzlCeSHXUsdLqsV/E+nPrgBn1EI3BoA38D5qfNMRcPTd9j4G8M4AyMymKyNxLoWOKLqz7xFBa801MHflGwEg==", + "dev": true, "dependencies": { "buffer": "4.9.2", "events": "1.1.1", @@ -10524,6 +10489,7 @@ "version": "4.9.2", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", @@ -10533,7 +10499,8 @@ "node_modules/aws-sdk/node_modules/ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true }, "node_modules/aws4": { "version": "1.12.0", @@ -10550,9 +10517,10 @@ } }, "node_modules/axios": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", - "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -10834,14 +10802,6 @@ "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", "dev": true }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -10850,18 +10810,6 @@ "node": "*" } }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -10924,9 +10872,7 @@ "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true, - "peer": true + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/bn.js": { "version": "5.2.1", @@ -11253,27 +11199,11 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "engines": { - "node": ">=0.10" - } - }, "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", - "engines": { - "node": ">=0.2.0" - } - }, "node_modules/builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -11486,17 +11416,6 @@ "resolved": "https://registry.npmjs.org/cfn-response/-/cfn-response-1.0.1.tgz", "integrity": "sha1-qOwDlQwGg8UUlejKaA2dwLiEsTc=" }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -13273,6 +13192,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "license": "BSD-3-Clause", "dependencies": { "readable-stream": "^2.0.2" } @@ -13372,9 +13292,10 @@ "dev": true }, "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "version": "6.5.7", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz", + "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==", + "license": "MIT", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -14544,6 +14465,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true, "engines": { "node": ">=0.4.x" } @@ -15276,31 +15198,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/fstream/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -15559,12 +15456,13 @@ "dev": true }, "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", "dependencies": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, @@ -15621,27 +15519,6 @@ "node": ">=4.0.0" } }, - "node_modules/handlebars/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "optional": true - }, - "node_modules/handlebars/node_modules/uglify-js": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.1.tgz", - "integrity": "sha512-JUPoL1jHsc9fOjVFHdQIhqEEJsQvfKDjlubcCilu8U26uZ73qOg8VsN8O1jbuei44ZPlwL7kmbAdM4tzaUvqnA==", - "optional": true, - "dependencies": { - "commander": "~2.20.3" - }, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/handlebars/node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -16112,16 +15989,6 @@ "node": ">=10.17.0" } }, - "node_modules/i18next": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-3.5.2.tgz", - "integrity": "sha1-kwOQ1cMYzqpIWLUt0OQOayA/n0E=" - }, - "node_modules/i18next-sprintf-postprocessor": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/i18next-sprintf-postprocessor/-/i18next-sprintf-postprocessor-0.2.2.tgz", - "integrity": "sha1-LkCfEENXk4Jpi2otpwzapVHWfqQ=" - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -18826,6 +18693,7 @@ "version": "0.16.0", "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "dev": true, "engines": { "node": ">= 0.6.0" } @@ -19153,8 +19021,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "peer": true, "dependencies": { "universalify": "^2.0.0" }, @@ -19166,8 +19032,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "peer": true, "engines": { "node": ">= 10.0.0" } @@ -19396,11 +19260,6 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==" - }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -20370,6 +20229,8 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "peer": true, "dependencies": { "minimist": "^1.2.6" }, @@ -20621,8 +20482,7 @@ "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" }, "node_modules/node-polyfill-webpack-plugin": { "version": "2.0.1", @@ -22588,7 +22448,8 @@ "node_modules/punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true }, "node_modules/pure-rand": { "version": "6.0.4", @@ -22766,13 +22627,14 @@ "dev": true }, "node_modules/read-excel-file": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/read-excel-file/-/read-excel-file-5.7.1.tgz", - "integrity": "sha512-cEX+y7A0TmUESjaVqDTVts3iY2YbySG5ew2TlP0qJN+H7PY+b9MqiK3pl/vNPhx112AuyLtmhfqQc5n6+U2vQw==", + "version": "5.8.5", + "resolved": "https://registry.npmjs.org/read-excel-file/-/read-excel-file-5.8.5.tgz", + "integrity": "sha512-KDDcSsI3VzXTNUBs8q7RwTYrGRE8RZgNwGUivYq13bQtMp1KJmocyBs/EiPTJaFk4I8Ri9iDF+ht2A4GUrudMg==", + "license": "MIT", "dependencies": { "@xmldom/xmldom": "^0.8.2", "fflate": "^0.7.3", - "unzipper": "^0.10.11" + "unzipper": "^0.12.2" } }, "node_modules/read-excel-file/node_modules/fflate": { @@ -23467,7 +23329,8 @@ "node_modules/sax": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", + "dev": true }, "node_modules/saxes": { "version": "5.0.1", @@ -23684,7 +23547,8 @@ "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true }, "node_modules/setprototypeof": { "version": "1.2.0", @@ -24928,14 +24792,6 @@ "integrity": "sha1-5xTZtpIR3ZU3k51Q46pXiMRCuFw=", "dev": true }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", - "engines": { - "node": "*" - } - }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", @@ -25122,6 +24978,19 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/uglify-js": { + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", + "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -25300,26 +25169,40 @@ } }, "node_modules/unzipper": { - "version": "0.10.14", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", - "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.12.3.tgz", + "integrity": "sha512-PZ8hTS+AqcGxsaQntl3IRBw65QrBI6lxzqDEL7IAo/XCEqRTKGfOX56Vea5TH9SZczRVxuzk1re04z/YjuYCJA==", + "license": "MIT", + "dependencies": { + "bluebird": "~3.7.2", "duplexer2": "~0.1.4", - "fstream": "^1.0.12", + "fs-extra": "^11.2.0", "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" + "node-int64": "^0.4.0" + } + }, + "node_modules/unzipper/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" } }, - "node_modules/unzipper/node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==" + "node_modules/unzipper/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } }, "node_modules/update-browserslist-db": { "version": "1.0.13", @@ -25371,6 +25254,7 @@ "version": "0.10.3", "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dev": true, "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" @@ -25458,6 +25342,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -26752,6 +26637,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dev": true, "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" @@ -26764,6 +26650,7 @@ "version": "11.0.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, "engines": { "node": ">=4.0" } diff --git a/source/package.json b/source/package.json index 4aecc260f..90314adad 100644 --- a/source/package.json +++ b/source/package.json @@ -1,6 +1,6 @@ { "name": "qnabot-on-aws", - "version": "6.0.3", + "version": "6.1.0", "engines": { "node": ">=18.0.0", "npm": ">=10.0.0" @@ -76,12 +76,11 @@ "@vue/compat": "^3.3.8", "@vue/eslint-config-standard": "^8.0.1", "ajv": "^6.10.2", - "alexa-sdk": "^1.0.25", "async-mutex": "^0.1.3", "autosize": "^3.0.21", "aws-lex-web-ui": "git+https://github.com/aws-samples/aws-lex-web-ui.git#feature/qnabot-sdkv3", "aws4": "^1.7.0", - "axios": "^1.6.8", + "axios": "^1.7.4", "body-parser": "^1.18.3", "bowser": "^1.9.3", "cfn-response": "^1.0.1", @@ -95,7 +94,7 @@ "express": "^4.19.2", "faker": "^4.1.0", "file-saver": "^1.3.8", - "handlebars": "^4.7.7", + "handlebars": "^4.7.8", "handlebars-loader": "^1.7.3", "highlight.js": "^10.4.1", "idle-js": "^1.2.0", @@ -122,7 +121,7 @@ "quick-lru": "^1.1.0", "range": "0.0.3", "raw-text": "^1.1.0", - "read-excel-file": "^5.7.1", + "read-excel-file": "^5.8.5", "recursive-readdir": "^2.2.2", "require-dir": "^0.3.2", "roboto-fontface": "^0.8.0", @@ -204,10 +203,12 @@ "semver@6.3.0": "^6.3.1", "semver@7.0.0 - 7.5.2": "^7.5.2", "@vue/cli-plugin-unit-jest": { - "@vue/vue3-jest": "$@vue/vue3-jest", - "postcss": "8.4.32" + "@vue/vue3-jest": "$@vue/vue3-jest" }, - "follow-redirects": "^1.15.6" + "follow-redirects": "^1.15.6", + "postcss": "^8.4.32", + "elliptic": "^6.5.7", + "uglify-js": "^3.19.2" }, "jest": { "globals": { diff --git a/source/templates/dev/__tests__/masterConfig.test.js b/source/templates/dev/__tests__/masterConfig.test.js index 37b7c9dd6..999f12d8f 100644 --- a/source/templates/dev/__tests__/masterConfig.test.js +++ b/source/templates/dev/__tests__/masterConfig.test.js @@ -53,7 +53,7 @@ describe('master template with config', () => { KendraFaqIndexId: { Default: 'test' }, AltSearchKendraIndexes: { Default: 'test' }, AltSearchKendraIndexAuth: { Default: 'test' }, - Username : { Default: 'Admin' }, + Username: { Default: 'Admin' }, XraySetting: { Default: 'TRUE' }, EmbeddingsBedrockModelId: { Default: 'test' }, LLMBedrockModelId: { Default: 'test' }, @@ -65,9 +65,9 @@ describe('master template with config', () => { VPCSubnetIdList : { Default: 'vpc-subnet-test' }, VPCSecurityGroupIdList : { Default: 'sg-test' }, OpenSearchInstanceType : { Default: 'm6g.large.search' }, - LexBotVersion: { Default: 'LexV2 Only' }, FulfillmentConcurrency: { Default: 1 }, LexV2BotLocaleIds: { Default: 'en_US,es_US,fr_CA' }, + LogRetentionPeriod: { Default: 0 }, EmbeddingsApi: { Default: 'SAGEMAKER' }, LLMApi: { Default: 'SAGEMAKER' }, InstallLexResponseBots: { Default: true }, diff --git a/source/templates/dev/__tests__/masterNoConfig.test.js b/source/templates/dev/__tests__/masterNoConfig.test.js index b0d89599e..9a31cd5ef 100644 --- a/source/templates/dev/__tests__/masterNoConfig.test.js +++ b/source/templates/dev/__tests__/masterNoConfig.test.js @@ -55,9 +55,9 @@ describe('master template with config', () => { KendraFaqIndexId: { Default: 'test' }, AltSearchKendraIndexes: { Default: 'test' }, AltSearchKendraIndexAuth: { Default: 'test' }, - LexBotVersion: { Default: 'test' }, FulfillmentConcurrency: { Default: 'test' }, LexV2BotLocaleIds: { Default: 'test' }, + LogRetentionPeriod: { Default: 0 }, EmbeddingsApi: { Default: 'test' }, LLMApi: { Default: 'test' }, EmbeddingsBedrockModelId: { Default: 'test' }, diff --git a/source/templates/dev/__tests__/mockConfigFull.json b/source/templates/dev/__tests__/mockConfigFull.json index 5b119e246..e30ddd0d3 100644 --- a/source/templates/dev/__tests__/mockConfigFull.json +++ b/source/templates/dev/__tests__/mockConfigFull.json @@ -9,7 +9,6 @@ "devPublicOrPrivate": "PRIVATE", "devLanguage": "English", "namespace": "dev", - "LexBotVersion": "LexV2 Only", "LexV2BotLocaleIds": "en_US,es_US,fr_CA", "stackNamePrefix": "QNA", "skipCheckTemplate": false, @@ -21,6 +20,7 @@ "EmbeddingsBedrockModelId": "test", "LLMApi": "SAGEMAKER", "LLMBedrockModelId": "test", + "LogRetentionPeriod": 0, "BedrockKnowledgeBaseId": "test", "BedrockKnowledgeBaseModel": "anthropic.claude-instant-v1", "InstallLexResponseBots": true, diff --git a/source/templates/dev/__tests__/mockMaster.js b/source/templates/dev/__tests__/mockMaster.js index 3ab46963b..b9fb3b928 100644 --- a/source/templates/dev/__tests__/mockMaster.js +++ b/source/templates/dev/__tests__/mockMaster.js @@ -30,9 +30,6 @@ module.exports = { AltSearchKendraIndexAuth: { Default: 'test', }, - LexBotVersion: { - Default: 'test', - }, FulfillmentConcurrency: { Default: 'test', }, @@ -78,6 +75,9 @@ module.exports = { LLMLambdaArn: { Default: '0000000000000000000000000000000000000:function:test', }, + LogRetentionPeriod: { + Default: 0 + }, VPCSubnetIdList: { Default: 'test', }, diff --git a/source/templates/dev/master.js b/source/templates/dev/master.js index 3d748fa92..8be18aac2 100644 --- a/source/templates/dev/master.js +++ b/source/templates/dev/master.js @@ -35,11 +35,11 @@ module.exports = Promise.all([ base.Parameters.EmbeddingsLambdaArn.Default = config.EmbeddingsLambdaArn ? config.EmbeddingsLambdaArn : base.Parameters.EmbeddingsLambdaArn.Default; base.Parameters.LLMSagemakerInstanceType.Default = config.LLMSagemakerInstanceType ? config.LLMSagemakerInstanceType : base.Parameters.LLMSagemakerInstanceType.Default; base.Parameters.LLMLambdaArn.Default = config.LLMLambdaArn ? config.LLMLambdaArn : base.Parameters.LLMLambdaArn.Default; + base.Parameters.LogRetentionPeriod.Default = config.LogRetentionPeriod ? config.LogRetentionPeriod : base.Parameters.LogRetentionPeriod.Default; base.Parameters.ApprovedDomain.Default = config.ApprovedDomain ? config.ApprovedDomain : base.Parameters.ApprovedDomain.Default; base.Parameters.OpenSearchInstanceType.Default = config.OpenSearchInstanceType ? config.OpenSearchInstanceType : base.Parameters.OpenSearchInstanceType.Default; base.Parameters.VPCSubnetIdList.Default = config.VPCSubnetIdList ? config.VPCSubnetIdList : base.Parameters.VPCSubnetIdList.Default; base.Parameters.VPCSecurityGroupIdList.Default = config.VPCSecurityGroupIdList ? config.VPCSecurityGroupIdList : base.Parameters.VPCSecurityGroupIdList.Default; - base.Parameters.LexBotVersion.Default = config.LexBotVersion ? config.LexBotVersion : base.Parameters.LexBotVersion.Default; base.Parameters.FulfillmentConcurrency.Default = config.FulfillmentConcurrency ? config.FulfillmentConcurrency : base.Parameters.FulfillmentConcurrency.Default; base.Parameters.LexV2BotLocaleIds.Default = config.LexV2BotLocaleIds ? config.LexV2BotLocaleIds : base.Parameters.LexV2BotLocaleIds.Default; base.Parameters.EmbeddingsApi.Default = config.EmbeddingsApi ? config.EmbeddingsApi : base.Parameters.EmbeddingsApi.Default; diff --git a/source/templates/examples/__snapshots__/index.test.js.snap b/source/templates/examples/__snapshots__/index.test.js.snap index 1e0d85f78..962143008 100644 --- a/source/templates/examples/__snapshots__/index.test.js.snap +++ b/source/templates/examples/__snapshots__/index.test.js.snap @@ -12,21 +12,15 @@ exports[`renders examples template correctly 1`] = ` "true", ], }, - "CreateLexV1Bots": { - "Fn::Equals": [ - { - "Ref": "LexBotVersion", - }, - "LexV1 and LexV2", - ], - }, - "CreateLexV1ResponseBots": { - "Fn::And": [ - { - "Condition": "CreateLexResponseBots", - }, + "LogRetentionPeriodIsNotZero": { + "Fn::Not": [ { - "Condition": "CreateLexV1Bots", + "Fn::Equals": [ + { + "Ref": "LogRetentionPeriod", + }, + 0, + ], }, ], }, @@ -54,14 +48,6 @@ exports[`renders examples template correctly 1`] = ` "Description": "(SO0189n-example) QnABot nested example resources - Version vx.x.x", "Mappings": {}, "Outputs": { - "EXTCanvasLMSHook": { - "Value": { - "Fn::GetAtt": [ - "EXTCanvasLMSHook", - "Arn", - ], - }, - }, "EXTCreateRecentTopicsResponse": { "Value": { "Fn::GetAtt": [ @@ -762,8 +748,8 @@ exports[`renders examples template correctly 1`] = ` "InstallLexResponseBots": { "Type": "String", }, - "LexBotVersion": { - "Type": "String", + "LogRetentionPeriod": { + "Type": "Number", }, "PrivateQnABotSettings": { "Type": "String", @@ -791,93 +777,53 @@ exports[`renders examples template correctly 1`] = ` }, }, "Resources": { - "AgeAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNAAge", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAAge", + "BotBrokerLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], }, - "description": "QNA Age Alias - x.x.x - v1", - "name": "live", }, - "Type": "Custom::LexAlias", - }, - "AgeIntent": { - "Condition": "CreateLexV1ResponseBots", "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}", + }, + "ExamplePYTHONLambdaBotBroker", + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], }, - "conclusionStatement": { - "messages": [ + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", { - "content": "OK. ", - "contentType": "PlainText", + "Ref": "LogRetentionPeriod", }, - ], - }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ { - "content": "Is {Age} correct (Yes or No)?", - "contentType": "PlainText", + "Ref": "AWS::NoValue", }, ], }, - "createVersion": true, - "description": "QNA Age Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNAAgeIntent-\${AWS::StackName}", - }, - "rejectionStatement": { - "messages": [ - { - "content": "Please let me know the age again.", - "contentType": "PlainText", - }, - ], - }, - "sampleUtterances": [ - "My age is {Age}", - "Age is {Age}", - "It is {Age}", - "I am {Age}", - "I am {Age} years old", - "His age is {Age}", - "He is {Age}", - "He is {Age} years old", - "Her age is {Age}", - "She is {Age}", - "She is {Age} years old", - "{Age}", - ], - "slots": [ - { - "name": "Age", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.NUMBER", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What age?", - "contentType": "PlainText", - }, - ], - }, - }, - ], }, - "Type": "Custom::LexIntent", + "Type": "AWS::Logs::LogGroup", }, "BotRuntimeRole": { "Condition": "CreateLexResponseBots", @@ -949,21 +895,6 @@ exports[`renders examples template correctly 1`] = ` }, "Type": "AWS::IAM::Role", }, - "CodeVersionCanvasLMSHook": { - "Properties": { - "Bucket": { - "Ref": "BootstrapBucket", - }, - "BuildDate": Any, - "Key": { - "Fn::Sub": "\${BootstrapPrefix}/lambda/EXTCanvasLMSHook.zip", - }, - "ServiceToken": { - "Ref": "CFNLambda", - }, - }, - "Type": "Custom::S3Version", - }, "CodeVersionCreateRecentTopicsResponse": { "Properties": { "Bucket": { @@ -1009,242 +940,199 @@ exports[`renders examples template correctly 1`] = ` }, "Type": "Custom::S3Version", }, - "DateAliasNoConfirmV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNADateNoConfirm", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNADateNoConfirm", - }, - "description": "QNA Date No Confirm Alias - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "DateAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNADate", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNADate", + "ConnectCallbackLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], }, - "description": "QNA Date Alias - x.x.x - v1", - "name": "live", }, - "Type": "Custom::LexAlias", - }, - "DateIntent": { - "Condition": "CreateLexV1ResponseBots", "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}", + }, + "ExamplePYTHONLambdaConnectCallback", + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], ], }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", { - "content": "Is {date} correct (Yes or No)?", - "contentType": "PlainText", + "Ref": "LogRetentionPeriod", }, - ], - }, - "createVersion": true, - "description": "QNA DateIntent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNADateIntent-\${AWS::StackName}", - }, - "rejectionStatement": { - "messages": [ { - "content": "Please let me know the date again.", - "contentType": "PlainText", + "Ref": "AWS::NoValue", }, ], }, - "sampleUtterances": [ - "The date is {date}", - "The date was {date}", - "I went on {date}", - "It is {date}", - "It occurred on {date}", - "I was born on {date}", - "My birthdate is {date}", - "My date of birth is {date}", - "{date}", - ], - "slots": [ - { - "name": "date", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.DATE", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What date?", - "contentType": "PlainText", - }, - ], - }, - }, - ], }, - "Type": "Custom::LexIntent", + "Type": "AWS::Logs::LogGroup", }, - "DateIntentNoConfirm": { - "Condition": "CreateLexV1ResponseBots", + "CreateRecentTopicsResponseLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}", + }, + "EXTCreateRecentTopicsResponse", + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], }, - "conclusionStatement": { - "messages": [ + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", { - "content": "OK. ", - "contentType": "PlainText", + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", }, ], }, - "createVersion": true, - "description": "QNA DateIntentNoConfirm - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNADateIntentNoConfirm-\${AWS::StackName}", - }, - "sampleUtterances": [ - "The date is {date}", - "The date was {date}", - "I went on {date}", - "It is {date}", - "It occurred on {date}", - "I was born on {date}", - "My birthdate is {date}", - "My date of birth is {date}", - "{date}", - ], - "slots": [ - { - "name": "date", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.DATE", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What date?", - "contentType": "PlainText", - }, - ], - }, - }, - ], }, - "Type": "Custom::LexIntent", + "Type": "AWS::Logs::LogGroup", }, - "DayOfWeekAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNADayOfWeek", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNADayOfWeek", + "CustomJSHookLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], }, - "description": "QNA Day Of Week Alias - x.x.x - v1", - "name": "live", }, - "Type": "Custom::LexAlias", - }, - "DayOfWeekIntent": { - "Condition": "CreateLexV1ResponseBots", "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}", + }, + "EXTCustomJSHook", + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], }, - "conclusionStatement": { - "messages": [ + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", { - "content": "OK. ", - "contentType": "PlainText", + "Ref": "LogRetentionPeriod", }, - ], - }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ { - "content": "Is {DayOfWeek} correct (Yes or No)?", - "contentType": "PlainText", + "Ref": "AWS::NoValue", }, ], }, - "createVersion": true, - "description": "QNA Day Of Week Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", + }, + "Type": "AWS::Logs::LogGroup", + }, + "CustomPYHookLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], }, - "name": { - "Fn::Sub": "QNADayOfWeekIntent-\${AWS::StackName}", + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}", + }, + "EXTCustomPYHook", + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], }, - "rejectionStatement": { - "messages": [ + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, { - "content": "Please let me know the day again.", - "contentType": "PlainText", + "Ref": "AWS::NoValue", }, ], }, - "sampleUtterances": [ - "The day is {DayOfWeek}", - "The day was {DayOfWeek}", - "I went on {DayOfWeek}", - "It is {DayOfWeek}", - "It occurred on {DayOfWeek}", - "{DayOfWeek}", - ], - "slots": [ - { - "name": "DayOfWeek", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.DayOfWeek", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What day?", - "contentType": "PlainText", - }, - ], - }, - }, - ], }, - "Type": "Custom::LexIntent", + "Type": "AWS::Logs::LogGroup", }, - "EXTCanvasLMSHook": { + "EXTCreateRecentTopicsResponse": { "Metadata": { "cfn_nag": { "rules_to_suppress": [ @@ -1273,12 +1161,12 @@ exports[`renders examples template correctly 1`] = ` { "Ref": "BootstrapPrefix", }, - "/lambda/EXTCanvasLMSHook.zip", + "/lambda/EXTCreateRecentTopicsResponse.zip", ], ], }, "S3ObjectVersion": { - "Ref": "CodeVersionCanvasLMSHook", + "Ref": "CodeVersionCreateRecentTopicsResponse", }, }, "Environment": { @@ -1292,15 +1180,25 @@ exports[`renders examples template correctly 1`] = ` "FIREHOSE_NAME": { "Ref": "FeedbackKinesisFirehoseName", }, - "PYTHONPATH": "/var/task/py_modules:/var/runtime:/opt/python", "QUIZ_KMS_KEY": { "Ref": "QuizKey", }, - "SOLUTION_ID": "SO0189", - "SOLUTION_VERSION": "vx.x.x", }, }, - "Handler": "CanvasLMSHook.handler", + "Handler": "CreateRecentTopicsResponse.handler", + "Layers": [ + { + "Ref": "AwsSdkLayerLambdaLayer", + }, + { + "Ref": "JsLambdaHookSDKLambdaLayer", + }, + ], + "LoggingConfig": { + "LogGroup": { + "Ref": "CreateRecentTopicsResponseLogGroup", + }, + }, "MemorySize": "2048", "Role": { "Fn::GetAtt": [ @@ -1308,7 +1206,7 @@ exports[`renders examples template correctly 1`] = ` "Arn", ], }, - "Runtime": "python", + "Runtime": "nodejs", "Tags": [ { "Key": "Type", @@ -1356,124 +1254,7 @@ exports[`renders examples template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, - "EXTCreateRecentTopicsResponse": { - "Metadata": { - "cfn_nag": { - "rules_to_suppress": [ - { - "id": "W92", - "reason": "This lambda function does not require to have ReservedConcurrentExecutions", - }, - ], - }, - "guard": { - "SuppressedRules": [ - "LAMBDA_CONCURRENCY_CHECK", - "LAMBDA_INSIDE_VPC", - ], - }, - }, - "Properties": { - "Code": { - "S3Bucket": { - "Ref": "BootstrapBucket", - }, - "S3Key": { - "Fn::Join": [ - "", - [ - { - "Ref": "BootstrapPrefix", - }, - "/lambda/EXTCreateRecentTopicsResponse.zip", - ], - ], - }, - "S3ObjectVersion": { - "Ref": "CodeVersionCreateRecentTopicsResponse", - }, - }, - "Environment": { - "Variables": { - "ES_ADDRESS": { - "Ref": "ESAddress", - }, - "ES_INDEX": { - "Ref": "Index", - }, - "FIREHOSE_NAME": { - "Ref": "FeedbackKinesisFirehoseName", - }, - "QUIZ_KMS_KEY": { - "Ref": "QuizKey", - }, - }, - }, - "Handler": "CreateRecentTopicsResponse.handler", - "Layers": [ - { - "Ref": "AwsSdkLayerLambdaLayer", - }, - { - "Ref": "JsLambdaHookSDKLambdaLayer", - }, - ], - "MemorySize": "2048", - "Role": { - "Fn::GetAtt": [ - "ExtensionLambdaRole", - "Arn", - ], - }, - "Runtime": "nodejs", - "Tags": [ - { - "Key": "Type", - "Value": "LambdaHook", - }, - ], - "Timeout": 300, - "TracingConfig": { - "Fn::If": [ - "XRAYEnabled", - { - "Mode": "Active", - }, - { - "Ref": "AWS::NoValue", - }, - ], - }, - "VpcConfig": { - "Fn::If": [ - "VPCEnabled", - { - "SecurityGroupIds": { - "Fn::Split": [ - ",", - { - "Ref": "VPCSecurityGroupIdList", - }, - ], - }, - "SubnetIds": { - "Fn::Split": [ - ",", - { - "Ref": "VPCSubnetIdList", - }, - ], - }, - }, - { - "Ref": "AWS::NoValue", - }, - ], - }, - }, - "Type": "AWS::Lambda::Function", - }, - "EXTCustomJSHook": { + "EXTCustomJSHook": { "Metadata": { "cfn_nag": { "rules_to_suppress": [ @@ -1535,6 +1316,11 @@ exports[`renders examples template correctly 1`] = ` "Ref": "JsLambdaHookSDKLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "CustomJSHookLogGroup", + }, + }, "MemorySize": "2048", "Role": { "Fn::GetAtt": [ @@ -1647,6 +1433,11 @@ exports[`renders examples template correctly 1`] = ` }, }, "Handler": "CustomPYHook.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "CustomPYHookLogGroup", + }, + }, "MemorySize": "2048", "Role": { "Fn::GetAtt": [ @@ -1707,9 +1498,6 @@ exports[`renders examples template correctly 1`] = ` "Bucket": { "Ref": "AssetBucket", }, - "CanvasLMSHookPY": { - "Ref": "EXTCanvasLMSHook", - }, "CreateRecentTopicsResponseJS": { "Ref": "EXTCreateRecentTopicsResponse", }, @@ -1787,6 +1575,11 @@ exports[`renders examples template correctly 1`] = ` "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "EXTUiImportLambdaLogGroup", + }, + }, "MemorySize": "128", "Role": { "Ref": "CFNLambdaRole", @@ -1839,99 +1632,67 @@ exports[`renders examples template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, - "EXTUiImportVersion": { - "Properties": { - "Bucket": { - "Ref": "BootstrapBucket", - }, - "BuildDate": Any, - "Key": { - "Fn::Sub": "\${BootstrapPrefix}/lambda/EXTUiImports.zip", - }, - "ServiceToken": { - "Ref": "CFNLambda", - }, - }, - "Type": "Custom::S3Version", - }, - "EmailAddressAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNAEmailAddress", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAEmailAddress", + "EXTUiImportLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], }, - "description": "QNA Email Address Alias - x.x.x - v1", - "name": "live", }, - "Type": "Custom::LexAlias", - }, - "EmailAddressIntent": { - "Condition": "CreateLexV1ResponseBots", "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-EXTUiImportLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], }, - "conclusionStatement": { - "messages": [ + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", { - "content": "OK. ", - "contentType": "PlainText", + "Ref": "LogRetentionPeriod", }, - ], - }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ { - "content": "Is {EmailAddress} correct (Yes or No)?", - "contentType": "PlainText", + "Ref": "AWS::NoValue", }, ], }, - "createVersion": true, - "description": "QNA Email Address Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", + }, + "Type": "AWS::Logs::LogGroup", + }, + "EXTUiImportVersion": { + "Properties": { + "Bucket": { + "Ref": "BootstrapBucket", }, - "name": { - "Fn::Sub": "QNAEmailAddressIntent-\${AWS::StackName}", + "BuildDate": Any, + "Key": { + "Fn::Sub": "\${BootstrapPrefix}/lambda/EXTUiImports.zip", }, - "rejectionStatement": { - "messages": [ - { - "content": "Please let me know the email address again.", - "contentType": "PlainText", - }, - ], + "ServiceToken": { + "Ref": "CFNLambda", }, - "sampleUtterances": [ - "My email address is {EmailAddress}", - "The email address is {EmailAddress}", - "{EmailAddress}", - ], - "slots": [ - { - "name": "EmailAddress", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.EmailAddress", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What email address?", - "contentType": "PlainText", - }, - ], - }, - }, - ], }, - "Type": "Custom::LexIntent", + "Type": "Custom::S3Version", }, "ExampleCodeVersion": { "Properties": { @@ -2012,6 +1773,11 @@ exports[`renders examples template correctly 1`] = ` "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "QuizLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -2131,6 +1897,11 @@ exports[`renders examples template correctly 1`] = ` "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "hookLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -2440,56 +2211,6 @@ exports[`renders examples template correctly 1`] = ` }, "PolicyName": "SNSQNALambda", }, - { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "lex:PostText", - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:aws:lex:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":bot:*", - ":qna*", - ], - ], - }, - { - "Fn::Join": [ - "", - [ - "arn:aws:lex:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":bot:*", - ":QNA*", - ], - ], - }, - ], - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "LexQNALambda", - }, { "PolicyDocument": { "Statement": [ @@ -2626,6 +2347,11 @@ exports[`renders examples template correctly 1`] = ` }, }, "Handler": "py/BotBroker.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "BotBrokerLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -2743,6 +2469,11 @@ exports[`renders examples template correctly 1`] = ` }, }, "Handler": "py/ConnectCallback.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "ConnectCallbackLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -2860,6 +2591,11 @@ exports[`renders examples template correctly 1`] = ` }, }, "Handler": "py/Feedback.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "FeedbackLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -2977,6 +2713,11 @@ exports[`renders examples template correctly 1`] = ` }, }, "Handler": "py/Next.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "NextLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -3094,6 +2835,11 @@ exports[`renders examples template correctly 1`] = ` }, }, "Handler": "py/Previous.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "PreviousLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -3211,6 +2957,11 @@ exports[`renders examples template correctly 1`] = ` }, }, "Handler": "py/hello.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "helloLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -3319,6 +3070,11 @@ exports[`renders examples template correctly 1`] = ` "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ExampleWriteLambdaLogGroup", + }, + }, "MemorySize": "128", "Role": { "Ref": "CFNLambdaRole", @@ -3371,10 +3127,57 @@ exports[`renders examples template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, - "ExtensionLambdaRole": { + "ExampleWriteLambdaLogGroup": { "Metadata": { - "cfn_nag": { - "rules_to_suppress": [ + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ExampleWriteLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, + "ExtensionLambdaRole": { + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ { "id": "W11", "reason": "This IAM role requires to have * resource on its permission policy", @@ -3586,106 +3389,6 @@ exports[`renders examples template correctly 1`] = ` }, "PolicyName": "LambdaFeedbackKinesisFirehoseQNALambda", }, - { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "lex:PostText", - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:aws:lex:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":bot:*", - ":qna*", - ], - ], - }, - { - "Fn::Join": [ - "", - [ - "arn:aws:lex:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":bot:*", - ":QNA*", - ], - ], - }, - ], - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "LexQNALambda", - }, - { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "secretsmanager:GetResourcePolicy", - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret", - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:aws:secretsmanager:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":secret:qna-*", - ], - ], - }, - { - "Fn::Join": [ - "", - [ - "arn:aws:secretsmanager:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":secret:QNA-*", - ], - ], - }, - ], - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "QNASecretsManagerLambda", - }, ], }, "Type": "AWS::IAM::Role", @@ -3712,12 +3415,6 @@ exports[`renders examples template correctly 1`] = ` "Arn", ], }, - { - "Fn::GetAtt": [ - "EXTCanvasLMSHook", - "Arn", - ], - }, { "Fn::GetAtt": [ "EXTCustomPYHook", @@ -3737,6 +3434,54 @@ exports[`renders examples template correctly 1`] = ` }, "Type": "AWS::IAM::ManagedPolicy", }, + "FeedbackLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}", + }, + "ExamplePYTHONLambdaFeedback", + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "FeedbackSNS": { "Properties": { "KmsMasterKeyId": "alias/aws/sns", @@ -3913,1510 +3658,103 @@ exports[`renders examples template correctly 1`] = ` }, "Type": "Custom::QnABotExamples", }, - "MonthAliasNoConfirmV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNAMonthNoConfirm", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAMonthNoConfirm", - }, - "description": "QNA Month Alias No Confirm - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "MonthAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNAMonth", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAMonth", + "NextLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], }, - "description": "QNA Month Alias - x.x.x - v1", - "name": "live", }, - "Type": "Custom::LexAlias", - }, - "MonthIntent": { - "Condition": "CreateLexV1ResponseBots", "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}", + }, + "ExamplePYTHONLambdaNext", + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], ], }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", { - "content": "Is {Month} correct (Yes or No)?", - "contentType": "PlainText", + "Ref": "LogRetentionPeriod", }, - ], - }, - "createVersion": true, - "description": "QNA Month Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNAMonthIntent-\${AWS::StackName}", - }, - "rejectionStatement": { - "messages": [ { - "content": "Please let me know the month again.", - "contentType": "PlainText", + "Ref": "AWS::NoValue", }, ], }, - "sampleUtterances": [ - "The month is {Month}", - "The month was {Month}", - "It is {Month}", - "It occurred on {Month}", - "{Month}", - ], - "slots": [ - { - "name": "Month", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.Month", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What month?", - "contentType": "PlainText", - }, - ], - }, - }, - ], }, - "Type": "Custom::LexIntent", + "Type": "AWS::Logs::LogGroup", }, - "MonthIntentNoConfirm": { - "Condition": "CreateLexV1ResponseBots", + "PreviousLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}", + }, + "ExamplePYTHONLambdaPrevious", + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], }, - "conclusionStatement": { - "messages": [ + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, { - "content": "OK. ", - "contentType": "PlainText", + "Ref": "AWS::NoValue", }, ], }, - "createVersion": true, - "description": "QNA Month Intent No Confirm - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNAMonthIntentNoConfirm-\${AWS::StackName}", - }, - "sampleUtterances": [ - "The month is {Month}", - "The month was {Month}", - "It is {Month}", - "It occurred on {Month}", - "{Month}", - ], - "slots": [ - { - "name": "Month", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.Month", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What month?", - "contentType": "PlainText", - }, - ], - }, - }, - ], }, - "Type": "Custom::LexIntent", + "Type": "AWS::Logs::LogGroup", }, - "NameAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNAName", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAName", - }, - "description": "QNA Name Alias - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "NameIntent": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, - ], - }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ - { - "content": "Did I get your name right (Yes or No) {FirstName} {LastName}?", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Name Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNANameIntent-\${AWS::StackName}", - }, - "rejectionStatement": { - "messages": [ - { - "content": "Please let me know your name again.", - "contentType": "PlainText", - }, - ], - }, - "sampleUtterances": [ - "My last name is {LastName}", - "My first name is {FirstName}", - "My first name is {FirstName} and My last name is {LastName}", - "My name is {FirstName} {LastName}", - "I am {FirstName} {LastName}", - "{FirstName} {LastName}", - "{FirstName}", - "{LastName}", - ], - "slots": [ - { - "name": "FirstName", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.US_FIRST_NAME", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What is your first name?", - "contentType": "PlainText", - }, - ], - }, - }, - { - "name": "LastName", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.US_LAST_NAME", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What is your last name?", - "contentType": "PlainText", - }, - ], - }, - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "NumberAliasNoConfirmV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNANumberNoConfirm", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNANumberNoConfirm", - }, - "description": "QNA Number Alias No Confirm - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "NumberAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNANumber", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNANumber", - }, - "description": "QNA Number Alias - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "NumberIntent": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, - ], - }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ - { - "content": "Is {Number} correct (Yes or No)?", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Number Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNANumberIntent-\${AWS::StackName}", - }, - "rejectionStatement": { - "messages": [ - { - "content": "Please let me know the number again.", - "contentType": "PlainText", - }, - ], - }, - "sampleUtterances": [ - "The number is {Number}", - "The number was {Number}", - "It is {Number}", - "{Number}", - ], - "slots": [ - { - "name": "Number", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.NUMBER", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What number?", - "contentType": "PlainText", - }, - ], - }, - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "NumberIntentNoConfirm": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Number Intent No Confirm - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNANumberIntentNoConfirm-\${AWS::StackName}", - }, - "sampleUtterances": [ - "The number is {Number}", - "The number was {Number}", - "It is {Number}", - "{Number}", - ], - "slots": [ - { - "name": "Number", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.NUMBER", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What number?", - "contentType": "PlainText", - }, - ], - }, - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "PhoneNumberAliasNoConfirmV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNAPhoneNumberNoConfirm", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAPhoneNumberNoConfirm", - }, - "description": "QNA Phone Number Alias No Confirm - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "PhoneNumberAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNAPhoneNumber", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAPhoneNumber", - }, - "description": "QNA Phone Number Alias - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "PhoneNumberIntent": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, - ], - }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ - { - "content": "Is {PhoneNumber} correct (Yes or No)?", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Phone Number Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNAPhoneNumberIntent-\${AWS::StackName}", - }, - "rejectionStatement": { - "messages": [ - { - "content": "Please let me know the phone number again.", - "contentType": "PlainText", - }, - ], - }, - "sampleUtterances": [ - "The phone number is {PhoneNumber}", - "My phone number is {PhoneNumber}", - "It is {PhoneNumber}", - "{PhoneNumber}", - ], - "slots": [ - { - "name": "PhoneNumber", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.PhoneNumber", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What phone number?", - "contentType": "PlainText", - }, - ], - }, - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "PhoneNumberIntentNoConfirm": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Phone Number Intent No Confirm - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNAPhoneNumberIntentNoConfirm-\${AWS::StackName}", - }, - "sampleUtterances": [ - "The phone number is {PhoneNumber}", - "My phone number is {PhoneNumber}", - "It is {PhoneNumber}", - "{PhoneNumber}", - ], - "slots": [ - { - "name": "PhoneNumber", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.PhoneNumber", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What phone number?", - "contentType": "PlainText", - }, - ], - }, - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "PinAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAPin", - }, - "description": "QNA Pin Alias - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "PinIntent": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, - ], - }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ - { - "content": "Is {Pin} correct (Yes or No)?", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Pin Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNAPinIntent-\${AWS::StackName}", - }, - "rejectionStatement": { - "messages": [ - { - "content": "I'm sorry I did not get all the digits, please re-enter all digits.", - "contentType": "PlainText", - }, - ], - }, - "sampleUtterances": [ - "The pin number is {Pin}", - "My pin number is {Pin}", - "It is {Pin}", - "{Pin}", - ], - "slots": [ - { - "name": "Pin", - "priority": 1, - "slotConstraint": "Required", - "slotType": { - "Ref": "PinSlotType", - }, - "slotTypeVersion": "QNABOT-AUTO-ASSIGNED", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What are all the digits?", - "contentType": "PlainText", - }, - ], - }, - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "PinIntentNoConfirm": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Pin Intent No Confirm - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNAPinIntentNoConfirm-\${AWS::StackName}", - }, - "sampleUtterances": [ - "The pin number is {Pin}", - "My pin number is {Pin}", - "It is {Pin}", - "{Pin}", - ], - "slots": [ - { - "name": "Pin", - "priority": 1, - "slotConstraint": "Required", - "slotType": { - "Ref": "PinSlotType", - }, - "slotTypeVersion": "QNABOT-AUTO-ASSIGNED", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What are all the digits?", - "contentType": "PlainText", - }, - ], - }, - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "PinNoConfirmAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAPinNoConfirm", - }, - "description": "QNA Pin No Confirm Alias - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "PinSlotType": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "createVersion": true, - "description": "QNA Pin Slot Type - x.x.x - v1", - "name": { - "Fn::Sub": "QNAPinSlotType-\${AWS::StackName}", - }, - "parentSlotTypeSignature": "AMAZON.AlphaNumeric", - "slotTypeConfigurations": [ - { - "regexConfiguration": { - "pattern": "[0-9]{4}", - }, - }, - ], - }, - "Type": "Custom::LexSlotType", - }, - "QNAAge": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "AgeIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the age.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Age Bot - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "AgeIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNAAgeBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNADate": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "DateIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the date.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Date Bot - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "DateIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNADateBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNADateNoConfirm": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "DateIntentNoConfirm", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the date.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Date Bot No Confirm - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "DateIntentNoConfirm", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNADateBotNoConfirm-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNADayOfWeek": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "DayOfWeekIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the day of the week.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNADayOfWeek bot - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "DayOfWeekIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNADayOfWeekBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNAEmailAddress": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "EmailAddressIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the email address.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Email Address Intent - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "EmailAddressIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNAEmailAddressBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNAMonth": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "MonthIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the month.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Month Bot - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "MonthIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNAMonthBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNAMonthNoConfirm": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "MonthIntentNoConfirm", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the month.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Month Bot No Confirm - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "MonthIntentNoConfirm", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNAMonthBotNoConfirm-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNAName": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "NameIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat your first and last name?", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Name Bot - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "NameIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNANameBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNANumber": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "NumberIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the number.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Number Bot - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "NumberIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNANumberBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNANumberNoConfirm": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "NumberIntentNoConfirm", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the number.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Number Bot No Confirm - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "NumberIntentNoConfirm", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNANumberBotNoConfirm-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNAPhoneNumber": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "PhoneNumberIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the phone number.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Phone Number Bot - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "PhoneNumberIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNAPhoneNumberBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNAPhoneNumberNoConfirm": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "PhoneNumberIntentNoConfirm", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the phone number.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Phone Number Bot No Confirm - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "PhoneNumberIntentNoConfirm", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNAPhoneNumberBotNoConfirm-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNAPin": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "PinIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "I'm sorry I did not get all the digits, please re-enter all digits.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Pin elicit response - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "PinIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNAPinBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNAPinNoConfirm": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "PinIntentNoConfirm", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "I'm sorry I did not get all the digits, please re-enter all digits.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Pin No Confirm elicit response - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "PinIntentNoConfirm", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNAPinBotNoConfirm-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNASocialSecurity": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "SocialSecurityIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat your social security number.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Social Security elicit response - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "SocialSecurityIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNASocialSecurityBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNATime": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "TimeIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat the time, specifying am or pm.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Time Bot - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "TimeIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNATimeBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNAWage": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "WageIntent", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 3, - "messages": [ - { - "content": "Please repeat your wage.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Wage elicit response - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "WageIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNAWageBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNAYesNo": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": [ - "YesNoSlotType", - "YesNoIntent", - ], - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 5, - "messages": [ - { - "content": "Please repeat - say Yes or No.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Yes No Bot - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "YesNoIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNAYesNoBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QNAYesNoExit": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": [ - "YesNoExitSlotType", - "YesNoExitIntent", - ], - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I could not understand. Please start again.", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "clarificationPrompt": { - "maxAttempts": 5, - "messages": [ - { - "content": "Please repeat - say Yes or No. You can also say exit, agent, quit, or bye to leave.", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Yes No Exit Bot - x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "YesNoExitIntent", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "QNAYesNoExitBot-\${AWS::StackName}", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, - "QuizKey": { + "QuizKey": { "Properties": { "Description": "QNABot Internal KMS CMK for quiz workflow", "EnableKeyRotation": true, @@ -5444,25 +3782,73 @@ exports[`renders examples template correctly 1`] = ` "Ref": "AWS::AccountId", }, }, - "Resource": "*", - "Sid": "Allow administration of the key", + "Resource": "*", + "Sid": "Allow administration of the key", + }, + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Sub": "arn:aws:iam::\${AWS::AccountId}:root", + }, + }, + "Resource": "*", + "Sid": "Enable IAM User Permissions", + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::KMS::Key", + }, + "QuizLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}", + }, + "ExampleJSLambdaQuiz", + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", }, { - "Action": "kms:*", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Sub": "arn:aws:iam::\${AWS::AccountId}:root", - }, - }, - "Resource": "*", - "Sid": "Enable IAM User Permissions", + "Ref": "AWS::NoValue", }, ], - "Version": "2012-10-17", }, }, - "Type": "AWS::KMS::Key", + "Type": "AWS::Logs::LogGroup", }, "ResponseBotQNAAgeAliasV2": { "Condition": "CreateLexResponseBots", @@ -9494,643 +7880,124 @@ exports[`renders examples template correctly 1`] = ` { "Name": "QNAYesNoSlotType", "SlotTypeValues": [ - { - "SampleValue": { - "Value": "Yes", - }, - "Synonyms": [ - { - "Value": "Yes", - }, - { - "Value": "OK", - }, - { - "Value": "yeah", - }, - { - "Value": "sure", - }, - { - "Value": "yep", - }, - { - "Value": "affirmative", - }, - { - "Value": "aye", - }, - { - "Value": "correct", - }, - { - "Value": "one", - }, - { - "Value": "1", - }, - ], - }, - { - "SampleValue": { - "Value": "No", - }, - "Synonyms": [ - { - "Value": "no", - }, - { - "Value": "nope", - }, - { - "Value": "na", - }, - { - "Value": "negative", - }, - { - "Value": "non", - }, - { - "Value": "incorrect", - }, - { - "Value": "Two", - }, - { - "Value": "2", - }, - ], - }, - ], - "ValueSelectionSetting": { - "ResolutionStrategy": "TOP_RESOLUTION", - }, - }, - ], - "VoiceSettings": { - "VoiceId": "Salli", - }, - }, - ], - "DataPrivacy": { - "ChildDirected": false, - }, - "Description": "QNA Yes No Bot - x.x.x - v2", - "IdleSessionTTLInSeconds": "300", - "Name": { - "Fn::Sub": "ResponseBot-QNAYesNoV2-\${AWS::StackName}", - }, - "RoleArn": { - "Fn::GetAtt": [ - "BotRuntimeRole", - "Arn", - ], - }, - }, - "Type": "AWS::Lex::Bot", - }, - "ResponseBotQNAYesNoVersionV2": { - "Condition": "CreateLexResponseBots", - "DeletionPolicy": "Retain", - "DependsOn": [ - "ResponseBotQNAPinVersionV2", - "ResponseBotQNAYesNoV2", - ], - "Properties": { - "BotId": { - "Ref": "ResponseBotQNAYesNoV2", - }, - "BotVersionLocaleSpecification": [ - { - "BotVersionLocaleDetails": { - "SourceBotVersion": "DRAFT", - }, - "LocaleId": "en_US", - }, - ], - }, - "Type": "AWS::Lex::BotVersion", - "UpdateReplacePolicy": "Retain", - }, - "SocialSecurityAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNASocialSecurity", - }, - "description": "QNA Social Security Alias - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "SocialSecurityIntent": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, - ], - }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ - { - "content": "Is {SSN} correct (Yes/No)?", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Social Security Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNASocialSecurityIntent-\${AWS::StackName}", - }, - "rejectionStatement": { - "messages": [ - { - "content": "Please let me know the social security number again.", - "contentType": "PlainText", - }, - ], - }, - "sampleUtterances": [ - "The social security number is {SSN}", - "My social security number is {SSN}", - "It is {SSN}", - "{SSN}", - ], - "slots": [ - { - "name": "SSN", - "priority": 1, - "slotConstraint": "Required", - "slotType": { - "Ref": "SocialSecuritySlotType", - }, - "slotTypeVersion": "QNABOT-AUTO-ASSIGNED", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What is your social security number?", - "contentType": "PlainText", - }, - ], - }, - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "SocialSecuritySlotType": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "createVersion": true, - "description": "QNA Social Security Slot Type - x.x.x - v1", - "name": { - "Fn::Sub": "QNASocialSecuritySlotType-\${AWS::StackName}", - }, - "parentSlotTypeSignature": "AMAZON.AlphaNumeric", - "slotTypeConfigurations": [ - { - "regexConfiguration": { - "pattern": "[0-9]{3}-[0-9]{2}-[0-9]{4}", - }, - }, - ], - }, - "Type": "Custom::LexSlotType", - }, - "TimeAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNATime", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNATime", - }, - "description": "QNA Time Alias - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "TimeIntent": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, - ], - }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ - { - "content": "Is {Time} correct (Yes or No)?", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Time Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNATimeIntent-\${AWS::StackName}", - }, - "rejectionStatement": { - "messages": [ - { - "content": "Please let me know the time again.", - "contentType": "PlainText", - }, - ], - }, - "sampleUtterances": [ - "The time was {Time}", - "It occurred at {Time}", - "At {Time}", - "{Time}", - ], - "slots": [ - { - "name": "Time", - "priority": 1, - "slotConstraint": "Required", - "slotType": "AMAZON.TIME", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What time?", - "contentType": "PlainText", - }, - ], - }, - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "WageAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAWage", - }, - "description": "QNA Wage Alias - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "WageIntent": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, - ], - }, - "confirmationPrompt": { - "maxAttempts": 1, - "messages": [ - { - "content": "Is {Wage} correct (Yes/No)?", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Wage Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNAWageIntent-\${AWS::StackName}", - }, - "rejectionStatement": { - "messages": [ - { - "content": "Please let me know what your wage was again.", - "contentType": "PlainText", - }, - ], - }, - "sampleUtterances": [ - "My salary is {Wage}", - "My wage is {Wage}", - "{Wage}", - ], - "slots": [ - { - "name": "Wage", - "priority": 1, - "slotConstraint": "Required", - "slotType": { - "Ref": "WageSlotType", - }, - "slotTypeVersion": "QNABOT-AUTO-ASSIGNED", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "What is your wage?", - "contentType": "PlainText", + { + "SampleValue": { + "Value": "Yes", + }, + "Synonyms": [ + { + "Value": "Yes", + }, + { + "Value": "OK", + }, + { + "Value": "yeah", + }, + { + "Value": "sure", + }, + { + "Value": "yep", + }, + { + "Value": "affirmative", + }, + { + "Value": "aye", + }, + { + "Value": "correct", + }, + { + "Value": "one", + }, + { + "Value": "1", + }, + ], + }, + { + "SampleValue": { + "Value": "No", + }, + "Synonyms": [ + { + "Value": "no", + }, + { + "Value": "nope", + }, + { + "Value": "na", + }, + { + "Value": "negative", + }, + { + "Value": "non", + }, + { + "Value": "incorrect", + }, + { + "Value": "Two", + }, + { + "Value": "2", + }, + ], + }, + ], + "ValueSelectionSetting": { + "ResolutionStrategy": "TOP_RESOLUTION", }, - ], - }, - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "WageSlotType": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "createVersion": true, - "description": "QNA Wage Slot Type - x.x.x - v1", - "name": { - "Fn::Sub": "QNAWageSlotType-\${AWS::StackName}", - }, - "parentSlotTypeSignature": "AMAZON.AlphaNumeric", - "slotTypeConfigurations": [ - { - "regexConfiguration": { - "pattern": "[0-9]{1,7}", + }, + ], + "VoiceSettings": { + "VoiceId": "Salli", }, }, ], - }, - "Type": "Custom::LexSlotType", - }, - "YesNoAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNAYesNo", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAYesNo", - }, - "description": "QNA Yes No Alias - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "YesNoExitAliasV2": { - "Condition": "CreateLexV1ResponseBots", - "DependsOn": "QNAYesNoExit", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "botName": { - "Ref": "QNAYesNoExit", + "DataPrivacy": { + "ChildDirected": false, }, - "description": "QNA Yes No Exit Alias - x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, - "YesNoExitIntent": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", + "Description": "QNA Yes No Bot - x.x.x - v2", + "IdleSessionTTLInSeconds": "300", + "Name": { + "Fn::Sub": "ResponseBot-QNAYesNoV2-\${AWS::StackName}", }, - "conclusionStatement": { - "messages": [ - { - "content": "Ok. ", - "contentType": "PlainText", - }, + "RoleArn": { + "Fn::GetAtt": [ + "BotRuntimeRole", + "Arn", ], }, - "createVersion": true, - "description": "QNA Yes No Exit Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNAYesNoExitIntent-\${AWS::StackName}", - }, - "sampleUtterances": [ - "{Yes_No_Exit}", - "I said {Yes_No_Exit}", - ], - "slots": [ - { - "name": "Yes_No_Exit", - "priority": 1, - "slotConstraint": "Required", - "slotType": { - "Ref": "YesNoExitSlotType", - }, - "slotTypeVersion": "QNABOT-AUTO-ASSIGNED", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "Say Yes, No, or Exit.", - "contentType": "PlainText", - }, - ], - }, - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "YesNoExitSlotType": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "createVersion": true, - "description": "QNA Yes No Exit Slot Type - x.x.x - v1", - "enumerationValues": [ - { - "synonyms": [ - "yes", - "ok", - "yeah", - "sure", - "yep", - "affirmative", - "aye", - "correct", - "1", - "one", - ], - "value": "Yes", - }, - { - "synonyms": [ - "no", - "nope", - "na", - "negative", - "non", - "2", - "two", - ], - "value": "No", - }, - { - "synonyms": [ - "exit", - "agent", - "rep", - "representative", - "stop", - "quit", - "help", - "bye", - "goodbye", - "3", - "three", - ], - "value": "Exit", - }, - ], - "name": { - "Fn::Sub": "QNAYesNoExitSlotType-\${AWS::StackName}", - }, - "valueSelectionStrategy": "TOP_RESOLUTION", }, - "Type": "Custom::LexSlotType", + "Type": "AWS::Lex::Bot", }, - "YesNoIntent": { - "Condition": "CreateLexV1ResponseBots", + "ResponseBotQNAYesNoVersionV2": { + "Condition": "CreateLexResponseBots", + "DeletionPolicy": "Retain", + "DependsOn": [ + "ResponseBotQNAPinVersionV2", + "ResponseBotQNAYesNoV2", + ], "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "conclusionStatement": { - "messages": [ - { - "content": "OK. ", - "contentType": "PlainText", - }, - ], - }, - "createVersion": true, - "description": "QNA Yes No Intent - x.x.x - v1", - "fulfillmentActivity": { - "type": "ReturnIntent", - }, - "name": { - "Fn::Sub": "QNAYesNoIntent-\${AWS::StackName}", + "BotId": { + "Ref": "ResponseBotQNAYesNoV2", }, - "sampleUtterances": [ - "{Yes_No}", - "I said {Yes_No}", - ], - "slots": [ + "BotVersionLocaleSpecification": [ { - "name": "Yes_No", - "priority": 1, - "slotConstraint": "Required", - "slotType": { - "Ref": "YesNoSlotType", - }, - "slotTypeVersion": "QNABOT-AUTO-ASSIGNED", - "valueElicitationPrompt": { - "maxAttempts": 2, - "messages": [ - { - "content": "Say Yes or No.", - "contentType": "PlainText", - }, - ], + "BotVersionLocaleDetails": { + "SourceBotVersion": "DRAFT", }, + "LocaleId": "en_US", }, ], }, - "Type": "Custom::LexIntent", - }, - "YesNoSlotType": { - "Condition": "CreateLexV1ResponseBots", - "Properties": { - "ServiceToken": { - "Ref": "CFNLambda", - }, - "createVersion": true, - "description": "QNA Yes No Slot Type - x.x.x - v1", - "enumerationValues": [ - { - "synonyms": [ - "yes", - "ok", - "yeah", - "sure", - "yep", - "affirmative", - "aye", - "correct", - "1", - "one", - ], - "value": "Yes", - }, - { - "synonyms": [ - "no", - "nope", - "na", - "negative", - "non", - "2", - "two", - ], - "value": "No", - }, - ], - "name": { - "Fn::Sub": "QNAYesNoSlotType-\${AWS::StackName}", - }, - "valueSelectionStrategy": "TOP_RESOLUTION", - }, - "Type": "Custom::LexSlotType", + "Type": "AWS::Lex::BotVersion", + "UpdateReplacePolicy": "Retain", }, "feedbacksnspolicy": { "Properties": { @@ -10173,6 +8040,102 @@ exports[`renders examples template correctly 1`] = ` }, "Type": "AWS::SNS::TopicPolicy", }, + "helloLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}", + }, + "ExamplePYTHONLambdahello", + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, + "hookLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}", + }, + "ExampleJSLambdahook", + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, }, } `; diff --git a/source/templates/examples/examples/examples/PrairieLineTrailTour.json b/source/templates/examples/examples/examples/PrairieLineTrailTour.json index 36b06a693..9809afe77 100644 --- a/source/templates/examples/examples/examples/PrairieLineTrailTour.json +++ b/source/templates/examples/examples/examples/PrairieLineTrailTour.json @@ -36,7 +36,7 @@ }, { "a": "This paired sculpture and mural features a finger and thumb clasping a steel needle, followed by a trail of stitches. The title takes its inspiration from a late-1800's promotional slogan for Tacoma, and the mural elaborates on this era in Tacoma's urban development. Together, these elements tell the story of the Northern Pacific Railroad finding its end at Commencement Bay and the growth of urban Tacoma.\n\n Ask for more about the art, the artist, or the medium for additional information.", - "qid": "Where the Rails Meet the Sails", + "qid": "Where_the_Rails_Meet_the_Sails", "next": "Pressure + Flow", "q": [ "Where the Rails Meet the Sails", @@ -57,7 +57,7 @@ }, { "a": "Steel rail, reinforced steel stitching, paint on concrete", - "qid": "Where the Rails Meet the Sails: Medium", + "qid": "Where_the_Rails_Meet_the_Sails:_Medium", "q": [ "Medium", "Material", @@ -73,7 +73,7 @@ }, { "a": "Rotator Creative is an agency located in Tacoma, working at the intersection of art, advertising, and community building.\n\nLance Kagey is best known for his Beautiful Angle street-art posters. They use poetry, design, and antique typefaces to celebrate Tacoma, much like his first permanent public art piece. For Kagey, Where the Rails Meet the Sails is a meditation on how the world is an incredibly connected place.\n\nMark Alvis, whose great grandfather worked as an advertiser in Tacoma, marvels at the opportunity to use his own design skills to commemorate the efforts of his ancestor and others like him.\n\nScott Varga designs everything from websites, to hot rods, to industrial sculpture. He sees a direct connection between the coming of the railroad in 1873 and the proudly working-class, global city Tacoma has become.\n\nVisit their website at : http://www.rotatorcreative.com/", - "qid": "Where the Rails Meet the Sails: Meet the artists", + "qid": "Where_the_Rails_Meet_the_Sails:_Meet_the_artists", "q": [ "who made this", "who is the artist", @@ -89,7 +89,7 @@ }, { "a": "Where the Rails Meet the Sails is a metaphor for rails and sails being stitched together to complete the connection of the Northern Route of the Transcontinental Railroad in 1873. Here in Tacoma, trains traveled to meet the ships headed to San Francisco, Alaska, Asia, and beyond.\n\nThe needle is a piece of historic rail salvaged from the Prairie Line Trail, and the stitches are made from the same kind of heavy mooring cable used to sew cotton sails. The mural's text and title is inspired by the many marketing campaigns that sought to attract people and investment to Tacoma.\n\nThe hand holding the needle in the sculpture and mural is larger-than-life, which is fitting considering the far-reaching impacts unleashed by the decision to set the western terminus of the Northern Pacific Railroad (NPRR) in Tacoma.", - "qid": "Where the Rails Meet the Sails: About the art", + "qid": "Where_the_Rails_Meet_the_Sails:_About_the_art", "q": [ "more about the art", "about the art", @@ -104,7 +104,7 @@ }, { "a": "Commissioned by the City of Tacoma.\n\nA two-part installation, Pressure + Flow is a reflection on the power of technology and communication to transform a landscape. Pressure is a sculpture inspired by the inner workings of a steam engine, and Flow involves etched writing applied directly to the historic Prairie Line rails, excerpted from historic documents and letters.\n\n Ask for more about the art, the artist, or the medium for additional information.", - "qid": "Pressure + Flow", + "qid": "Pressure+Flow", "next": "Shipment to China", "q": [ "Pressure + Flow", @@ -125,7 +125,7 @@ }, { "a": "Steel sculpture", - "qid": "Pressure + Flow: Medium", + "qid": "Pressure+Flow:_Medium", "q": [ "Medium", "Material", @@ -141,7 +141,7 @@ }, { "a": "Matthew Dockery is a Seattle-area industrial artist who works in metal, electronics, wood and textiles. The history of technology provides the inspiration for much of his work, and he has a special love for machines, gadgets, gears that mesh properly, and history. His work has been featured on the Discovery Channel, at Greenwich Observatory in London, at the annual Burning Man festival, and around the Pacific Northwest. Dockery describes his work as “living at the intersection of gears and mad science.”\n\nWhen asked how Pressure + Flow tells the Prairie Line's story, Dockery replied, “In many ways, the railroad is Tacoma's story. It was just another small town until the Northern Pacific made it their terminus.” Dockery insists that in many ways society is still moving to the frontier: “There are still such things as real estate bubbles and speculation, risk and reward, boom and bust.”\n\nVisit his website at : http://www.attoparsec.com/", - "qid": "Pressure + Flow: Meet the artist", + "qid": "Pressure+Flow:_Meet_the_artist", "q": [ "who made this", "who is the artist", @@ -157,7 +157,7 @@ }, { "a": " Pressure + Flow reveals the hidden mechanisms, both technical and cultural, that have carried us into the present. As we travel daily in cars, bikes, and planes, it is easy to take for granted the complex machines working to get us to our destinations. Pressure unveils the inner workings of a steam-powered train engine like those used in the early railroad era, providing an opportunity to interact with the usually unseen piston and pipes.\n\nAlongside rail lines came telegraph towers, marking a revolution in communication technology. Trains transported immigrants from all over the world to Tacoma, and each traveler brought their own stories and cultures with them. Excerpts from historical documents, journals, oral histories, telegrams, and letters are etched in different languages into the remaining historical railroad tracks along the trail, representing the flow of new communities into the area alongside the original occupants of Tacoma – the Puyallup.\n\nThis artwork encourages us to look more deeply at how we arrived where we are today, and provides snapshots of the many stories embedded along the Prairie Line.\n\nPressure + Flow will be installed by Spring 2018.", - "qid": "Pressure + Flow: About the art", + "qid": "Pressure+Flow:_About_the_art", "q": [ "more about the art", "about the art", @@ -172,7 +172,7 @@ }, { "a": "Commissioned by the Chinese Reconciliation Project Foundation in partnership with the City of Tacoma.\n\nThis piece commemorates the early Chinese in America, their labors to construct the transcontinental railroads railroad construction, and their unjust suffering. It consists of an antique train truck and abstracted representation of 100 ash boxes, a reference to the Chinese workers who died while building the railroads.\n\n Ask for more about the art, the artist, or the medium for additional information.", - "qid": "Shipment to China", + "qid": "Shipment_to_China", "next": "Nexus", "q": [ "Shipment to China", @@ -192,7 +192,7 @@ }, { "a": "Bronze, antique train truck", - "qid": "Shipment to China: Medium", + "qid": "Shipment_to_China:_Medium", "q": [ "Medium", "Material", @@ -208,7 +208,7 @@ }, { "a": "A native of China, Haiying Wu was a professional sculptor before emigrating to the US. He created this piece while a graduate student at the University of Washington. A prolific artist, his work can be found in Seattle, Lynnwood, Tacoma, Redmond, and in Chengdu, in the Sichuan province of China.\n\nAccording to Wu,“This piece shows the bitterness of the Chinese experience in America during that time, for the railroad built by their efforts was the same transportation used to carry them out of Tacoma.”\n\nThanks to the Chinese Reconciliation Project Foundation for contributing this important piece for exhibition on the Prairie Line Trail, now displayed on the very tracks that the Chinese worked tirelessly to build.\n\nVisit their website at : http://www.tacomachinesepark.org/", - "qid": "Shipment to China: Meet the artist", + "qid": "Shipment_to_China:_Meet_the_artist", "q": [ "who made this", "who is the artist", @@ -224,7 +224,7 @@ }, { "a": " Shipment to China was created to commemorate the Chinese laborers who were instrumental in building the transcontinental railroad in the United States. Starting in the mid-1860's, thousands of Chinese came to the US to work on the country's expanding railroad lines. In addition to dangerous, sometimes fatal working conditions, many Chinese laborers were threatened and killed during anti-Chinese expulsion movements.\n\nAfter a Chinese worker died, the ashes of the deceased were often sent back to China in boxes, so that they could be buried next to their ancestors. This piece refers to that practice. Each “box” represents a worker. The majority of boxes are anonymous; however a few choice names and dates powerfully connect us to the past and the people who gave their lives to build the railroad and the West.\n\nAfter connecting the city to the nation by building the Northern Pacific Railroad (NPRR), many Chinese workers settled in the growing city. But national sentiment began to turn against these immigrants, and in Tacoma, the Chinese community was intentionally expelled after anti-Chinese sentiment turned violent. Led by Tacoma's Mayor, the Chinese community of 600 was driven out of town on November 3, 1885. After the riot, the Chinese District, sometimes called Little Canton, lay in smoldering ruins. This horrific event, and the complicit role of the City's leaders, led this kind of expulsion to be known as the “Tacoma Method” nation-wide.", - "qid": "Shipment to China: About the art", + "qid": "Shipment_to_China:_About_the_art", "q": [ "more about the art", "about the art", @@ -258,7 +258,7 @@ }, { "a": "Painted metal, with elements of wood, tile, and glass", - "qid": "Nexus: Medium", + "qid": "Nexus:_Medium", "q": [ "Medium", "Material", @@ -274,7 +274,7 @@ }, { "a": "Ryan Feddersen is a mixed media installation artist. Her work is characterized by a sense of exploration and experimentation. Many of her pieces utilize tongue in cheek humor accompanied by interactivity, inviting the viewer to engage with the irrationalities and hypocrisies of contemporary American culture. Feddersen is a member of the Confederated Tribes of the Colville Reservation (Okanogan / Arrow Lakes), the Interior Salish community that historically moved trade goods across the Plateau region and had especially strong relationships with the Puyallup and other Coastal Salish tribes.\n\nSpeaking about the potential of interactive art, Feddersen noted that the simple act of play can “transport you to another time, creating a connection to the deep history of a place.”.\n\nVisit her website at : http://ryanfeddersen.com/", - "qid": "Nexus: Meet the artist", + "qid": "Nexus:_Meet_the_artist", "q": [ "who made this", "who is the artist", @@ -290,7 +290,7 @@ }, { "a": "Taking inspiration from the childhood games of “playing store,” this artwork is staged as a trading space that you can step into, making room for imaginative play while also learning about the relationships between Native American tribes. The artwork references the exchange of goods, people, and cultural interactions along pre-colonial trade routes. The inter-tribal trade network was vast, but main lines connected the Pacific Northwest Coast most closely to the Subarctic, California, and Plateau—the region represented as a trade partner in the artwork.\n\nThe section of the Prairie Line Trail that this artwork occupies was historically known by the Puyallup Tribe as the Place of Many Fires, where locals and visitors came together and traded for luxurious goods like the ones seen here.\n\nNexus will be installed in Spring 2018.", - "qid": "Nexus: About the art", + "qid": "Nexus:_About_the_art", "q": [ "more about the art", "about the art", @@ -305,7 +305,7 @@ }, { "a": "The Tacoma Arts Commission and Tacoma Art Museum.\n\nAccording to Puyallup historians, Native American travelers knew the tough part of their journey lay behind them when they were greeted by a welcome figure like this on the shores of Puget Sound. Carved by Qwalsius (Shaun Peterson), in a style unique to the Puyallup People, spuy'elepebS Welcome Figure is a modern take on a local traditional art form.\n\n Ask for more about the art, the artist, historical context, or the medium for additional information", - "qid": "Welcome Figure", + "qid": "Welcome_Figure", "next": "Maru", "q": [ "Welcome Figure", @@ -324,7 +324,7 @@ }, { "a": "Western Red Cedar, exterior latex paint textured by a traditional adze method, chisels, and knives", - "qid": "Welcome Figure: Medium", + "qid": "Welcome_Figure:_Medium", "q": [ "Medium", "Material", @@ -340,7 +340,7 @@ }, { "a": "Qwalsius (Shaun Peterson) is a prolific Puyallup artist and a towering presence in the movement to revive Coast Salish Art traditions. He carved Welcome Figure in 2010. Qwalsius works in many art forms, from carving, to painting, to printing — always inspired by his heritage. His pieces mix tradition with innovation. His works have graced exhibitions in New Zealand, China, Japan, and throughout the U.S., and permanently adorn several buildings on the Puyallup Reservation. He is currently working on a large commission for the Seattle waterfront.\n\n Visit his website at : http://www.qwalsius.com/", - "qid": "Welcome Figure: Meet the artist", + "qid": "Welcome_Figure:_Meet_the_artist", "q": [ "who made this", "who is the artist", @@ -356,7 +356,7 @@ }, { "a": "The style of Welcome Figure is traditional to this region and the Coast Salish tribes. Totem poles are often mistakenly identified with the Pacific Northwest, but that form was primarily practiced by the First Nations Groups of Canada and Alaska. Traditional wood carving practices of the Puyallup included welcome figures.\n\nIn the words of the artist, the colors and formlines of this piece were chosen with intention and purpose:“The earth red color here signifies the healing power associated with Thunderbird by the Puyallup people long ago. Although it was believed that Thunderbird had white feathers, the print and the painted dress pattern convey a healing that is called upon for the devastation of losing a prominent village. Contrary to surrounding tribes who envision the Thunderbird as a massive creature who consumes whales, the Puyallup percieved the being to be no larger than a small hawk. It is an indication that power was not associated with mass and that the strength to heal was of equal if not greater importance in the philosophy of our ancestors.”\n\n Many Puget Sound tribes continue to practice the important practices that distinguish this region of the world, generously sharing their culture through art, song, and dance. The intention of this contemporary welcoming figure is the same as that of its predecessors: with its arms outstretched, it gracefully receives visitors to the site while powerfully honoring the traditions of the area's first peoples.", - "qid": "Welcome Figure: About the art", + "qid": "Welcome_Figure:_About_the_art", "q": [ "more about the art", "about the art", @@ -371,7 +371,7 @@ }, { "a": " Generous and blessed with abundant resources, the Puyallup often hosted Native travelers. Their generosity extended to non-Native newcomers as well, though their gestures of friendship were not always reciprocal.\n\n The tribes of the Pacific Northwest were connected through travel, marriage, and a practice called potlatch. A potlatch is a gift-giving feast meant to mark an important event. At the end of the party, the host family gave away all their worldly possessions. Ample resources and a culture of generosity made it easy for hosts regain what was “lost” after they hosted a potlatch.\n\n From the site of Welcome Figure, visitors can glimpse the Tacoma Dome, and on clear days, Tacopid (Mt. Rainier). Tacopid supports its caretakers with water, fish, timber, and game. It is a beloved source of life for the Puyallup. Historically, the Tribe tucked villages and temporary hunting camps into the gentle curves of the streams and rivers that flowed from the mountain. But their main village sat where the Tacoma Dome now stands. What little remains of that village lies beneath forty feet of fill today.\n\n Today, tribal headquarters are located off of Portland Avenue, in East Tacoma, where the tribe owns many local businesses, provides services to tribal members, and offers education about the tribe's historic and contemporary cultural practices and lifeways.", - "qid": "Welcome Figure: Historical Context", + "qid": "Welcome_Figure:_Historical_Context", "q": [ "more about the history", "about the historical context", @@ -405,7 +405,7 @@ }, { "a": "Bronze", - "qid": "Maru: Medium", + "qid": "Maru:_Medium", "q": [ "Medium", "Material", @@ -421,7 +421,7 @@ }, { "a": "While designing Maru, sculptor Gerard Tsutakawa worked with an advisory board of former students. The late landscape designer Kenichi Nakano also collaborated on this sculpture.\n\n Tsutakawa's designs combine the cultures and traditions of the Pacific Rim, incorporating Japanese forms and sensibilities with his lifetime of experience living in the Pacific Northwest's unique natural environment. Well known for MITT, the sculpture that stands outside Safeco Field in Seattle, his sculptures are humanistic, accessible, and inviting.", - "qid": "Maru: Meet the artist", + "qid": "Maru:_Meet_the_artist", "q": [ "who made this", "who is the artist", @@ -437,7 +437,7 @@ }, { "a": "Maru stands among a landscape of boulders and Japanese maples. The bronze sculpture has a large cut-out circle, inviting visitors to sit, touch, and interact with the piece. It also offers an opportunity for contemplation and learning about the history of the Japanese Language school, which was located a few blocks up the hill from the sculpture.\n\n Maru, which means \"circle,\" might alternatively evoke a sense of negative space, or the image of a closed, unending circle. Similarly, the piece suggests both the hollow space left in the community after wartime incarceration, as well as the continued presence of the Japanese American community in Tacoma. Japanese ship names often end in -maru, so the piece may also refer to the importance of Japanese ships in bringing people and goods to Tacoma.", - "qid": "Maru: About the art", + "qid": "Maru:_About_the_art", "q": [ "more about the art", "about the art", @@ -452,7 +452,7 @@ }, { "a": " As the point of arrival for the railroad, the hillside west of the Prairie Line corridor hosted many ethnic enclaves, including the Nihonmachi, or Japan Town. By 1890, approximately 500 Japanese-Americans lived in Tacoma. Arriving by ship, many Japanese first came to work in railroad construction. In the 1880s, the Northern Pacific enlisted Hifumi “Harry” Kumamoto to recruit 2,000 Japanese laborers to help build the Cascade Branch of the NPRR. Building this more direct route over the Cascades was what made Tacoma finally boom.\n\n As the city grew up, so did the Nihonmachi. Japanese entrepreneurs like Fujimatsu and Sadako Moriguchi set up shop. Established in 1928, their store — Uwajima-ya — sold Japanese staples to countrymen craving a bit of home.\n\n The Japanese Language School, Nihongo Gakko, served as the main hub of Japan Town. From 1911 through 1942, the school brought the families of a thriving urban neighborhood together to support the future of their community and their children. The school was located on the 1700 block of Tacoma Avenue in a bustling neighborhood of hotels, restaurants, laundries, banks, and houses. For three decades, the school instilled in its young students the moral and cultural values of their Japanese heritage, and also emphasized a strong commitment to American citizenship.", - "qid": "Maru: Historical Context", + "qid": "Maru:_Historical_Context", "q": [ "more about the history", "about the historical context", @@ -467,7 +467,7 @@ }, { "a": " As the point of arrival for the railroad, the hillside west of the Prairie Line corridor hosted many ethnic enclaves, including the Nihonmachi, or Japan Town. By 1890, approximately 500 Japanese-Americans lived in Tacoma. Arriving by ship, many Japanese first came to work in railroad construction. In the 1880s, the Northern Pacific enlisted Hifumi “Harry” Kumamoto to recruit 2,000 Japanese laborers to help build the Cascade Branch of the NPRR. Building this more direct route over the Cascades was what made Tacoma finally boom.\n\n As the city grew up, so did the Nihonmachi. Japanese entrepreneurs like Fujimatsu and Sadako Moriguchi set up shop. Established in 1928, their store — Uwajima-ya — sold Japanese staples to countrymen craving a bit of home.\n\n The Japanese Language School, Nihongo Gakko, served as the main hub of Japan Town. From 1911 through 1942, the school brought the families of a thriving urban neighborhood together to support the future of their community and their children. The school was located on the 1700 block of Tacoma Avenue in a bustling neighborhood of hotels, restaurants, laundries, banks, and houses. For three decades, the school instilled in its young students the moral and cultural values of their Japanese heritage, and also emphasized a strong commitment to American citizenship.", - "qid": "Maru: WWII Internment", + "qid": "Maru:_WWII_Internment", "q": [ "world war 2", "world war two", @@ -489,7 +489,7 @@ }, { "a": "In 1990, the University of Washington started renovating vacant buildings in what was historically known as the Jobber's District, including this 1892 building commissioned by Russell T. Joy. The Joy Building used “flatiron” technology, a major innovation in its day. Built in brick, the building's interior structure was steel, rather than Douglas fir timber — a first step towards the emergence of skyscrapers. The building was supposed to be nearly fireproof. This was an important selling point: just four years prior, Seattle had burnt to the ground.\n\n But in 1903, a four-engine fire at the Joy Building destroyed the inventory and equipment of four tenants, including that of the Weigel and Star Diamond candy companies. Luckily, the fire was contained, and the building was renovated a few months later. Since then, the building was repurposed for many uses, including a glove manufacturer, coffee company, and automobile dealerships. \n\n Ask for more about adapative reuse for additional information", - "qid": "Joy Building", + "qid": "Joy_Building", "next": "Branch: West Coast Grocery and Union Station", "q": [ "Joy Building", @@ -509,7 +509,7 @@ }, { "a": " Roughly 120 years after it was originally built, UW Tacoma renovated the Joy Building. This remodel was a part of an innovative campus development project that adaptively and creatively reused the historic warehouse buildings along the Prairie Line.\n\n Though the buildings were redesigned for their new purpose, historical elements like facades and painted signs (sometimes called ghost signage) were intentionally left in place. Here's a handy list to help you find all of UW Tacoma's ghost signs, http://www.tacoma.washington.edu/about-uw-tacoma/ghost-signs-campus.", - "qid": "Joy Building: UW Tacoma and adaptive reuse", + "qid": "Joy_Building:_UW_Tacoma_and_adaptive_reuse", "q": [ "more about adaptive reuse", "adaptive reuse" @@ -528,7 +528,7 @@ }, { "a": "There are two options for the next stop, Terminus and Union Station. Union Station is slightly out of the way. Say or type which stop you would like to go to next.", - "qid": "Branch: West Coast Grocery and Union Station", + "qid": "Branch:_West_Coast_Grocery_and_Union_Station", "next": "Branch: West Coast Grocery and Union Station", "q": [ "Branch: West Coast Grocery and Union Station" @@ -545,7 +545,7 @@ }, { "a": "In 1990, the University of Washington started renovating vacant buildings in what was historically known as the Jobber's District, including this 1892 building commissioned by Russell T. Joy. The Pacific Avenue and Union Station used “flatiron” technology, a major innovation in its day. Built in brick, the building's interior structure was steel, rather than Douglas fir timber — a first step towards the emergence of skyscrapers. The building was supposed to be nearly fireproof. This was an important selling point: just four years prior, Seattle had burnt to the ground.\n\n But in 1903, a four-engine fire at the Pacific Avenue and Union Station destroyed the inventory and equipment of four tenants, including that of the Weigel and Star Diamond candy companies. Luckily, the fire was contained, and the building was renovated a few months later. Since then, the building was repurposed for many uses, including a glove manufacturer, coffee company, and automobile dealerships. \n\n Ask for more about early development or more about the station for additional information", - "qid": "Pacific Avenue and Union Station", + "qid": "Pacific_Avenue_and_Union_Station", "next": "West Coast Grocery", "q": [ "Pacific Avenue and Union Station", @@ -564,7 +564,7 @@ }, { "a": " Roughly 120 years after it was originally built, UW Tacoma renovated the Pacific Avenue and Union Station. This remodel was a part of an innovative campus development project that adaptively and creatively reused the historic warehouse buildings along the Prairie Line.\n\n Though the buildings were redesigned for their new purpose, historical elements like facades and painted signs (sometimes called ghost signage) were intentionally left in place. Here's a handy list to help you find all of UW Tacoma's ghost signs, http://www.tacoma.washington.edu/about-uw-tacoma/ghost-signs-campus.", - "qid": "Platting Tacoma and Pacific Avenue", + "qid": "Platting_Tacoma_and_Pacific_Avenue", "q": [ "more about early development", "more about development", @@ -585,7 +585,7 @@ }, { "a": " The Northern Pacific's copper-topped passenger depot wouldn't be built along Pacific Avenue until 1909. Union Station arrived amid a flurry of railroad activity. Three new railroads connected to Tacoma in the early 1900's: The Great Northern (1909), Union Pacific (1910), and the Milwaukee Railroad (1911). \n\n For many years, Union Station was the key transportation hub for the region. But in the mid-1900's, the national highway system replaced railroads as the preferred travel method for most Americans. Ridership dwindled.\n\n In 1984, an Amtrak Station was built in the Dome District. Union Station saw its last passenger train depart the same year. The historic depot sat vacant for several years. Neighboring warehouses were also abandoned for several years until renovation by the University of Washington Tacoma began in the 1990's.", - "qid": "More about Union Station", + "qid": "More_about_Union_Station", "q": [ "more about union station", "more about the station", @@ -604,7 +604,7 @@ }, { "a": "This building's original tenants — Tacoma Grocery — supplied groceries from Montana to Alaska, but went belly up in the Panic of 1893. West Coast Grocery reused the space and built a more lasting grocery empire headquartered right here in the Jobber's District. \n\n Ask about the boom,bust,and boom or more about the Jobber's district information", - "qid": "West Coast Grocery", + "qid": "West_Coast_Grocery", "next": "Terminus", "q": [ "West Coast Grocery", @@ -624,7 +624,7 @@ }, { "a": " Tacoma Grocery's founders intended to establish the largest wholesale grocery in the Pacific Northwest. Instead, they got caught in the throes of a nationwide depression caused by a banking crisis. Many local startups faced a similar fate. \n\n Three years later, West Coast Grocery took over where Tacoma Grocery left off. Selling products under the brand name “Amocat” (Tacoma spelled backward), West Coast Grocery thrived, expanding into the Birmingham Hay & Seed Building on its south side in 1917. The building served as a warehouse for West Coast Grocery until 1970.", - "qid": "Boom, bust, and boom again", + "qid": "Boom,_bust,_and_boom_again", "q": [ "boom", "boom bust and boom", @@ -645,7 +645,7 @@ }, { "a": " The area was called the Jobber's District after the multitude of wholesale businesses who sprouted up along the Prairie Line, taking advantage of the spur lines that could connect them to goods arriving by rail. Those who worked in the warehouses were also known as jobbers, and multitudes flooded in to work in these growing industries.\n\n West Coast Grocery, with its retail space in front and warehouse space in the back, is a typical example of Jobber's District architecture. Other businesses along this stretch of the Prairie Line included the Joy Building, Garretson, Woodruff and Pratt Company; F. S. Harmon Furniture Manufacturing Company; Lindstrom-Berg Cabinet Works; and Tacoma Paper and Stationary.\n\n Built right along the Prairie Line Rail corridor, most of these buildings share similarities. The side facing Pacific Avenue was usually more attractive since it faced the shopping public, while the side facing the railroad was more industrial, offering efficient loading and unloading on a special railroad spur built just off of the Prairie Line. We can thank this design strategy for West Coast Grocery's timeless Italianate façade.\n\n The building was renovated in 1996 by the University of Washington. As UW Tacoma renovated this and other buildings in the Jobber's District, it kept some of this history in tact, keeping the original loading docks and repurposing them as covered walkways.", - "qid": "The Jobber's District", + "qid": "The_Jobber's_District", "q": [ "jobbers district", "jobber's district", @@ -679,7 +679,7 @@ }, { "a": "Granite, stainless steel, and fluorescent lights", - "qid": "Terminus: Medium", + "qid": "Terminus:_Medium", "q": [ "Medium", "Material", @@ -695,7 +695,7 @@ }, { "a": "Brian Goldbloom is a sculptor and public artist, well known for his site-specific stone constructions. Drawing inspiration from each site, his natural stone pieces provide contrast and interest to built environments.\n\nVisit their website at : http://www.goldbloomart.com/artist.asp?ArtistID=22174&Akey=EGW9FJRW&flM=1", - "qid": "Terminus: Meet the artist", + "qid": "Terminus:_Meet_the_artist", "q": [ "who made this", "who is the artist", @@ -711,7 +711,7 @@ }, { "a": "Nine of the sculpture's ten granite forms are left rough; one has been shaped into a smoother, more recognizable suitcase form, providing a focal point and interpretive clue to the piece. Recessed lamps in the granite flood the ground with pools of light, making the sculpture particularly striking at night.\n\nThese multiple forms help to remind us of the crowded terminal city that once surrounded this site, and the upturned suitcase hints at those who emptied their suitcases and put down roots, and those who merely passed through.", - "qid": "Terminus: About the art", + "qid": "Terminus:_About_the_art", "q": [ "more about the art", "about the art", @@ -726,7 +726,7 @@ }, { "a": "In July of 1873, a telegram arrived in Tacoma: the small waterfront community had been selected as the terminus of the Northern Pacific Railroad (NPRR). Under a tight deadline to connect the railroad to saltwater, the railroad raced to connect Tacoma to existing rail lines along the Columbia River at Kalama, WA.\n\n Built between the fall and winter of 1873 by a diverse group of laborers, including over 750 Chinese workers who had also worked on the Central Pacific Railroad, the Tacoma-Kalama line was finished with weeks to spare on December 16, 1873. Regular train service began in January of 1874. The Northern Pacific established their first passenger depot at 17th Street and present-day South Hood Street, close to the location of Terminus. \n\nThe final leg of this railroad ran from Tenino to Tacoma, passing through the “burnt prairie” near Olympia. Thus, it became known as the Prairie Line. For roughly a decade, the Prairie Line was the only “game” in town. Rows of brick warehouses lined its tracks.\n\n However, the completion of the rail line into Tacoma didn't immediately bring the boost the city wanted. Tacoma only grew by 283 people between 1875 and 1880. The Tacoma - Kalama line wasn't ideal. To reach the Northern Pacific main line, trains took a ferry — equipped with rails — across the Columbia River. Once in Oregon, the track finally shot eastward toward the plains. But the line wasn't connected to the Midwest unitl 1883, holding Tacoma's growth in check. Tacoma's population began to climb in the mid-1880's, reaching 7,000 people by 1885.\n\n Ask about part 2 of the history for more information.", - "qid": "Terminus: Historical Context Part 1", + "qid": "Terminus:_Historical_Context_Part_1", "q": [ "more about the history", "about the historical context", @@ -746,7 +746,7 @@ }, { "a": " The real boom came after the NPRR completed the Stampede Pass tunnel, a direct route that cut through the mountains of the Cascades to Eastern Washington. By 1890, Tacoma was 36,000 strong.\n\n The Cascade Branch met the Prairie Line at South 15th Street, bringing with it Tacoma's first major surge of passenger traffic. The next wave of newcomers, many of them immigrants, poured into Tacoma. Ethnic enclaves took root in Old Town and west of the Prairie Line on the hill overlooking Commencement Bay. Swedes, Germans, Danes, Italians, Norwegians, Greeks, and Croatians grouped together to ease their transition to America and preserve their culture. Japanese immigrants, arriving by ship, also settled near the rail line, opening hotels and other businesses and creating the Nihonmachi, or Japan Town neighborhood. Many African-Americans who arrived in Tacoma worked for the railroad, and some settled up the hill in a neighborhood that would become known as Hilltop.\n\n In 1911, Union Station replaced the passenger depot on South 17th Street, creating a formal railroad terminal for passengers arriving in Tacoma. ", - "qid": "Terminus: Historical Context Part 2", + "qid": "Terminus:_Historical_Context_Part_2", "q": [ "history part 2", "part 2 of history", @@ -767,7 +767,7 @@ }, { "a": "The next possible destinations are the Swiss Hall, the Washington State History Museum, and the Rails & Rain Garden. Choosing the Swiss Hall or the Washington State History Museum will send you off the main trail, while the Rails & Rain Garden is on the main trail. Which one would you like to go to next?", - "qid": "Branch: Swiss Hall, Washington State History Museum, and Rails & Rain Garden", + "qid": "Branch:_Swiss_Hall,_Washington_State_History_Museum,_and_Rails_&_Rain_Garden", "next": "Branch: Swiss Hall, Washington State History Museum, and Rails & Rain Garden", "q": [ "Branch: Swiss Hall, Washington State History Museum, and Rails & Rain Garden" @@ -784,7 +784,7 @@ }, { "a": "On the terraced hill west of the Prairie Line, immigrant communities formed societies offering support and social events. The Swiss Hall, which is visible from the main steps of the UW Tacoma campus, is one example of these ethnic halls created to host society events. The halls can be found throughout the city. Ask for more about the hall or about other ethnic halls for additional information.", - "qid": "Swiss Hall", + "qid": "Swiss_Hall", "next": "Branch: Washington State History Museum and Rails & Rain Garden", "q": [ "Swiss Hall", @@ -803,7 +803,7 @@ }, { "a": "The Swiss Society built their half-timbered hall between the jobbers' district and the ethnic neighborhoods above Market Street in 1903. The hall's distinctive tower once marked the southern edge of Tacoma's open-air markets. Japanese grocers and merchants lined Market Street to the north, lending the street its name.", - "qid": "Swiss Hall: More about the hall", + "qid": "Swiss_Hall:_More_about_the_hall", "q": [ "more about the hall", "more about the swiss hall", @@ -822,7 +822,7 @@ }, { "a": "The Swiss Society built their half-timbered hall between the jobbers' district and the ethnic neighborhoods above Market Street in 1903. The hall's distinctive tower once marked the southern edge of Tacoma's open-air markets. Japanese grocers and merchants lined Market Street to the north, lending the street its name.", - "qid": "Swiss Hall: Other ethnic halls", + "qid": "Swiss_Hall:_Other_ethnic_halls", "q": [ "more about other ethnic halls", "other ethnic halls", @@ -841,7 +841,7 @@ }, { "a": "The next possible destinations are the Washington State History Museum and the Rails & Rain Garden. The Washington State History Museum is off the main trail, while the Rails & Rain Garden is on the main trail. Which one would you like to go to next?", - "qid": "Branch: Washington State History Museum and Rails & Rain Garden", + "qid": "Branch:_Washington_State_History_Museum_and_Rails_&_Rain_Garden", "next": "Branch: Washington State History Museum and Rails & Rain Garden", "q": [ "Branch: Washington State History Museum and Rails & Rain Garden" @@ -858,7 +858,7 @@ }, { "a": "The Washington State History Museum's interactive exhibits, dynamic storytelling, high-tech displays, and dramatic artifacts bring the state's history to life. The museum also played a key role in revitalizing downtown Tacoma. Ask about the historical context or about \"a new cultural dimension\" for additional information ", - "qid": "Washington State History Museum", + "qid": "Washington_State_History_Museum", "next": "Branch: Swiss Hall and Rails & Rain Garden", "q": [ "Washington State History Museum", @@ -878,7 +878,7 @@ }, { "a": " Initially, the super highway was unkind to downtown Tacoma and countless more urban centers across the country. Suburbs, complete with shopping malls, popped up. Downtown businesses departed. Blight set in. From the 1960's to the early 80's, downtown Tacoma felt deserted.\n\n The jewel of the city, Union Station, sat vacant from 1984 until 1989. Then it was restored and repurposed as a federal courthouse. Nearby, in the Warehouse District, the University of Washington started rehabilitating historic buildings. And I-705 finally connected downtown Tacoma to I-5.", - "qid": "Washington State History Museum: Historical Context", + "qid": "Washington_State_History_Museum:_Historical_Context", "q": [ "more about the history", "about the historical context", @@ -893,7 +893,7 @@ }, { "a": "Amidst this flurry of downtown revitalization came Tacoma's first major museum. The Washington State Historical Society began constructing the History Museum on a site adjacent to Union Station. The museum, designed by architects Charles Moore and Arthur Andersson, imitated the arched facades of the Union Depot. Completed in 1996, the museum fit in well with the historic district.\n\n The History Museum became the first of six museums that, today, comprise Tacoma's Museum District. Featuring world class collections of studio glass, collectible cars, Northwest art, maritime history, and much more, Tacoma's Museum District offers a variety of avenues to explore in one walkable cluster. It's one reason for Tacoma's re-emergence as a thriving cultural and economic hub.\n\nTo learn more, visit the Washington State History Museum's website: http://www.washingtonhistory.org/visit/wshm/ .", - "qid": "Washington State History Museum: A new cultural dimension", + "qid": "Washington_State_History_Museum:_A_new_cultural_dimension", "q": [ "more about other the new cultural dimension", "cultural dimension", @@ -907,7 +907,7 @@ }, { "a": "The next possible destinations are the Washington State History Museum and the Rails & Rain Garden. The Washington State History Museum is off the main trail, while the Rails & Rain Garden is on the main trail. Which one would you like to go to next?", - "qid": "Branch: Swiss Hall and Rails & Rain Garden", + "qid": "Branch:_Swiss_Hall_and_Rails_&_Rain_Garden", "next": "Branch: Swiss Hall and Rails & Rain Garden", "q": [ "Branch: Swiss Hall and Rails & Rain Garden" @@ -924,7 +924,7 @@ }, { "a": "Visitors are often intrigued by this garden-like feature at the south end of the UW segment of the Prairie Line Trail. It has plants, rusty steel brackets and troughs, and often water flowing through it. Is it art? History? A science project? This rain garden could be said to be all three. Ask about the art ,history and science or about the \"End of the Line\" for additional information", - "qid": "Rails & Rain Garden", + "qid": "Rails_&_Rain_Garden", "next": "Heidelberg Complex", "q": [ "Rails & Rain Garden", @@ -945,7 +945,7 @@ }, { "a": "This feature's main practical function is to treat stormwater. In an urban environment, stormwater picks up pollutants. Rain gardens like this one use special plants to filter out pollution before runoff hits major waterways. This rain garden treats stormwater from 42 acres of developed urban space upstream, making sure that water is clean and safe when it joins the Thea Foss Waterway at the bottom of the hill.\n\n Artfully designed to work with the existing railroad tracks, the rain garden also preserves a key piece of Tacoma's history. A close look at the rusty track segments reveals dates. These dates show the last time the tracks were swapped out for maintenance reasons. The last train rumbled over the Prairie Line tracks in Tacoma on the afternoon of March 30, 2003, just under fifty years after these rails were last replaced.", - "qid": "Rails & Rain Garden: Art, history, and science", + "qid": "Rails_&_Rain_Garden:_Art,_history,_and_science", "q": [ "art", "history", @@ -965,7 +965,7 @@ }, { "a": "Closing the book on the Prairie Line opened a new chapter in Tacoma's story — a chapter that harkens back to an earlier time. Historically, a streetcar ran up and down Pacific Avenue. The city brought streetcars back with Tacoma Link light rail in 2003. The historic rail line complicated the intersection of South 17th and Pacific Avenue. To make room for this new rail line, the City and the railroad agreed to phase out the Prairie Line. \n\nVacating the Prairie Line made light rail much more affordable. It also created an opportunity for a multi-modal transportation route through the heart of Tacoma featuring light rail, automobile, pedestrian, and bicycle traffic.\n\n Bonus: Prairie Line Trail connects to the Thea Foss Esplanade and the historic Water Flume Line Trail, creating a multi-district biking and walking trail enhanced with art and history.", - "qid": "Rails & Rain Garden: End of the Line", + "qid": "Rails_&_Rain_Garden:_End_of_the_Line", "q": [ "end of the line", "end line", @@ -979,7 +979,7 @@ }, { "a": "The Columbia – Heidelberg Building produced Northwest beer for three-quarters of a century before shutting down in 1979. In 2016, the historic brewing complex gained a new tenant — 7 Seas Brewing Company — making way for this neighborhood's comeback and an emerging Brewery District.Ask about the beginning, prohibition, or the post-war boom for additional information", - "qid": "Heidelberg Complex", + "qid": "Heidelberg_Complex", "next": "Working Forward, Weaving Anew", "q": [ "Heidelberg Complex", @@ -1000,7 +1000,7 @@ }, { "a": "The Heidelberg Brewing complex, located at 2120-32 South C Street, first housed Columbia Brewing Company. Columbia started in 1900, created by German-born Emil Kliese and William C. Klitz. This wasn't Kleise's first beer venture. He started at Capital Brewing Company in Tumwater, WA. By 1899, Kleise had risen to head brewmaster. Investors approached him about starting a brewery in Tacoma. He signed on.\n\n Tacoma was a thirsty city. At the turn of the century, it boasted 95 different bars. Columbia Brewing rolled out 50 barrels a day to meet demand. They created various brands, including Columbia, Golden Drops, Golden Foam, Old Pilsner, and Alt Heidelberg (“Old Heidelberg”). Tacoma's brewing industry was hopping but the beer bubble was about to burst.", - "qid": "Heidelberg Complex: The beginning", + "qid": "Heidelberg_Complex:_The_beginning", "q": [ "beginning", "the beginning", @@ -1019,7 +1019,7 @@ }, { "a": "Prohibition hit in Washington State in 1916, four years earlier than the nation. Many saloons shut down, but some reinvented themselves as soft drink parlors. Columbia adapted. They started brewing soda: Birch Beer, Green River, Chocolate Soldier, and Blue Jay. They also crafted a “near beer” (non-alcoholic beer).\n\n Columbia Brewing Company became Columbia Breweries Inc. in 1933. Prohibition was over. The company resurrected their Alt Heidelberg brand. The company logo changed too. Its patriotic female figure was out. In came a good-timing character popularized by a play, opera, and silent movie. He was called the Student Prince.", - "qid": "Heidelberg Complex: Prohibition", + "qid": "Heidelberg_Complex:_Prohibition", "q": [ "prohibition", "the prohibition" @@ -1037,7 +1037,7 @@ }, { "a": " The Heidelberg brand proved enduring. In 1949, the company restructured, taking on the named Heidelberg Brewing. It ramped up to meet post-war demand. Kitchy Alt Heidelberg ads blanketed the Northwest, driving up sales.\n\n The company traded hands two more times, but kept the popular Alt Heidelberg brand afloat. In 1976, G. Heileman Brewing Co was expanding in the Northwest, and purchased Columbia-Heidelberg. Heilman had already purchased Rainier Brewing Company in Seattle. The courts ruled that Heilman owned too much of the Northwest beer market, and forced it to part with one of its companies. In 1979, the Columbia-Heidelberg brewery closed for good.\n\n Much of the original Columbia - Heidelberg complex is gone now, but the post-prohibition part of its facility remains. In 2016, the 7 Seas Brewing Company renovated this historic site, creating a brewery, tap room, and multi-use culinary space.", - "qid": "Heidelberg Complex: Post-war boom", + "qid": "Heidelberg_Complex:_Post-war_boom", "q": [ "the post war boom", "post-war boom", @@ -1056,7 +1056,7 @@ }, { "a": "Working Forward, Weaving Anew is a 13,000-square-foot, team-created mural. It intertwines scenes of hand production: Puyallup basket weaving, logging, furniture-building, and present-day weaving, telling a site-specific story of the changing attitudes towards the natural world. \n\n Ask for more about the art, the artist, or the medium for additional information.", - "qid": "Working Forward, Weaving Anew", + "qid": "Working_Forward,_Weaving_Anew", "next": "The Brewery District", "q": [ "Working Forward, Weaving Anew", @@ -1077,7 +1077,7 @@ }, { "a": "Paint and sculpted metal", - "qid": "Working Forward, Weaving Anew: Medium", + "qid": "Working_Forward,_Weaving_Anew:_Medium", "q": [ "Medium", "Material", @@ -1093,7 +1093,7 @@ }, { "a": " Jessilyn Brinkerhoff and Esteban Camacho Steffensen are muralists and collaborative public artists. Their work flows out of conversations, and tells awe-inspiring, larger-than-life stories. In this case, their conversations with local historians and representatives from the Puyallup Tribe inspired this mural, which was conceptualized and refined in 20 different versions of the design.\n\n To create the final mural, the artists used their full artistic arsenal: sketching, painting, photography, and graphic design. As they designed, the artists relied on historic photos, documents, and artifacts to accurately capture and weave together this complex array of stories.\n\n Visit Esteban Camacho Steffensen's website: https://camachosteffensen.blogspot.com/.", - "qid": "Working Forward, Weaving Anew: Meet the artists", + "qid": "Working_Forward,_Weaving_Anew:_Meet_the_artists", "q": [ "who made this", "who is the artist", @@ -1109,7 +1109,7 @@ }, { "a": " Esteban Camacho Steffensen and Jessilyn Brinkerhoff created this mural through an exploration of the history of production in Tacoma, primarily employing images of wood and weaving. Their design includes a Puyallup basket weaver, clearcutting, furniture making, and a person creating a contemporary artwork. All of these forms of production are intimately connected with the history of this place, from the massive cedar trees that once stood along this corridor to the furniture shop that occupied buildings in the surrounding warehouses.\n\n Working Forward, Weaving Anew is a mural designed to honor cultural traditions, the natural environment, and our need for new harmonious and sustainable paths forward into the future. The muralists worked closely with representatives from the Puyallup Tribe to ensure the cultural imagery in their artwork is respectful and accurate. This 50-foot-tall mural was hand painted in a span of 6 weeks with help from a team of nine Native American artists: Bruce Speakthunder Berry, Andrea Bob, Lloyd Neeka Cook, Anthony Duenas, Kanani Miyamoto, Ariella Pool, Elisabeth Tail, Charles Taylor, and Paul Valencia.\n\n View a closeup mural (https://www.youtube.com/watch?v=Uczz83XO4RE) showing the artists at work.", - "qid": "Working Forward, Weaving Anew: About the art", + "qid": "Working_Forward,_Weaving_Anew:_About_the_art", "q": [ "more about the art", "about the art", @@ -1124,7 +1124,7 @@ }, { "a": "Growing rapidly through 1890's and early 1900's, the district hit a roadblock in 1916. Prohibition. Some breweries fell. Others fought through. For the better part of a century, some of the Northwest's most recognizable beers were brewed here. Today, many breweries are capitalizing on these historic warehouses. \n\n Ask for more about the timeline for additional information.", - "qid": "The Brewery District", + "qid": "The_Brewery_District", "next": "End of Tour", "q": [ "The Brewery District", @@ -1146,7 +1146,7 @@ }, { "a": "John D. Scholl and Anton Huth established the Puget Sound Brewery in 1888. They set up shop at 1532 C Street before moving to the corner of Jefferson Avenue and 25th Street.\n\n In 1891, Scholl, Huth, and business partner Peter A. Kalenborn incorporated the Puget Sound Brewing Company with $600,000 in capital stock.\n\n Growth came quickly. Huth soon partnered with Samuel S. Loeb of the Milwaukee Brewing Company in 1897, merging the two companies into Pacific Brewing & Malting Company. Their new location? 2511-15 South Holgate Street.\n\n Columbia Brewing Company, located at 2120-32 South C Street, was formed in 1900 by German-born Emil Kliese and William C. Klitz.\n\n In 1916, the state of Washington prohibited the manufacture and sale of liquor.\n\n Many saloons rebranded as soft drink parlors during prohibition.\n\n In 1949, Heidelberg Brewing purchased Columbia Breweries, Inc. \n\n In 2014, Pacific Brewing & Malting returned (now in the Stadium District and under new ownership).\n\n The 7 Seas Brewing Co. moved into the Heidelberg complex in 2016. Beer is being brewed again at this location for the first time since 1979.", - "qid": "The Brewery District: Timeline", + "qid": "The_Brewery_District:_Timeline", "q": [ "Timeline", "the timeline" diff --git a/source/templates/examples/examples/index.js b/source/templates/examples/examples/index.js index f211b511c..3c3cf8c8e 100644 --- a/source/templates/examples/examples/index.js +++ b/source/templates/examples/examples/index.js @@ -14,7 +14,6 @@ const fs = require('fs'); const _ = require('lodash'); const util = require('../../util'); -const responsebots = require('./responsebots.js').resources; const responsebots_lexv2 = require('./responsebots-lexv2.js').resources; const js = fs.readdirSync(`${__dirname}/js`) @@ -25,6 +24,8 @@ const js = fs.readdirSync(`${__dirname}/js`) return { name: `ExampleJSLambda${name}`, resource: jslambda(name), + logGroupName: `${name}LogGroup`, + logGroupResource: jsLambdaLogGroup(name), id: `${name}JS`, }; }); @@ -38,14 +39,17 @@ const py = fs.readdirSync(`${__dirname}/py`, { withFileTypes: true }) return { name: `ExamplePYTHONLambda${name}`, resource: pylambda(name), + logGroupName: `${name}LogGroup`, + logGroupResource: pyLambdaLogGroup(name), id: `${name}PY`, }; }); module.exports = Object.assign( - responsebots, responsebots_lexv2, + _.fromPairs(js.map((x) => [x.logGroupName, x.logGroupResource])), _.fromPairs(js.map((x) => [x.name, x.resource])), + _.fromPairs(py.map((x) => [x.logGroupName, x.logGroupResource])), _.fromPairs(py.map((x) => [x.name, x.resource])), { FeedbackSNS: { @@ -165,6 +169,30 @@ module.exports = Object.assign( BuildDate: (new Date()).toISOString(), }, }, + ExampleWriteLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ExampleWriteLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ExampleWriteLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -184,6 +212,9 @@ module.exports = Object.assign( } }, Handler: 'cfn.handler', + LoggingConfig: { + LogGroup: { Ref: 'ExampleWriteLambdaLogGroup' }, + }, MemorySize: '128', Role: { Ref: 'CFNLambdaRole' }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -284,24 +315,6 @@ module.exports = Object.assign( ], }, }, - { - PolicyName: 'LexQNALambda', - PolicyDocument: { - Version: '2012-10-17', - Statement: [ - { - Effect: 'Allow', - Action: [ - 'lex:PostText', - ], - Resource: [ - { 'Fn::Join': ['', ['arn:aws:lex:', { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, ':bot:*', ':qna*']] }, - { 'Fn::Join': ['', ['arn:aws:lex:', { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, ':bot:*', ':QNA*']] }, - ], - }, - ], - }, - }, { PolicyName: 'LambdaQnABotStdExecution', PolicyDocument: { @@ -379,6 +392,9 @@ function jslambda(name) { }, }, Handler: `js/${name}.handler`, + LoggingConfig: { + LogGroup: { Ref: `${name}LogGroup` }, + }, MemorySize: '128', Role: { 'Fn::GetAtt': ['ExampleLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -433,6 +449,9 @@ function pylambda(name) { }, }, Handler: `py/${name}.handler`, + LoggingConfig: { + LogGroup: { Ref: `${name}LogGroup` }, + }, MemorySize: '128', Role: { 'Fn::GetAtt': ['ExampleLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_pythonRuntime, @@ -458,3 +477,59 @@ function pylambda(name) { }, }; } + +function jsLambdaLogGroup(name) { + return { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}' }, + `ExampleJSLambda${name}`, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }; +} + +function pyLambdaLogGroup(name) { + return { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}' }, + `ExamplePYTHONLambda${name}`, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }; +} diff --git a/source/templates/examples/examples/package-lock.json b/source/templates/examples/examples/package-lock.json index c4dd703a6..ac3497f5c 100644 --- a/source/templates/examples/examples/package-lock.json +++ b/source/templates/examples/examples/package-lock.json @@ -1,16 +1,16 @@ { "name": "examples", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "examples", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "cfn-response": "^1.0.1", - "handlebars": "^4.7.7", + "handlebars": "^4.7.8", "lodash": "^4.17.21" } }, @@ -19,19 +19,14 @@ "resolved": "https://registry.npmjs.org/cfn-response/-/cfn-response-1.0.1.tgz", "integrity": "sha1-qOwDlQwGg8UUlejKaA2dwLiEsTc=" }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "optional": true - }, "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", "dependencies": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, @@ -56,9 +51,10 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "node_modules/neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" }, "node_modules/source-map": { "version": "0.6.1", @@ -69,13 +65,11 @@ } }, "node_modules/uglify-js": { - "version": "3.9.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.4.tgz", - "integrity": "sha512-8RZBJq5smLOa7KslsNsVcSH+KOXf1uDU8yqLeNuVKwmT0T3FA0ZoXlinQfRad7SDcbZZRZE4ov+2v71EnxNyCA==", + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", + "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", + "license": "BSD-2-Clause", "optional": true, - "dependencies": { - "commander": "~2.20.3" - }, "bin": { "uglifyjs": "bin/uglifyjs" }, diff --git a/source/templates/examples/examples/package.json b/source/templates/examples/examples/package.json index f3dd40a9d..fa2f87176 100644 --- a/source/templates/examples/examples/package.json +++ b/source/templates/examples/examples/package.json @@ -1,6 +1,6 @@ { "name": "examples", - "version": "6.0.3", + "version": "6.1.0", "description": "Lambda contains a collection of lambda hooks for QnABot and a custom resource to create the example documents", "main": "index.js", "scripts": { @@ -13,7 +13,10 @@ "license": "Apache-2.0", "dependencies": { "cfn-response": "^1.0.1", - "handlebars": "^4.7.7", + "handlebars": "^4.7.8", "lodash": "^4.17.21" + }, + "overrides": { + "uglify-js": "^3.19.2" } } diff --git a/source/templates/examples/examples/py/requirements-dev.txt b/source/templates/examples/examples/py/requirements-dev.txt index 7da7bc821..d94d9ad60 100644 --- a/source/templates/examples/examples/py/requirements-dev.txt +++ b/source/templates/examples/examples/py/requirements-dev.txt @@ -1,4 +1,4 @@ -pytest~=7.4.2 -pytest-cov~=4.1.0 +pytest~=8.3.2 +pytest-cov~=5.0.0 mock~=5.1.0 -boto3==1.26.3 \ No newline at end of file +boto3==1.35.5 \ No newline at end of file diff --git a/source/templates/examples/examples/responsebots.js b/source/templates/examples/examples/responsebots.js deleted file mode 100644 index e30c068c3..000000000 --- a/source/templates/examples/examples/responsebots.js +++ /dev/null @@ -1,2100 +0,0 @@ -/** ******************************************************************************************************************* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * - * with the License. A copy of the License is located at * - * * - * http://www.apache.org/licenses/ * - * * - * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * - * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * - * and limitations under the License. * - ******************************************************************************************************************** */ - -/** - * - * SlotTypes, Intents, and Bots for elicit response bots. - * - * Warning : Important Note: If you update an Intent or a SlotType, it is mandatory to update the description - * in the associated Bot. Failure to do so when running an update will leave the bot in the NOT_BUILT state and you - * will need to rebuild in the AWS Console. To update description for all bots, change botDateVersion string below. - */ -const botDateVersion = `${process.env.npm_package_version} - v1`; // CHANGE ME TO FORCE BOT REBUILD - -const _ = require('lodash'); - -const config = { - voiceId: 'Joanna', - Clarification: 'Sorry, can you please repeat that?', - Abort: 'Sorry, I could not understand. Please start again.', - utterances: require('../../../assets/default-utterances'), -}; - -exports.resources = { - WageSlotType: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexSlotType', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAWageSlotType-${AWS::StackName}' }, - createVersion: true, - description: `QNA Wage Slot Type - ${botDateVersion}`, - parentSlotTypeSignature: 'AMAZON.AlphaNumeric', - slotTypeConfigurations: [ - { - regexConfiguration: { - pattern: '[0-9]{1,7}', - }, - }, - ], - }, - }, - QNAWage: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'WageIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAWageBot-${AWS::StackName}' }, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'WageIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat your wage.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - description: `QNA Wage elicit response - ${botDateVersion}`, - }, - }, - WageIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAWageIntent-${AWS::StackName}' }, - createVersion: true, - description: `QNA Wage Intent - ${botDateVersion}`, - sampleUtterances: [ - 'My salary is {Wage}', - 'My wage is {Wage}', - '{Wage}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - content: 'Is {Wage} correct (Yes/No)?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'Please let me know what your wage was again.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'Wage', - slotType: { Ref: 'WageSlotType' }, - slotTypeVersion: 'QNABOT-AUTO-ASSIGNED', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What is your wage?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - WageAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAWage', - }, - name: 'live', - description: `QNA Wage Alias - ${botDateVersion}`, - }, - }, - SocialSecuritySlotType: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexSlotType', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNASocialSecuritySlotType-${AWS::StackName}' }, - createVersion: true, - description: `QNA Social Security Slot Type - ${botDateVersion}`, - parentSlotTypeSignature: 'AMAZON.AlphaNumeric', - slotTypeConfigurations: [ - { - regexConfiguration: { - pattern: '[0-9]{3}-[0-9]{2}-[0-9]{4}', - }, - }, - ], - }, - }, - QNASocialSecurity: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'SocialSecurityIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNASocialSecurityBot-${AWS::StackName}' }, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'SocialSecurityIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat your social security number.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - description: `QNA Social Security elicit response - ${botDateVersion}`, - }, - }, - SocialSecurityIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNASocialSecurityIntent-${AWS::StackName}' }, - createVersion: true, - description: `QNA Social Security Intent - ${botDateVersion}`, - sampleUtterances: [ - 'The social security number is {SSN}', - 'My social security number is {SSN}', - 'It is {SSN}', - '{SSN}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - content: 'Is {SSN} correct (Yes/No)?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'Please let me know the social security number again.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'SSN', - slotType: { Ref: 'SocialSecuritySlotType' }, - slotTypeVersion: 'QNABOT-AUTO-ASSIGNED', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What is your social security number?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - SocialSecurityAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNASocialSecurity', - }, - name: 'live', - description: `QNA Social Security Alias - ${botDateVersion}`, - }, - }, - PinSlotType: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexSlotType', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAPinSlotType-${AWS::StackName}' }, - description: `QNA Pin Slot Type - ${botDateVersion}`, - parentSlotTypeSignature: 'AMAZON.AlphaNumeric', - createVersion: true, - slotTypeConfigurations: [ - { - regexConfiguration: { - pattern: '[0-9]{4}', - }, - }, - ], - }, - }, - QNAPin: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'PinIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAPinBot-${AWS::StackName}' }, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'PinIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'I\'m sorry I did not get all the digits, please re-enter all digits.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - description: `QNA Pin elicit response - ${botDateVersion}`, - }, - }, - PinIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAPinIntent-${AWS::StackName}' }, - description: `QNA Pin Intent - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'The pin number is {Pin}', - 'My pin number is {Pin}', - 'It is {Pin}', - '{Pin}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - content: 'Is {Pin} correct (Yes or No)?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'I\'m sorry I did not get all the digits, please re-enter all digits.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'Pin', - slotType: { Ref: 'PinSlotType' }, - slotTypeVersion: 'QNABOT-AUTO-ASSIGNED', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What are all the digits?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - PinAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAPin', - }, - name: 'live', - description: `QNA Pin Alias - ${botDateVersion}`, - }, - }, - QNAPinNoConfirm: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'PinIntentNoConfirm', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAPinBotNoConfirm-${AWS::StackName}' }, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'PinIntentNoConfirm' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'I\'m sorry I did not get all the digits, please re-enter all digits.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - description: `QNA Pin No Confirm elicit response - ${botDateVersion}`, - }, - }, - PinIntentNoConfirm: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAPinIntentNoConfirm-${AWS::StackName}' }, - description: `QNA Pin Intent No Confirm - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'The pin number is {Pin}', - 'My pin number is {Pin}', - 'It is {Pin}', - '{Pin}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'Pin', - slotType: { Ref: 'PinSlotType' }, - slotTypeVersion: 'QNABOT-AUTO-ASSIGNED', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What are all the digits?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - PinNoConfirmAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAPinNoConfirm', - }, - name: 'live', - description: `QNA Pin No Confirm Alias - ${botDateVersion}`, - }, - }, - YesNoSlotType: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexSlotType', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAYesNoSlotType-${AWS::StackName}' }, - description: `QNA Yes No Slot Type - ${botDateVersion}`, - createVersion: true, - valueSelectionStrategy: 'TOP_RESOLUTION', - enumerationValues: [ - { value: 'Yes', synonyms: ['yes', 'ok', 'yeah', 'sure', 'yep', 'affirmative', 'aye', 'correct', '1', 'one'] }, - { value: 'No', synonyms: ['no', 'nope', 'na', 'negative', 'non', '2', 'two'] }, - ], - }, - }, - YesNoIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAYesNoIntent-${AWS::StackName}' }, - createVersion: true, - description: `QNA Yes No Intent - ${botDateVersion}`, - sampleUtterances: [ - '{Yes_No}', - 'I said {Yes_No}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'Yes_No', - slotType: { Ref: 'YesNoSlotType' }, - slotTypeVersion: 'QNABOT-AUTO-ASSIGNED', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Say Yes or No.', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNAYesNo: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: ['YesNoSlotType', 'YesNoIntent'], - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAYesNoBot-${AWS::StackName}' }, - description: `QNA Yes No Bot - ${botDateVersion}`, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'YesNoIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat - say Yes or No.', - }, - ], - maxAttempts: 5, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - }, - }, - YesNoAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNAYesNo', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAYesNo', - }, - name: 'live', - description: `QNA Yes No Alias - ${botDateVersion}`, - }, - }, - YesNoExitSlotType: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexSlotType', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAYesNoExitSlotType-${AWS::StackName}' }, - description: `QNA Yes No Exit Slot Type - ${botDateVersion}`, - createVersion: true, - valueSelectionStrategy: 'TOP_RESOLUTION', - enumerationValues: [ - { value: 'Yes', synonyms: ['yes', 'ok', 'yeah', 'sure', 'yep', 'affirmative', 'aye', 'correct', '1', 'one'] }, - { value: 'No', synonyms: ['no', 'nope', 'na', 'negative', 'non', '2', 'two'] }, - { value: 'Exit', synonyms: ['exit', 'agent', 'rep', 'representative', 'stop', 'quit', 'help', 'bye', 'goodbye', '3', 'three'] }, - ], - }, - }, - YesNoExitIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAYesNoExitIntent-${AWS::StackName}' }, - createVersion: true, - description: `QNA Yes No Exit Intent - ${botDateVersion}`, - sampleUtterances: [ - '{Yes_No_Exit}', - 'I said {Yes_No_Exit}', - ], - conclusionStatement: { - messages: [ - { - content: 'Ok. ', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'Yes_No_Exit', - slotType: { Ref: 'YesNoExitSlotType' }, - slotTypeVersion: 'QNABOT-AUTO-ASSIGNED', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Say Yes, No, or Exit.', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNAYesNoExit: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: ['YesNoExitSlotType', 'YesNoExitIntent'], - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAYesNoExitBot-${AWS::StackName}' }, - description: `QNA Yes No Exit Bot - ${botDateVersion}`, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'YesNoExitIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat - say Yes or No. You can also say exit, agent, quit, or bye to leave.', - }, - ], - maxAttempts: 5, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - }, - }, - YesNoExitAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNAYesNoExit', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAYesNoExit', - }, - name: 'live', - description: `QNA Yes No Exit Alias - ${botDateVersion}`, - }, - }, - DateIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNADateIntent-${AWS::StackName}' }, - createVersion: true, - description: `QNA DateIntent - ${botDateVersion}`, - sampleUtterances: [ - 'The date is {date}', - 'The date was {date}', - 'I went on {date}', - 'It is {date}', - 'It occurred on {date}', - 'I was born on {date}', - 'My birthdate is {date}', - 'My date of birth is {date}', - '{date}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - content: 'Is {date} correct (Yes or No)?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'Please let me know the date again.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'date', - slotType: 'AMAZON.DATE', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What date?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNADate: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'DateIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNADateBot-${AWS::StackName}' }, - description: `QNA Date Bot - ${botDateVersion}`, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'DateIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the date.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - }, - }, - DateAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNADate', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNADate', - }, - name: 'live', - description: `QNA Date Alias - ${botDateVersion}`, - }, - }, - DateIntentNoConfirm: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNADateIntentNoConfirm-${AWS::StackName}' }, - createVersion: true, - description: `QNA DateIntentNoConfirm - ${botDateVersion}`, - sampleUtterances: [ - 'The date is {date}', - 'The date was {date}', - 'I went on {date}', - 'It is {date}', - 'It occurred on {date}', - 'I was born on {date}', - 'My birthdate is {date}', - 'My date of birth is {date}', - '{date}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'date', - slotType: 'AMAZON.DATE', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What date?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNADateNoConfirm: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'DateIntentNoConfirm', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNADateBotNoConfirm-${AWS::StackName}' }, - description: `QNA Date Bot No Confirm - ${botDateVersion}`, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'DateIntentNoConfirm' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the date.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - }, - }, - DateAliasNoConfirmV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNADateNoConfirm', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNADateNoConfirm', - }, - name: 'live', - description: `QNA Date No Confirm Alias - ${botDateVersion}`, - }, - }, - DayOfWeekIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNADayOfWeekIntent-${AWS::StackName}' }, - description: `QNA Day Of Week Intent - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'The day is {DayOfWeek}', - 'The day was {DayOfWeek}', - 'I went on {DayOfWeek}', - 'It is {DayOfWeek}', - 'It occurred on {DayOfWeek}', - '{DayOfWeek}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - content: 'Is {DayOfWeek} correct (Yes or No)?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'Please let me know the day again.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'DayOfWeek', - slotType: 'AMAZON.DayOfWeek', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What day?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNADayOfWeek: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'DayOfWeekIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNADayOfWeekBot-${AWS::StackName}' }, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'DayOfWeekIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the day of the week.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - description: `QNADayOfWeek bot - ${botDateVersion}`, - }, - }, - DayOfWeekAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNADayOfWeek', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNADayOfWeek', - }, - name: 'live', - description: `QNA Day Of Week Alias - ${botDateVersion}`, - }, - }, - MonthIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAMonthIntent-${AWS::StackName}' }, - description: `QNA Month Intent - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'The month is {Month}', - 'The month was {Month}', - 'It is {Month}', - 'It occurred on {Month}', - '{Month}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - content: 'Is {Month} correct (Yes or No)?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'Please let me know the month again.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'Month', - slotType: 'AMAZON.Month', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What month?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNAMonth: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'MonthIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAMonthBot-${AWS::StackName}' }, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'MonthIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the month.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - description: `QNA Month Bot - ${botDateVersion}`, - }, - }, - MonthAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNAMonth', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAMonth', - }, - name: 'live', - description: `QNA Month Alias - ${botDateVersion}`, - }, - }, - MonthIntentNoConfirm: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAMonthIntentNoConfirm-${AWS::StackName}' }, - description: `QNA Month Intent No Confirm - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'The month is {Month}', - 'The month was {Month}', - 'It is {Month}', - 'It occurred on {Month}', - '{Month}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'Month', - slotType: 'AMAZON.Month', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What month?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNAMonthNoConfirm: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'MonthIntentNoConfirm', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAMonthBotNoConfirm-${AWS::StackName}' }, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'MonthIntentNoConfirm' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the month.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - description: `QNA Month Bot No Confirm - ${botDateVersion}`, - }, - }, - MonthAliasNoConfirmV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNAMonthNoConfirm', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAMonthNoConfirm', - }, - name: 'live', - description: `QNA Month Alias No Confirm - ${botDateVersion}`, - }, - }, - NumberIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNANumberIntent-${AWS::StackName}' }, - description: `QNA Number Intent - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'The number is {Number}', - 'The number was {Number}', - 'It is {Number}', - '{Number}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - content: 'Is {Number} correct (Yes or No)?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'Please let me know the number again.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'Number', - slotType: 'AMAZON.NUMBER', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What number?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNANumber: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'NumberIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNANumberBot-${AWS::StackName}' }, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'NumberIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the number.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - description: `QNA Number Bot - ${botDateVersion}`, - }, - }, - NumberAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNANumber', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNANumber', - }, - name: 'live', - description: `QNA Number Alias - ${botDateVersion}`, - }, - }, - NumberIntentNoConfirm: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNANumberIntentNoConfirm-${AWS::StackName}' }, - description: `QNA Number Intent No Confirm - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'The number is {Number}', - 'The number was {Number}', - 'It is {Number}', - '{Number}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'Number', - slotType: 'AMAZON.NUMBER', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What number?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNANumberNoConfirm: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'NumberIntentNoConfirm', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNANumberBotNoConfirm-${AWS::StackName}' }, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'NumberIntentNoConfirm' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the number.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - description: `QNA Number Bot No Confirm - ${botDateVersion}`, - }, - }, - NumberAliasNoConfirmV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNANumberNoConfirm', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNANumberNoConfirm', - }, - name: 'live', - description: `QNA Number Alias No Confirm - ${botDateVersion}`, - }, - }, - AgeIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAAgeIntent-${AWS::StackName}' }, - description: `QNA Age Intent - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'My age is {Age}', - 'Age is {Age}', - 'It is {Age}', - 'I am {Age}', - 'I am {Age} years old', - 'His age is {Age}', - 'He is {Age}', - 'He is {Age} years old', - 'Her age is {Age}', - 'She is {Age}', - 'She is {Age} years old', - '{Age}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - content: 'Is {Age} correct (Yes or No)?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'Please let me know the age again.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'Age', - slotType: 'AMAZON.NUMBER', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What age?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNAAge: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'AgeIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAAgeBot-${AWS::StackName}' }, - description: `QNA Age Bot - ${botDateVersion}`, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'AgeIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the age.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - }, - }, - AgeAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNAAge', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAAge', - }, - name: 'live', - description: `QNA Age Alias - ${botDateVersion}`, - }, - }, - PhoneNumberIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAPhoneNumberIntent-${AWS::StackName}' }, - description: `QNA Phone Number Intent - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'The phone number is {PhoneNumber}', - 'My phone number is {PhoneNumber}', - 'It is {PhoneNumber}', - '{PhoneNumber}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - // QnABot always uses postText to interact with response bot, however, it supports embedded SSML tags in - // the confirmation prompt so that speech back to Alexa or Lex client in postContent mode. - // SSML tags are automatically stripped by QnABot for text mode clients. - content: 'Is {PhoneNumber} correct (Yes or No)?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'Please let me know the phone number again.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'PhoneNumber', - slotType: 'AMAZON.PhoneNumber', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What phone number?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNAPhoneNumber: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'PhoneNumberIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAPhoneNumberBot-${AWS::StackName}' }, - description: `QNA Phone Number Bot - ${botDateVersion}`, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'PhoneNumberIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the phone number.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - }, - }, - PhoneNumberAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNAPhoneNumber', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAPhoneNumber', - }, - name: 'live', - description: `QNA Phone Number Alias - ${botDateVersion}`, - }, - }, - PhoneNumberIntentNoConfirm: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAPhoneNumberIntentNoConfirm-${AWS::StackName}' }, - description: `QNA Phone Number Intent No Confirm - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'The phone number is {PhoneNumber}', - 'My phone number is {PhoneNumber}', - 'It is {PhoneNumber}', - '{PhoneNumber}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'PhoneNumber', - slotType: 'AMAZON.PhoneNumber', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What phone number?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNAPhoneNumberNoConfirm: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'PhoneNumberIntentNoConfirm', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAPhoneNumberBotNoConfirm-${AWS::StackName}' }, - description: `QNA Phone Number Bot No Confirm - ${botDateVersion}`, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'PhoneNumberIntentNoConfirm' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the phone number.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - }, - }, - PhoneNumberAliasNoConfirmV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNAPhoneNumberNoConfirm', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAPhoneNumberNoConfirm', - }, - name: 'live', - description: `QNA Phone Number Alias No Confirm - ${botDateVersion}`, - }, - }, - TimeIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNATimeIntent-${AWS::StackName}' }, - description: `QNA Time Intent - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'The time was {Time}', - 'It occurred at {Time}', - 'At {Time}', - '{Time}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - content: 'Is {Time} correct (Yes or No)?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'Please let me know the time again.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'Time', - slotType: 'AMAZON.TIME', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What time?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNATime: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'TimeIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNATimeBot-${AWS::StackName}' }, - description: `QNA Time Bot - ${botDateVersion}`, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'TimeIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the time, specifying am or pm.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - }, - }, - TimeAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNATime', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNATime', - }, - name: 'live', - description: `QNA Time Alias - ${botDateVersion}`, - }, - }, - EmailAddressIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAEmailAddressIntent-${AWS::StackName}' }, - description: `QNA Email Address Intent - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'My email address is {EmailAddress}', - 'The email address is {EmailAddress}', - '{EmailAddress}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - content: 'Is {EmailAddress} correct (Yes or No)?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'Please let me know the email address again.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'EmailAddress', - slotType: 'AMAZON.EmailAddress', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What email address?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNAEmailAddress: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'EmailAddressIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNAEmailAddressBot-${AWS::StackName}' }, - description: `QNA Email Address Intent - ${botDateVersion}`, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'EmailAddressIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat the email address.', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - }, - }, - EmailAddressAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNAEmailAddress', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAEmailAddress', - }, - name: 'live', - description: `QNA Email Address Alias - ${botDateVersion}`, - }, - }, - NameIntent: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNANameIntent-${AWS::StackName}' }, - description: `QNA Name Intent - ${botDateVersion}`, - createVersion: true, - sampleUtterances: [ - 'My last name is {LastName}', - 'My first name is {FirstName}', - 'My first name is {FirstName} and My last name is {LastName}', - 'My name is {FirstName} {LastName}', - 'I am {FirstName} {LastName}', - '{FirstName} {LastName}', - '{FirstName}', - '{LastName}', - ], - conclusionStatement: { - messages: [ - { - content: 'OK. ', - contentType: 'PlainText', - }, - ], - }, - confirmationPrompt: { - maxAttempts: 1, - messages: [ - { - content: 'Did I get your name right (Yes or No) {FirstName} {LastName}?', - contentType: 'PlainText', - }, - ], - }, - rejectionStatement: { - messages: [ - { - content: 'Please let me know your name again.', - contentType: 'PlainText', - }, - ], - }, - fulfillmentActivity: { - type: 'ReturnIntent', - }, - slots: [ - { - name: 'FirstName', - slotType: 'AMAZON.US_FIRST_NAME', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What is your first name?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - { - name: 'LastName', - slotType: 'AMAZON.US_LAST_NAME', - slotConstraint: 'Required', - valueElicitationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'What is your last name?', - }, - ], - maxAttempts: 2, - }, - priority: 1, - }, - ], - }, - }, - QNAName: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexBot', - DependsOn: 'NameIntent', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - name: { 'Fn::Sub': 'QNANameBot-${AWS::StackName}' }, - description: `QNA Name Bot - ${botDateVersion}`, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'NameIntent' } }, - ], - clarificationPrompt: { - messages: [ - { - contentType: 'PlainText', - content: 'Please repeat your first and last name?', - }, - ], - maxAttempts: 3, - }, - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - }, - }, - NameAliasV2: { - Condition: 'CreateLexV1ResponseBots', - Type: 'Custom::LexAlias', - DependsOn: 'QNAName', - Properties: { - ServiceToken: { Ref: 'CFNLambda' }, - botName: { - Ref: 'QNAName', - }, - name: 'live', - description: `QNA Name Alias - ${botDateVersion}`, - }, - }, -}; - -exports.names = [ - 'QNAYesNo', 'QNAYesNoExit', 'QNADate', 'QNADateNoConfirm', 'QNADayOfWeek', 'QNAMonth', 'QNAMonthNoConfirm', - 'QNANumber', 'QNANumberNoConfirm', 'QNAAge', 'QNAPhoneNumber', 'QNAPhoneNumberNoConfirm', - 'QNATime', 'QNAEmailAddress', 'QNAName', 'QNAWage', 'QNASocialSecurity', 'QNAPin', 'QNAPinNoConfirm', -]; - -exports.outputs = _.fromPairs(exports.names.map((x) => [x, { Value: { 'Fn::If': ['CreateLexV1ResponseBots', { Ref: x }, 'LexV2 only'] } }])); diff --git a/source/templates/examples/extensions/index.js b/source/templates/examples/extensions/index.js index e45d7ef3b..952474db5 100644 --- a/source/templates/examples/extensions/index.js +++ b/source/templates/examples/extensions/index.js @@ -23,6 +23,8 @@ const js = fs.readdirSync(`${__dirname}/js_lambda_hooks`) resource: jslambda(name), codeVersionName: `CodeVersion${name}`, codeVersionResource: codeVersion(name), + logGroupName: `${name}LogGroup`, + logGroupResource: lambdaLogGroup(name), id: `${name}JS`, }; } @@ -34,13 +36,15 @@ const py = fs.readdirSync(`${__dirname}/py_lambda_hooks`) resource: pylambda(name), codeVersionName: `CodeVersion${name}`, codeVersionResource: codeVersion(name), + logGroupName: `${name}LogGroup`, + logGroupResource: lambdaLogGroup(name), id: `${name}PY`, })); const lambda_hooks = js.concat(py); -// NOTICE: Canvas LMS integration with QnABot on AWS is deprecated in this release and no longer be supported. Customers may fork the code needed for their specific use case from previous versions. The integration code will be removed in the next release.(QnASecretsManagerLambda) module.exports = Object.assign( + _.fromPairs(lambda_hooks.map((x) => [x.logGroupName, x.logGroupResource])), _.fromPairs(lambda_hooks.map((x) => [x.name, x.resource])), _.fromPairs(lambda_hooks.map((x) => [x.codeVersionName, x.codeVersionResource])), { @@ -56,6 +60,30 @@ module.exports = Object.assign( }, ), }, + EXTUiImportLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-EXTUiImportLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, EXTUiImportLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -75,6 +103,9 @@ module.exports = Object.assign( }, }, Handler: 'ui_import.handler', + LoggingConfig: { + LogGroup: { Ref: 'EXTUiImportLambdaLogGroup' }, + }, MemorySize: '128', Role: { Ref: 'CFNLambdaRole' }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -219,44 +250,7 @@ module.exports = Object.assign( ], }, }, - { - PolicyName: 'LexQNALambda', - PolicyDocument: { - Version: '2012-10-17', - Statement: [ - { - Effect: 'Allow', - Action: [ - 'lex:PostText', - ], - Resource: [ - { 'Fn::Join': ['', ['arn:aws:lex:', { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, ':bot:*', ':qna*']] }, - { 'Fn::Join': ['', ['arn:aws:lex:', { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, ':bot:*', ':QNA*']] }, - ], - }, - ], - }, - }, - { - PolicyName: 'QNASecretsManagerLambda', - PolicyDocument: { - Version: '2012-10-17', - Statement: [ - { - Effect: 'Allow', - Action: [ - 'secretsmanager:GetResourcePolicy', - 'secretsmanager:GetSecretValue', - 'secretsmanager:DescribeSecret', - ], - Resource: [ - { 'Fn::Join': ['', ['arn:aws:secretsmanager:', { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, ':secret:qna-*']] }, - { 'Fn::Join': ['', ['arn:aws:secretsmanager:', { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, ':secret:QNA-*']] }, - ], - }, - ], - }, - }], + ], }, Metadata: { cfn_nag: util.cfnNag(['W11', 'W12']), @@ -288,6 +282,9 @@ function jslambda(name) { }, }, Handler: `${name}.handler`, + LoggingConfig: { + LogGroup: { Ref: `${name}LogGroup` }, + }, MemorySize: '2048', Role: { 'Fn::GetAtt': ['ExtensionLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -342,6 +339,9 @@ function pylambda(name) { }, }, Handler: `${name}.handler`, + LoggingConfig: { + LogGroup: { Ref: `${name}LogGroup` }, + }, MemorySize: '2048', Role: { 'Fn::GetAtt': ['ExtensionLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_pythonRuntime, @@ -379,3 +379,31 @@ function codeVersion(name) { }, }; } + +function lambdaLogGroup(name) { + return { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}' }, + `EXT${name}`, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }; +} diff --git a/source/templates/examples/extensions/js_lambda_hooks/CreateRecentTopicsResponse/package-lock.json b/source/templates/examples/extensions/js_lambda_hooks/CreateRecentTopicsResponse/package-lock.json index 367e6a19c..386998f83 100644 --- a/source/templates/examples/extensions/js_lambda_hooks/CreateRecentTopicsResponse/package-lock.json +++ b/source/templates/examples/extensions/js_lambda_hooks/CreateRecentTopicsResponse/package-lock.json @@ -1,12 +1,12 @@ { "name": "createrecenttopicsresponse", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "createrecenttopicsresponse", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "lodash": "^4.17.21" diff --git a/source/templates/examples/extensions/js_lambda_hooks/CreateRecentTopicsResponse/package.json b/source/templates/examples/extensions/js_lambda_hooks/CreateRecentTopicsResponse/package.json index 3b0045736..0abab4666 100644 --- a/source/templates/examples/extensions/js_lambda_hooks/CreateRecentTopicsResponse/package.json +++ b/source/templates/examples/extensions/js_lambda_hooks/CreateRecentTopicsResponse/package.json @@ -1,6 +1,6 @@ { "name": "createrecenttopicsresponse", - "version": "6.0.3", + "version": "6.1.0", "description": "Lambda hook that creates recent topic response", "main": "CreateRecentTopicResponse.js", "scripts": { diff --git a/source/templates/examples/extensions/js_lambda_hooks/CustomJSHook/package-lock.json b/source/templates/examples/extensions/js_lambda_hooks/CustomJSHook/package-lock.json index c04d69a0d..13615eea6 100644 --- a/source/templates/examples/extensions/js_lambda_hooks/CustomJSHook/package-lock.json +++ b/source/templates/examples/extensions/js_lambda_hooks/CustomJSHook/package-lock.json @@ -1,16 +1,16 @@ { "name": "examples", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "examples", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "cfn-response": "^1.0.1", - "handlebars": "^4.7.7", + "handlebars": "^4.7.8", "lodash": "^4.17.21" } }, @@ -19,19 +19,14 @@ "resolved": "https://registry.npmjs.org/cfn-response/-/cfn-response-1.0.1.tgz", "integrity": "sha1-qOwDlQwGg8UUlejKaA2dwLiEsTc=" }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "optional": true - }, "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", "dependencies": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, @@ -56,9 +51,10 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "node_modules/neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" }, "node_modules/source-map": { "version": "0.6.1", @@ -69,13 +65,11 @@ } }, "node_modules/uglify-js": { - "version": "3.9.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.4.tgz", - "integrity": "sha512-8RZBJq5smLOa7KslsNsVcSH+KOXf1uDU8yqLeNuVKwmT0T3FA0ZoXlinQfRad7SDcbZZRZE4ov+2v71EnxNyCA==", + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", + "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", + "license": "BSD-2-Clause", "optional": true, - "dependencies": { - "commander": "~2.20.3" - }, "bin": { "uglifyjs": "bin/uglifyjs" }, @@ -95,21 +89,15 @@ "resolved": "https://registry.npmjs.org/cfn-response/-/cfn-response-1.0.1.tgz", "integrity": "sha1-qOwDlQwGg8UUlejKaA2dwLiEsTc=" }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "optional": true - }, "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "requires": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", - "uglify-js": "^3.1.4", + "uglify-js": "^3.19.2", "wordwrap": "^1.0.0" } }, @@ -124,9 +112,9 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "source-map": { "version": "0.6.1", @@ -134,13 +122,10 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "uglify-js": { - "version": "3.9.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.4.tgz", - "integrity": "sha512-8RZBJq5smLOa7KslsNsVcSH+KOXf1uDU8yqLeNuVKwmT0T3FA0ZoXlinQfRad7SDcbZZRZE4ov+2v71EnxNyCA==", - "optional": true, - "requires": { - "commander": "~2.20.3" - } + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", + "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", + "optional": true }, "wordwrap": { "version": "1.0.0", diff --git a/source/templates/examples/extensions/js_lambda_hooks/CustomJSHook/package.json b/source/templates/examples/extensions/js_lambda_hooks/CustomJSHook/package.json index c179c1761..84e9e85ac 100644 --- a/source/templates/examples/extensions/js_lambda_hooks/CustomJSHook/package.json +++ b/source/templates/examples/extensions/js_lambda_hooks/CustomJSHook/package.json @@ -1,6 +1,6 @@ { "name": "examples", - "version": "6.0.3", + "version": "6.1.0", "description": "Creates custom JS Lambda Hooks", "main": "index.js", "scripts": { @@ -13,7 +13,10 @@ "license": "Apache-2.0", "dependencies": { "cfn-response": "^1.0.1", - "handlebars": "^4.7.7", + "handlebars": "^4.7.8", "lodash": "^4.17.21" + }, + "overrides": { + "uglify-js": "^3.19.2" } } diff --git a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/CanvasLMSHelper.py b/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/CanvasLMSHelper.py deleted file mode 100644 index 737153402..000000000 --- a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/CanvasLMSHelper.py +++ /dev/null @@ -1,496 +0,0 @@ -###################################################################################################################### -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # -# with the License. A copy of the License is located at # -# # -# http://www.apache.org/licenses/LICENSE-2.0 # -# # -# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES # -# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # -# and limitations under the License. # -###################################################################################################################### - -# NOTICE: Canvas LMS integration with QnABot on AWS is deprecated in this release and no longer be supported. Customers may fork the code needed for their specific use case from previous versions. The integration code will be removed in the next release. - -import json -import os -import boto3 -import base64 -import datetime -import calendar -from botocore import config - -from bs4 import BeautifulSoup -from botocore.exceptions import ClientError - -CONTENT_TYPE = 'application/vnd.amazonaws.card.generic' -TITLE = 'response buttons' -SSML_PREOUTPUT = 'Please select one of these options: ' -NOT_FOUND_RESP = 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in, to get a list of enrolled courses.' - -def get_secret(secrets_name): - """ - function: get_secret from AWS Secrets Manager - This function retrieves the secret string from AWS Secrets Manager. - We will retrieve the Canvas API Token using this function. - Refer to the readme for more details on how to store secret in AWS Secrets Manager, and configure QnABot with the secret key name. - """ - - region_name = os.environ['AWS_REGION'] - - # Create a Secrets Manager client - session = boto3.session.Session() - client = session.client( - service_name='secretsmanager', - config= config.Config(region_name=region_name, - user_agent_extra = f"AWSSOLUTION/{os.environ['SOLUTION_ID']}/{os.environ['SOLUTION_VERSION']} AWSSOLUTION-CAPABILITY/{os.environ['SOLUTION_ID']}-C018/{os.environ['SOLUTION_VERSION']}")) - - # In this sample we only handle the specific exceptions for the 'GetSecretValue' API. - # See https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html - # We rethrow the exception by default. - - try: - get_secret_value_response = client.get_secret_value( - SecretId=secrets_name - ) - # Decrypts secret using the associated KMS CMK. - # Depending on whether the secret is a string or binary, one of these fields will be populated. - if 'SecretString' in get_secret_value_response: - secret = get_secret_value_response['SecretString'] - secret = json.loads(get_secret_value_response['SecretString'])['API_Token'] - else: - decoded_binary_secret = base64.b64decode(get_secret_value_response['SecretBinary']) - secret = decoded_binary_secret.API_Token - except ClientError as e: - print ("ERROR: "+ str(e)) #print the exception - raise e - - #return the API token - return secret - - -def get_canvas_user (param_canvas, param_user_name): - """ - function to get Canvas User - This function retrieves the Canvas user by using the SIS Login ID - """ - - user = param_canvas.get_user(param_user_name, 'sis_login_id') - return user - - -def query_menu (event, student_name): # NOSONAR param passed from upstream - """ - function to get menu - """ - - # provide a menu to choose from (announcements, enrollments, syllabus, assignments, grades) - choicelist = [{'text':'Announcements','value':"tell me about my announcements"}, {'text':'Course Enrollments','value':"tell me about my enrollments"}, {'text':'Course Syllabus','value':"tell me about my syllabus"}, {'text':'Assignments','value':"tell me about my assignments"}, {'text':'Grades','value':"tell me about my grades"}] - generic_attachments = {'version': '1','contentType': CONTENT_TYPE,'genericAttachments':[{"title": TITLE,"buttons":choicelist}]} - event['res']['session']['appContext']['responseCard'] = generic_attachments - event['res']['session']['appContext']['altMessages']['markdown'] = "Please select one of the options below:" # NOSONAR Do not need a literal - - int_counter = 0 - str_choice_list = "" - for _ in choicelist: - if str_choice_list != '': - str_choice_list = str_choice_list + ", " - str_choice_list = str_choice_list + choicelist[int_counter]['text'] - int_counter = int_counter + 1 - event['res']['session']['appContext']['altMessages']['ssml'] = get_ssml_output(SSML_PREOUTPUT + str_choice_list) - - return event - - -def query_enrollments_for_student(event, canvas, student_user_name): - """ - function: query_enrollments_for_student - This function retrieves students' active enrollments - """ - - # Get the user using user_id to match with LMS SIS_ID - try: - user = get_canvas_user (canvas, student_user_name) - except: # NOSONAR Function to log exception already implemented - return user_not_found_error (event) - - if user: - courses = user.get_courses(enrollment_status='active',include=['syllabus_body']) - # Loop through the courses. - course_names = [course.name for course in courses] - - result = {"CourseNames": course_names} - - return_courses = result['CourseNames'] - if return_courses: - choicelist = [] - for i in return_courses: - choicelist.append({'text':i,'value':"more information about my {} course".format(i)}) - generic_attachments = {'version': '1','contentType': CONTENT_TYPE,'genericAttachments':[{"title":TITLE,"buttons":choicelist}]} - event['res']['session']['appContext']['responseCard'] = generic_attachments - event['res']['session']['appContext']['altMessages']['markdown'] = "Please select one of the options below:" - - int_counter = 0 - str_choice_list = "" - for _ in choicelist: - if str_choice_list != '': - str_choice_list = str_choice_list + ", " - str_choice_list = str_choice_list + choicelist[int_counter]['text'] - int_counter = int_counter + 1 - event['res']['session']['appContext']['altMessages']['ssml'] = get_ssml_output(SSML_PREOUTPUT + str_choice_list) - else: - return_message = "You are not currently enrolled in any courses." - set_alt_message (event, return_message) - - return event - -def is_not_filtered_course(course_name_to_filter, course): - return course_name_to_filter != '' and course.name.upper().strip() != course_name_to_filter.upper() - -def is_filtered_course(course_name_to_filter, course): - return course_name_to_filter != '' and course.name.upper().strip() == course_name_to_filter.upper() - -def get_course_result(course_name_to_filter, user): - bln_found_course = False - if user: - courses = user.get_courses(enrollment_status='active') - # Loop through the courses. - for course in courses: - if is_filtered_course(course_name_to_filter, course): - result = {"Choice": course.name} - bln_found_course = True - break - if bln_found_course == False: - result = {"Choice": 'N/A'} - else: - result = {"Choice": 'N/A'} - return result - -def query_courses_for_student(event, canvas, student_user_name, course_name_to_filter): - """ - function: query_courses_for_student - This function retrieves course options across all active enrolled courses, or for a particular course, for the student - for example: more information about {course name} - """ - - # Get the user using user_id to match with LMS SIS_ID - try: - user = get_canvas_user (canvas, student_user_name) - except: # NOSONAR Function to log exception already implemented - return user_not_found_error (event) - - result = get_course_result(course_name_to_filter, user) - - returned_course = result['Choice'] - if returned_course == 'N/A': - return_message = NOT_FOUND_RESP - - set_alt_message (event, return_message) - else: - generic_attachment = ['assignments','syllabus','grades'] - choice_list = [] - for i in generic_attachment: - choice_list.append({'text':'{} {}'.format(returned_course,i),'value':'tell me about my {} {}'.format(returned_course,i)}) - generic_attachments = {'version': '1','contentType': CONTENT_TYPE,'genericAttachments':[{"title":TITLE,"buttons":choice_list}]} - event['res']['session']['appContext']['responseCard'] = generic_attachments - event['res']['session']['appContext']['altMessages']['markdown'] = "Please select one of the options below:" - - int_counter = 0 - str_choice_list = "" - for _ in choice_list: - if str_choice_list != '': - str_choice_list = str_choice_list + ", " - str_choice_list = str_choice_list + choice_list[int_counter]['text'] - int_counter = int_counter + 1 - event['res']['session']['appContext']['altMessages']['ssml'] = get_ssml_output(SSML_PREOUTPUT + str_choice_list) - return event - -def append_assignment_due_date(assignment): - if assignment.due_at: #check if assignments have due dates - due_date = datetime.datetime.strptime(assignment.due_at,'%Y-%m-%dT%H:%M:%SZ') - due_date_string = '{0}, {1} {2}, {3}'.format(calendar.day_name[due_date.weekday()], due_date.strftime("%B"), due_date.strftime("%-d"), due_date.strftime("%Y")) - return "
  • {} -- is due: {}.
  • ".format(assignment.name, due_date_string) - else: - return "
  • {} -- has no due date.
  • ".format(assignment.name) - -def get_course_assignments(course_name_to_filter, no_records_message, user): - course_assignments = '' - bln_has_assignments = False - bln_found_match = False - courses = user.get_courses(enrollment_status='active') - - for course in courses: - bln_has_assignments = False - bln_found_match = False - - #check for matching course_name_slot_input with course names - if is_filtered_course(course_name_to_filter, course): - bln_found_match = True - - if bln_found_match == True: - course_assignments = "" + course.name + ":
      " - else: - course_assignments += "" + course.name + ":
        " - - # Loop through the assignments that have not been submitted - for assignment in course.get_assignments(bucket='unsubmitted'): - bln_has_assignments = True - if is_not_filtered_course(course_name_to_filter, course): - # if a slot value is provided, but does not have a matching course that the student is enrolled in - course_assignments = NOT_FOUND_RESP - break - - course_assignments += append_assignment_due_date(assignment) - - if bln_has_assignments == False: - course_assignments += no_records_message - - course_assignments += "

      " - - #if found a matching course, then break from the course For loop - if bln_found_match == True: - break - return course_assignments - -def query_course_assignments_for_student(event, canvas, student_user_name, course_name_to_filter): - """ - function: query_course_assignments_for_student - This function retrieves assignment information across all active enrolled courses, or for a particular course, for the student - for example: do i have any assignments due or tell me about by {course_name} assignments - """ - - no_records_message = 'There are no assignments for this course.' - # Get the user using user_id to match with LMS SIS_ID - try: - user = get_canvas_user (canvas, student_user_name) - except: # NOSONAR Function to log exception already implemented - return user_not_found_error (event) - - if user: - course_assignments = get_course_assignments(course_name_to_filter, no_records_message, user) - result = {"CourseAssignments": course_assignments} - if result['CourseAssignments']: - return_message = result['CourseAssignments'] - set_alt_message (event, return_message) - else: - return_message = no_records_message - set_alt_message (event, return_message) - - return event - -def query_announcements_for_student(event, canvas, student_user_name): - """ - function: query_announcements_for_student - This function retrieves any announcements across all active enrolled courses for the student - for example: do i have any announcements - """ - - no_records_message = 'You currently have no announcements.' - course_announcements = '' - - # Get the user using user_id to match with LMS SIS_ID - try: - user = get_canvas_user (canvas, student_user_name) - except: # NOSONAR Function to log exception already implemented - return user_not_found_error (event) - - course_names = [] - if user: - courses = user.get_courses(enrollment_status='active') - - # Loop through the courses. - for course in courses: - course_names.append(course.name) - # get_announcements returns a list of discussion topics. - for discussion_topic in canvas.get_announcements(context_codes=[course.id]): - if discussion_topic: - announcement_date = datetime.datetime.strftime(discussion_topic.posted_at_date,"%b %d %Y %-I:%M %p") # NOSONAR storing the date in string - course_announcements += '
    • {0}: {1}:
      {2}.
    • '.format(course.name, discussion_topic.title, discussion_topic.message) - else: - course_announcements += no_records_message - - if course_announcements != '': - course_announcements = "
        " + course_announcements + "
      " - - result = {"Announcements": course_announcements} - - if result['Announcements']: - return_message = 'Here are your announcements: {}'.format(result['Announcements']) - set_alt_message (event, return_message) - else: - set_alt_message (event, no_records_message) - - return event - -def get_grade_score(grade): - if grade.grades['current_score'] != '': - grade_score = grade.grades['current_score'] - else: - grade_score = "N/A" - return grade_score - -def query_grades_for_student(event, canvas, student_user_name, course_name_to_filter): - """ - function: query_grades_for_student - This function retrieves grade information across all active enrolled courses, or for a particular course, for the student - for example: tell me about my grades, or how did i do in {course name} - """ - - no_records_message = "There are no enrolled courses." - course_grades = '
        ' - # Get the user using user_id to match with LMS SIS_ID - try: - user = get_canvas_user (canvas, student_user_name) - except: # NOSONAR Function to log exception already implemented - return user_not_found_error (event) - - if user: - # Loop through the courses - courses = user.get_enrollments(include='current_points', search_by='course') - - if courses: - for grade in courses: - course_name = canvas.get_course(grade.course_id) - grade_score = get_grade_score(grade) - - #check for matching course_name_slot_input with course names - if is_filtered_course(course_name_to_filter, course_name): - course_grades = "
      • Grades for {} course: {}.
      • ".format(course_name.name, grade_score) - break - elif course_name_to_filter != '': - # if a slot value is provided, but does not have a matching course that the student is enrolled in - course_grades = NOT_FOUND_RESP - else: - course_grades += "
      • Grades for {} course: {}.
      • ".format(course_name.name, grade_score) - else: - course_grades = no_records_message - - course_grades += "
      " - - result = {"Grades": course_grades} - - return_message = result['Grades'] - set_alt_message (event, return_message) - - return event - -def query_syllabus_for_student(event, canvas, student_user_name, course_name_to_filter): - """ - function: query_syllabus_for_student - This function retrieves syllabus information across all active enrolled courses, or for a particular course, for the student - for example: what is my syllabus, or tell me about my {course name} syllabus - """ - - no_records_message = 'There is no syllabus currently available for this course.' - course_syllabus = '' - - # Get the user using user_id to match with LMS SIS_ID - try: - user = get_canvas_user (canvas, student_user_name) - except: # NOSONAR Function to log exception already implemented - return user_not_found_error (event) - - if user: - courses = user.get_courses(enrollment_status='active',include=['syllabus_body']) - - # Loop through the courses. - for course in courses: - #check for matching course_name_slot_input with course names - if is_filtered_course(course_name_to_filter, course): - if course.syllabus_body.strip() != '': - course_syllabus = '{0}: {1}
      '.format(course.name, course.syllabus_body) - else: - course_syllabus = no_records_message - break - elif course_name_to_filter != '': - # if a slot value is provided, but does not have a matching course that the student is enrolled in - course_syllabus = NOT_FOUND_RESP - else: - if course.syllabus_body.strip() != '': - course_syllabus += '{0}: {1}.
      '.format(course.name, course.syllabus_body) - else: - course_syllabus += '{0}: {1}.
      '.format(course.name, no_records_message) - - result = {"CourseSyllabus": course_syllabus} - - return_message = result['CourseSyllabus'] - set_alt_message (event, return_message) - - return event - - -def validate_input(event): - """ - function: validate_input - This function checks whether the user is logged in - Additionally, also checks if QnABot is configured with the required parameters - """ - - error_message = '' - - try: - if json.loads(event['res']['result']['args'][0])['Query'] == '': - error_message = 'There was an error processing your request. Please check the question setup and try again.' - return error_message - - if event['req']['_userInfo']['isVerifiedIdentity'] != "true": - error_message = 'There was an error processing your request. Please check your login and try again, or contact your administrator.' - return error_message - - if event['req']['_settings']['CanvasDomainName'].strip() == '' or event['req']['_settings']['CanvasAPIKey'].strip() == '' or event['req']['_settings']['CanvasCourseNameSlot'].strip() == '': - error_message = 'There was an error processing your request. Please check the QnABot custom setting names/values and try again.' - return error_message - except Exception as e: - print("validate_input exception") - print(e) - error_message = 'There was an error processing your request. Please check the question setup and try again.' - return error_message - - -def remove_html_tags (str_input): - """ - function to remove HTML tags - """ - - #parse html input string - obj_b_soup = BeautifulSoup(str_input, "html.parser") - - for data in obj_b_soup (['style', 'script']): - #remove html tags - data.decompose() - - # return - return ' '.join(obj_b_soup.stripped_strings) - - -def get_ssml_output (str_input): - """ - function to return SSML output - """ - - #parse html input string - return "" + remove_html_tags(str_input) + "" - - -def set_alt_message (event, str_input): - """ - function to set alt messages - """ - - # set markdown output - event['res']['session']['appContext']['altMessages']['markdown'] = str_input - # set ssml output - event['res']['session']['appContext']['altMessages']['ssml'] = get_ssml_output (str_input) - - -def user_not_found_error(event): - """ - function to return error message when user id does not exist in Canvas LMS - """ - - print ("user_not_found_error") - return_message = "There was an error processing your request. Please check your login and try again, or contact your administrator." - set_alt_message (event, return_message) - - return event diff --git a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/CanvasLMSHook.py b/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/CanvasLMSHook.py deleted file mode 100644 index b94757567..000000000 --- a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/CanvasLMSHook.py +++ /dev/null @@ -1,118 +0,0 @@ -###################################################################################################################### -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # -# with the License. A copy of the License is located at # -# # -# http://www.apache.org/licenses/LICENSE-2.0 # -# # -# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES # -# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # -# and limitations under the License. # -###################################################################################################################### - -# NOTICE: Canvas LMS integration with QnABot on AWS is deprecated in this release and no longer be supported. Customers may fork the code needed for their specific use case from previous versions. The integration code will be removed in the next release. - -# Import the Canvas class -from canvasapi import Canvas - -import CanvasLMSHelper as CanvasLMS - - -api_token = '' #variable to hold the value of API_Token stored in AWS Secrets Manager -canvas = None #variable to hold the Canvas object - - -def handler(event, context): # NOSONAR Lambda Handler - """ - function handler - Main handler function - This function processes: - a. lambda hook arguments - b. processes user input - c. provides response back to the user - """ - - global api_token - global canvas - - return_message = '' - course_name_slot_input = '' - course_name_slot_resolved_input = '' - course_name_to_filter = '' - - # Validate the required input. - error_message = CanvasLMS.validate_input(event) - - if error_message: - return_message = error_message - CanvasLMS.set_alt_message (event, return_message) - else: - # get the API domain. This will be needed for API calls and for looking up the bearer token. - domain = event['req']['_settings']['CanvasLMS_DomainName'].strip() - secrets_name = event['req']['_settings']['CanvasLMS_APIKey'].strip() - course_name_slot = 'CanvasLMS_course_name_slot' - - try: - # get slot value if present - course_name_slot_input = event["req"]["_event"]["interpretations"][0]["intent"]["slots"][course_name_slot]["value"].get("originalValue", '') - except: # NOSONAR the case is handled and no exception is needed - course_name_slot_input = '' - - course_name_slot_resolved_input = event["req"]["slots"].get(course_name_slot, '') - course_name_to_filter = course_name_slot_resolved_input - - if (course_name_slot_resolved_input == '' and course_name_slot_input != ''): - return_message = "Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in, to get a list of enrolled courses." - CanvasLMS.set_alt_message (event, return_message) - return event - - - # Get the API Token from AWS Secrets Manager - if api_token == '': - api_token = CanvasLMS.get_secret(secrets_name) - - # Initialize Canvas object - if canvas is None: - canvas = Canvas(domain, api_token) - - try: - # Get the student's profile from the request - student_user_name = event['req']['_userInfo']['UserName'] - student_name = event['req']['_userInfo']['GivenName'] - - # Get the query from the request (lambda function argument) - query = CanvasLMS.json.loads(event['res']['result']['args'][0])['Query'] - match query: - case 'CanvasMenu': - # retrieve the menu - return CanvasLMS.query_menu (event, student_name) - case'CourseEnrollments': - # retrieve the course options for this student. - return CanvasLMS.query_enrollments_for_student(event, canvas, student_user_name) - case 'CourseAssignments': - # retrieve the assignments for this student. - return CanvasLMS.query_course_assignments_for_student(event, canvas, student_user_name, course_name_to_filter) - case 'SyllabusForCourse': - # retrieve the course syllabus for this student. - return CanvasLMS.query_syllabus_for_student(event, canvas, student_user_name, course_name_to_filter) - case 'CoursesForStudent': - # retrieve the course options for this student. - return CanvasLMS.query_courses_for_student(event, canvas, student_user_name, course_name_to_filter) - case 'AnnouncementsForStudent': - # retrieve the announcements for this student. - return CanvasLMS.query_announcements_for_student(event, canvas, student_user_name) - case 'GradesForStudent': - # retrieve the course grades for this student. - return CanvasLMS.query_grades_for_student(event, canvas, student_user_name, course_name_to_filter) - case _: - return_message = 'There was an error processing your request. For a list of available options, type or say canvas menu.' - CanvasLMS.set_alt_message (event, return_message) - return event - except ValueError as e: - print ("ERROR: "+ str(e)) #print the exception - return_message = 'There was an error processing your request. Please contact your administrator.' - CanvasLMS.set_alt_message (event, return_message) - return event - - return event diff --git a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/__init__.py b/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/test_CanvasLMSHelper.py b/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/test_CanvasLMSHelper.py deleted file mode 100644 index 2221e3e7d..000000000 --- a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/test_CanvasLMSHelper.py +++ /dev/null @@ -1,847 +0,0 @@ -###################################################################################################################### -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # -# with the License. A copy of the License is located at # -# # -# http://www.apache.org/licenses/LICENSE-2.0 # -# # -# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES # -# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # -# and limitations under the License. # -###################################################################################################################### - -# NOTICE: Canvas LMS integration with QnABot on AWS is deprecated in this release and no longer be supported. Customers may fork the code needed for their specific use case from previous versions. The integration code will be removed in the next release. - -from unittest.mock import Mock -import pytest -import datetime -import json -from botocore.exceptions import ClientError -from moto import mock_secretsmanager - -class TestCanvasLMSHelper(): - - @mock_secretsmanager - def test_get_secret_with_secret_string(self, mock_sm): - from CanvasLMSHelper import get_secret - mock_sm.create_secret(Name='test', SecretString=json.dumps({'API_Token': 'value'})) - response = get_secret('test') - assert response == 'value' - - @mock_secretsmanager - def test_get_secret_without_secret_string(self): - from CanvasLMSHelper import get_secret - try: - get_secret('test') - except ClientError as e: - assert e.args[0] == "An error occurred (ResourceNotFoundException) when calling the GetSecretValue operation: Secrets Manager can't find the specified secret." - - def test_get_canvas_user(self): - from CanvasLMSHelper import get_canvas_user - canvas_mock = Mock() - get_canvas_user(canvas_mock, 'user') - canvas_mock.get_user.assert_called_with('user', 'sis_login_id') - - def test_query_menu(self): - from CanvasLMSHelper import query_menu - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_menu(event, 'user') - assert response == {'res': {'session': {'appContext': {'responseCard': {'version': '1', 'contentType': 'application/vnd.amazonaws.card.generic', 'genericAttachments': [{'title': 'response buttons', 'buttons': [{'text': 'Announcements', 'value': 'tell me about my announcements'}, {'text': 'Course Enrollments', 'value': 'tell me about my enrollments'}, {'text': 'Course Syllabus', 'value': 'tell me about my syllabus'}, {'text': 'Assignments', 'value': 'tell me about my assignments'}, {'text': 'Grades', 'value': 'tell me about my grades'}]}]}, 'altMessages': {'markdown': 'Please select one of the options below:', 'ssml': 'Please select one of these options: Announcements, Course Enrollments, Course Syllabus, Assignments, Grades'}}}}} - - def test_query_enrollments_for_student(self): - from CanvasLMSHelper import query_enrollments_for_student - course_mock = Mock() - course_mock.name = 'course name' - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_enrollments_for_student(event, canvas_mock, 'user') - assert response == {'res': {'session': {'appContext': {'responseCard': {'version': '1', 'contentType': 'application/vnd.amazonaws.card.generic', 'genericAttachments': [{'title': 'response buttons', 'buttons': [{'text': 'course name', 'value': 'more information about my course name course'}]}]}, 'altMessages': {'markdown': 'Please select one of the options below:', 'ssml': 'Please select one of these options: course name'}}}}} - - def test_query_enrollments_for_student_with_more_than_one_course(self): - from CanvasLMSHelper import query_enrollments_for_student - course_mock = Mock() - course_mock.name = 'course name' - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock, course_mock] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_enrollments_for_student(event, canvas_mock, 'user') - assert response == {'res': {'session': {'appContext': {'responseCard': {'version': '1', 'contentType': 'application/vnd.amazonaws.card.generic', 'genericAttachments': [{'title': 'response buttons', 'buttons': [{'text': 'course name', 'value': 'more information about my course name course'}, {'text': 'course name', 'value': 'more information about my course name course'}]}]}, 'altMessages': {'markdown': 'Please select one of the options below:', 'ssml': 'Please select one of these options: course name, course name'}}}}} - - def test_query_enrollments_for_student_with_no_courses(self): - from CanvasLMSHelper import query_enrollments_for_student - user_mock = Mock() - user_mock.get_courses.return_value = [] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_enrollments_for_student(event, canvas_mock, 'user') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'You are not currently enrolled in any courses.', 'ssml': 'You are not currently enrolled in any courses.'}}}}} - - def test_query_enrollments_for_missing_student(self): - from CanvasLMSHelper import query_enrollments_for_student - canvas_mock = Mock() - canvas_mock.get_user.side_effect = Exception('user not found') - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - - response = query_enrollments_for_student(event, canvas_mock, 'user') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'There was an error processing your request. Please check your login and try again, or contact your administrator.', 'ssml': 'There was an error processing your request. Please check your login and try again, or contact your administrator.'}}}}} - - def test_query_courses_for_student(self): - from CanvasLMSHelper import query_courses_for_student - course_mock = Mock() - course_mock.name = 'course name' - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_courses_for_student(event, canvas_mock, 'user', 'course name') - assert response == {'res': {'session': {'appContext': {'responseCard': {'version': '1', 'contentType': 'application/vnd.amazonaws.card.generic', 'genericAttachments': [{'title': 'response buttons', 'buttons': [{'text': 'course name assignments', 'value': 'tell me about my course name assignments'}, {'text': 'course name syllabus', 'value': 'tell me about my course name syllabus'}, {'text': 'course name grades', 'value': 'tell me about my course name grades'}]}]}, 'altMessages': {'markdown': 'Please select one of the options below:', 'ssml': 'Please select one of these options: course name assignments, course name syllabus, course name grades'}}}}} - - def test_query_courses_for_student_with_course_not_found(self): - from CanvasLMSHelper import query_courses_for_student - course_mock = Mock() - course_mock.name = 'course name' - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_courses_for_student(event, canvas_mock, 'user', 'missing course') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in, to get a list of enrolled courses.', 'ssml': 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in , to get a list of enrolled courses.'}}}}} - - def test_query_courses_for_student_when_student_not_found(self): - from CanvasLMSHelper import query_courses_for_student - - canvas_mock = Mock() - canvas_mock.get_user.side_effect = Exception('user not found') - - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_courses_for_student(event, canvas_mock, 'user', 'missing course') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'There was an error processing your request. Please check your login and try again, or contact your administrator.', 'ssml': 'There was an error processing your request. Please check your login and try again, or contact your administrator.'}}}}} - - def test_query_courses_for_student_with_empty_student(self): - from CanvasLMSHelper import query_courses_for_student - - user_mock = '' - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_courses_for_student(event, canvas_mock, 'user', 'missing course') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in, to get a list of enrolled courses.', 'ssml': 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in , to get a list of enrolled courses.'}}}}} - - def test_query_course_assignments_for_student(self): - from CanvasLMSHelper import query_course_assignments_for_student - - assignment1 = Mock() - assignment2 = Mock() - assignment1.name = 'assignment 1' - assignment2.name = 'assignment 2' - assignment1.due_at = '2020-01-01T00:00:00Z' - assignment2.due_at = '' - course_mock = Mock() - course_mock.name = 'course name' - course_mock.get_assignments = lambda bucket: [assignment1, assignment2] - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_course_assignments_for_student(event, canvas_mock, 'user', 'course name') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'course name:
      • assignment 1 -- is due: Wednesday, January 1, 2020.
      • assignment 2 -- has no due date.

      ', 'ssml': 'course name: assignment 1 -- is due: Wednesday, January 1, 2020. assignment 2 -- has no due date.'}}}}} - - def test_query_course_assignments_for_student_unfiltered_course(self): - from CanvasLMSHelper import query_course_assignments_for_student - - assignment1 = Mock() - assignment2 = Mock() - assignment1.name = 'assignment 1' - assignment2.name = 'assignment 2' - assignment1.due_at = '2020-01-01T00:00:00Z' - assignment2.due_at = '' - course_mock = Mock() - course_mock.name = 'course name' - course_mock.get_assignments = lambda bucket: [assignment1, assignment2] - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_course_assignments_for_student(event, canvas_mock, 'user', 'not course name') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in, to get a list of enrolled courses.

    ', 'ssml': 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in , to get a list of enrolled courses.'}}}}} - - def test_query_course_assignments_for_student_with_course_with_no_assignments(self): - from CanvasLMSHelper import query_course_assignments_for_student - - course_mock = Mock() - course_mock.name = 'course name' - course_mock.get_assignments = lambda bucket: [] - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_course_assignments_for_student(event, canvas_mock, 'user', 'not course name') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'course name:
      There are no assignments for this course.

    ', 'ssml': 'course name: There are no assignments for this course.'}}}}} - - def test_query_course_assignments_for_student_with_no_courses(self): - from CanvasLMSHelper import query_course_assignments_for_student - - user_mock = Mock() - user_mock.get_courses.return_value = [] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_course_assignments_for_student(event, canvas_mock, 'user', 'not course name') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'There are no assignments for this course.', 'ssml': 'There are no assignments for this course.'}}}}} - - def test_query_course_assignments_for_student_when_no_student(self): - from CanvasLMSHelper import query_course_assignments_for_student - - canvas_mock = Mock() - canvas_mock.get_user.side_effect = Exception('user not found') - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_course_assignments_for_student(event, canvas_mock, 'user', 'not course name') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'There was an error processing your request. Please check your login and try again, or contact your administrator.', 'ssml': 'There was an error processing your request. Please check your login and try again, or contact your administrator.'}}}}} - - - def test_query_announcements_for_student(self): - from CanvasLMSHelper import query_announcements_for_student - - discussion_topic = Mock() - discussion_topic.posted_at_date = datetime.datetime.now().date() - discussion_topic.title = 'title' - discussion_topic.message = 'do your homework!' - course_mock = Mock() - course_mock.name = 'course name' - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock] - canvas_mock = Mock() - canvas_mock.get_announcements = lambda context_codes: [discussion_topic, {}] - canvas_mock.get_user.return_value = user_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_announcements_for_student(event, canvas_mock, 'user') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'Here are your announcements:
    • course name: title:
      do your homework!.
    • You currently have no announcements.
    ', 'ssml': 'Here are your announcements: course name : title: do your homework!. You currently have no announcements.'}}}}} - - def test_query_announcements_for_student_with_no_announcements(self): - from CanvasLMSHelper import query_announcements_for_student - - course_mock = Mock() - course_mock.name = 'course name' - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock] - canvas_mock = Mock() - canvas_mock.get_announcements = lambda context_codes: [] - canvas_mock.get_user.return_value = user_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_announcements_for_student(event, canvas_mock, 'user') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'You currently have no announcements.', 'ssml': 'You currently have no announcements.'}}}}} - - def test_query_announcements_for_student_when_no_student(self): - from CanvasLMSHelper import query_announcements_for_student - - canvas_mock = Mock() - canvas_mock.get_user.side_effect = Exception('user not found') - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_announcements_for_student(event, canvas_mock, 'user') - assert response =={'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'There was an error processing your request. Please check your login and try again, or contact your administrator.', 'ssml': 'There was an error processing your request. Please check your login and try again, or contact your administrator.'}}}}} - - def test_query_grades_for_student(self): - from CanvasLMSHelper import query_grades_for_student - - grade_mock1 = Mock() - grade_mock1.course_id = '1' - grade_mock1.grades = { - 'current_score': 100 - } - grade_mock2 = Mock() - grade_mock2.course_id = '2' - grade_mock2.grades = { - 'current_score': '' - } - course_mock = Mock() - course_mock.name = 'course name' - user_mock = Mock() - user_mock.get_enrollments.return_value = [grade_mock1, grade_mock2] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - canvas_mock.get_course = lambda course_id: course_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_grades_for_student(event, canvas_mock, 'user', '') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': '
    • Grades for course name course: 100.
    • Grades for course name course: N/A.
    ', 'ssml': 'Grades for course name course: 100. Grades for course name course: N/A.'}}}}} - - def test_query_grades_for_student_with_filtered_course(self): - from CanvasLMSHelper import query_grades_for_student - - grade_mock1 = Mock() - grade_mock1.course_id = '1' - grade_mock1.grades = { - 'current_score': 100 - } - grade_mock2 = Mock() - grade_mock2.course_id = '2' - grade_mock2.grades = { - 'current_score': '' - } - course_mock = Mock() - course_mock.name = 'course name' - user_mock = Mock() - user_mock.get_enrollments.return_value = [grade_mock1, grade_mock2] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - canvas_mock.get_course = lambda course_id: course_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_grades_for_student(event, canvas_mock, 'user', 'course name') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': '
  • Grades for course name course: 100.
  • ', 'ssml': 'Grades for course name course: 100.'}}}}} - - def test_query_grades_for_student_with_filtered_incorrect_course(self): - from CanvasLMSHelper import query_grades_for_student - - grade_mock1 = Mock() - grade_mock1.course_id = '1' - grade_mock1.grades = { - 'current_score': 100 - } - course_mock = Mock() - course_mock.name = 'course name' - user_mock = Mock() - user_mock.get_enrollments.return_value = [grade_mock1] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - canvas_mock.get_course = lambda course_id: course_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_grades_for_student(event, canvas_mock, 'user', 'missing course name') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in, to get a list of enrolled courses.', 'ssml': 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in , to get a list of enrolled courses.'}}}}} - - def test_query_grades_for_student_with_no_courses(self): - from CanvasLMSHelper import query_grades_for_student - - user_mock = Mock() - user_mock.get_enrollments.return_value = [] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_grades_for_student(event, canvas_mock, 'user', '') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'There are no enrolled courses.', 'ssml': 'There are no enrolled courses.'}}}}} - - def test_query_grades_for_student_with_missing_student(self): - from CanvasLMSHelper import query_grades_for_student - - canvas_mock = Mock() - canvas_mock.get_user.side_effect = Exception('user not found') - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_grades_for_student(event, canvas_mock, 'user', '') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'There was an error processing your request. Please check your login and try again, or contact your administrator.', 'ssml': 'There was an error processing your request. Please check your login and try again, or contact your administrator.'}}}}} - - def test_query_syllabus_for_student(self): - from CanvasLMSHelper import query_syllabus_for_student - - course_mock1 = Mock() - course_mock1.name = 'course name' - course_mock1.syllabus_body = 'body' - course_mock2 = Mock() - course_mock2.name = 'course name' - course_mock2.syllabus_body = '' - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock1, course_mock2] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_syllabus_for_student(event, canvas_mock, 'user', '') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'course name: body.
    course name: There is no syllabus currently available for this course..
    ', 'ssml': 'course name : body. course name : There is no syllabus currently available for this course..'}}}}} - - def test_query_syllabus_for_student_with_filter(self): - from CanvasLMSHelper import query_syllabus_for_student - - course_mock1 = Mock() - course_mock1.name = 'course name' - course_mock1.syllabus_body = 'body' - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock1] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_syllabus_for_student(event, canvas_mock, 'user', 'course name') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'course name: body
    ', 'ssml': 'course name : body'}}}}} - - def test_query_syllabus_for_student_with_filtered_course_without_body(self): - from CanvasLMSHelper import query_syllabus_for_student - - course_mock1 = Mock() - course_mock1.name = 'course name' - course_mock1.syllabus_body = '' - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock1] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_syllabus_for_student(event, canvas_mock, 'user', 'course name') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'There is no syllabus currently available for this course.', 'ssml': 'There is no syllabus currently available for this course.'}}}}} - - def test_query_syllabus_for_student_with_incorrect_filtered_course(self): - from CanvasLMSHelper import query_syllabus_for_student - - course_mock1 = Mock() - course_mock1.name = 'course name' - course_mock1.syllabus_body = '' - user_mock = Mock() - user_mock.get_courses.return_value = [course_mock1] - canvas_mock = Mock() - canvas_mock.get_user.return_value = user_mock - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_syllabus_for_student(event, canvas_mock, 'user', 'missing course name') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in, to get a list of enrolled courses.', 'ssml': 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in , to get a list of enrolled courses.'}}}}} - - def test_query_syllabus_for_student_with_missing_student(self): - from CanvasLMSHelper import query_syllabus_for_student - - canvas_mock = Mock() - canvas_mock.get_user.side_effect = Exception('user not found') - - event = { - 'res': { - 'session': { - 'appContext': { - 'responseCard': '', - 'altMessages': { - 'markdown': '' - } - } - } - } - } - response = query_syllabus_for_student(event, canvas_mock, 'user', 'missing course name') - assert response == {'res': {'session': {'appContext': {'responseCard': '', 'altMessages': {'markdown': 'There was an error processing your request. Please check your login and try again, or contact your administrator.', 'ssml': 'There was an error processing your request. Please check your login and try again, or contact your administrator.'}}}}} - - def test_validate_input_correct_input(self): - from CanvasLMSHelper import validate_input - event = { - 'res': { - 'result': { - 'args': [ - json.dumps({ - 'Query': 'test' - }) - ] - } - }, - 'req': { - '_settings': { - 'CanvasDomainName': 'test.com', - 'CanvasAPIKey': 'test', - 'CanvasCourseNameSlot': 'test' - }, - '_userInfo': { - 'isVerifiedIdentity': 'true', - }, - 'slots': {} - }, - } - - error = validate_input(event) - assert error == None - - def test_validate_input_empty_query(self): - from CanvasLMSHelper import validate_input - event = { - 'res': { - 'result': { - 'args': [ - json.dumps({ - 'Query': '' - }) - ] - } - }, - } - - error = validate_input(event) - assert error == 'There was an error processing your request. Please check the question setup and try again.' - - def test_validate_input_is_not_verified_identity(self): - from CanvasLMSHelper import validate_input - event = { - 'res': { - 'result': { - 'args': [ - json.dumps({ - 'Query': 'test' - }) - ] - } - }, - 'req': { - '_userInfo': { - 'isVerifiedIdentity': 'false', - }, - 'slots': {} - }, - } - - error = validate_input(event) - assert error == 'There was an error processing your request. Please check your login and try again, or contact your administrator.' - - def test_validate_input_missing_canvas_info(self): - from CanvasLMSHelper import validate_input - event = { - 'res': { - 'result': { - 'args': [ - json.dumps({ - 'Query': 'test' - }) - ] - } - }, - 'req': { - '_settings': { - 'CanvasDomainName': '', - 'CanvasAPIKey': '', - 'CanvasCourseNameSlot': '' - }, - '_userInfo': { - 'isVerifiedIdentity': 'true', - }, - 'slots': {} - }, - } - - error = validate_input(event) - assert error == 'There was an error processing your request. Please check the QnABot custom setting names/values and try again.' - - def test_validate_input_invalid_object(self): - from CanvasLMSHelper import validate_input - event = {} - - error = validate_input(event) - assert error == 'There was an error processing your request. Please check the question setup and try again.' - - def test_vremove_html_tags(self): - from CanvasLMSHelper import remove_html_tags - str_input = '' - - result = remove_html_tags(str_input) - assert result == '' \ No newline at end of file diff --git a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/test_CanvasLMSHook.py b/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/test_CanvasLMSHook.py deleted file mode 100644 index 6eba49b5e..000000000 --- a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/__tests__/test_CanvasLMSHook.py +++ /dev/null @@ -1,475 +0,0 @@ -###################################################################################################################### -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # -# with the License. A copy of the License is located at # -# # -# http://www.apache.org/licenses/LICENSE-2.0 # -# # -# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES # -# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # -# and limitations under the License. # -###################################################################################################################### - -# NOTICE: Canvas LMS integration with QnABot on AWS is deprecated in this release and no longer be supported. Customers may fork the code needed for their specific use case from previous versions. The integration code will be removed in the next release. - -import unittest -from unittest.mock import patch, Mock -import pytest -from CanvasLMSHook import handler - -@patch('CanvasLMSHook.Canvas') -@patch('CanvasLMSHook.CanvasLMS') -class TestCanvasLMSHook(unittest.TestCase): - - def test_sets_message_with_error_if_query_is_not_valid(self, canvas_lms_mock, canvas_mock): - event = { - 'res': { - 'result': { - 'args': [ - { - 'query': 'test' - } - ] - } - }, - 'req': { - '_settings': { - 'CanvasLMS_DomainName': 'test.com', - 'CanvasLMS_APIKey': 'test' - }, - '_userInfo': { - 'UserName': 'user', - 'GivenName': 'User McStudent' - }, - 'slots': {} - }, - } - - context = {} - - canvas_lms_mock.validate_input.return_value = False - canvas_lms_mock.get_secret.return_value = { - "CanvasLMS_APIKey": "test", - "CanvasLMS_DomainName": "test.com" - } - canvas_lms_mock.json.loads.return_value = { - "Query": "test" - } - - event = handler(event, context) - canvas_lms_mock.set_alt_message.assert_called_once_with({'res': {'result': {'args': [{'query': 'test'}]}}, 'req': {'_settings': {'CanvasLMS_DomainName': 'test.com', 'CanvasLMS_APIKey': 'test'}, '_userInfo': {'UserName': 'user', 'GivenName': 'User McStudent'}, 'slots': {}}}, 'There was an error processing your request. For a list of available options, type or say canvas menu.') - - def test_sets_message_with_error_if_value_error_is_thrown(self, canvas_lms_mock, canvas_mock): - event = { - 'res': { - 'result': { - 'args': [ - { - 'query': 'test' - } - ] - } - }, - 'req': { - '_settings': { - 'CanvasLMS_DomainName': 'test.com', - 'CanvasLMS_APIKey': 'test' - }, - '_userInfo': { - 'UserName': 'user', - 'GivenName': 'User McStudent' - }, - 'slots': {} - }, - } - - context = {} - - canvas_lms_mock.validate_input.return_value = False - canvas_lms_mock.get_secret.return_value = { - "CanvasLMS_APIKey": "test", - "CanvasLMS_DomainName": "test.com" - } - - canvas_lms_mock.json.loads.side_effect = ValueError() - - event = handler(event, context) - canvas_lms_mock.set_alt_message.assert_called_once_with({'res': {'result': {'args': [{'query': 'test'}]}}, 'req': {'_settings': {'CanvasLMS_DomainName': 'test.com', 'CanvasLMS_APIKey': 'test'}, '_userInfo': {'UserName': 'user', 'GivenName': 'User McStudent'}, 'slots': {}}}, 'There was an error processing your request. Please contact your administrator.') - - def test_sets_message_with_error_if_invalid_input(self, canvas_lms_mock, canvas_mock): - event = { - 'res': { - 'result': { - 'args': [ - { - 'query': 'test' - } - ] - } - }, - 'req': { - '_settings': { - 'CanvasLMS_DomainName': 'test.com', - 'CanvasLMS_APIKey': 'test' - }, - '_userInfo': { - 'UserName': 'user', - 'GivenName': 'User McStudent' - }, - 'slots': {} - }, - } - - context = {} - - canvas_lms_mock.validate_input.return_value = True - - event = handler(event, context) - canvas_lms_mock.set_alt_message.assert_called_once_with({'res': {'result': {'args': [{'query': 'test'}]}}, 'req': {'_settings': {'CanvasLMS_DomainName': 'test.com', 'CanvasLMS_APIKey': 'test'}, '_userInfo': {'UserName': 'user', 'GivenName': 'User McStudent'}, 'slots': {}}}, True) - - def test_sets_message_with_error_when_course_name_slot_is_not_empty(self, canvas_lms_mock, canvas_mock): - event = { - 'res': { - 'result': { - 'args': [ - { - 'query': 'test' - } - ] - } - }, - 'req': { - '_settings': { - 'CanvasLMS_DomainName': 'test.com', - 'CanvasLMS_APIKey': 'test' - }, - '_event': { - 'interpretations': [ - { - 'intent': { - 'slots': { - 'CanvasLMS_course_name_slot': { - 'value': { - 'originalValue': 'not_empty' - } - } - } - } - } - ] - }, - '_userInfo': { - 'UserName': 'user', - 'GivenName': 'User McStudent' - }, - 'slots': {} - }, - } - - context = {} - - canvas_lms_mock.validate_input.return_value = False - canvas_lms_mock.get_secret.return_value = { - "CanvasLMS_APIKey": "test", - "CanvasLMS_DomainName": "test.com" - } - - canvas_lms_mock.json.loads.side_effect = ValueError() - - event = handler(event, context) - canvas_lms_mock.set_alt_message.assert_called_once_with({'res': {'result': {'args': [{'query': 'test'}]}}, 'req': {'_settings': {'CanvasLMS_DomainName': 'test.com', 'CanvasLMS_APIKey': 'test'}, '_event': {'interpretations': [{'intent': {'slots': {'CanvasLMS_course_name_slot': {'value': {'originalValue': 'not_empty'}}}}}]}, '_userInfo': {'UserName': 'user', 'GivenName': 'User McStudent'}, 'slots': {}}}, 'Sorry, was unable to find the course you are looking for. Check the course name and try again. You can also ask what courses have i enrolled in, to get a list of enrolled courses.') - - def test_CanvasMenu_called(self, canvas_lms_mock, canvas_mock): - event = { - 'res': { - 'result': { - 'args': [ - { - 'query': 'test' - } - ] - } - }, - 'req': { - '_settings': { - 'CanvasLMS_DomainName': 'test.com', - 'CanvasLMS_APIKey': 'test' - }, - '_userInfo': { - 'UserName': 'user', - 'GivenName': 'User McStudent' - }, - 'slots': {} - }, - } - - context = {} - - canvas_lms_mock.validate_input.return_value = False - canvas_lms_mock.get_secret.return_value = { - "CanvasLMS_APIKey": "test", - "CanvasLMS_DomainName": "test.com" - } - canvas_lms_mock.json.loads.return_value = { - "Query": "CanvasMenu" - } - - event = handler(event, context) - canvas_lms_mock.query_menu.assert_called_once_with({'res': {'result': {'args': [{'query': 'test'}]}}, 'req': {'_settings': {'CanvasLMS_DomainName': 'test.com', 'CanvasLMS_APIKey': 'test'}, '_userInfo': {'UserName': 'user', 'GivenName': 'User McStudent'}, 'slots': {}}}, 'User McStudent') - - def test_CourseEnrollments_called(self, canvas_lms_mock, canvas_mock): - event = { - 'res': { - 'result': { - 'args': [ - { - 'query': 'test' - } - ] - } - }, - 'req': { - '_settings': { - 'CanvasLMS_DomainName': 'test.com', - 'CanvasLMS_APIKey': 'test' - }, - '_userInfo': { - 'UserName': 'user', - 'GivenName': 'User McStudent' - }, - 'slots': {} - }, - } - - context = {} - - canvas_lms_mock.validate_input.return_value = False - canvas_lms_mock.get_secret.return_value = { - "CanvasLMS_APIKey": "test", - "CanvasLMS_DomainName": "test.com" - } - canvas_lms_mock.json.loads.return_value = { - "Query": "CourseEnrollments" - } - - event = handler(event, context) - args = canvas_lms_mock.query_enrollments_for_student.call_args.args - canvas_lms_mock.query_enrollments_for_student.assert_called() - self.assertEqual(args[0], {'res': {'result': {'args': [{'query': 'test'}]}}, 'req': {'_settings': {'CanvasLMS_DomainName': 'test.com', 'CanvasLMS_APIKey': 'test'}, '_userInfo': {'UserName': 'user', 'GivenName': 'User McStudent'}, 'slots': {}}}) - self.assertIsInstance(args[1], Mock) - self.assertEqual(args[2], 'user') - - def test_CourseAssignments_called(self, canvas_lms_mock, canvas_mock): - event = { - 'res': { - 'result': { - 'args': [ - { - 'query': 'test' - } - ] - } - }, - 'req': { - '_settings': { - 'CanvasLMS_DomainName': 'test.com', - 'CanvasLMS_APIKey': 'test' - }, - '_userInfo': { - 'UserName': 'user', - 'GivenName': 'User McStudent' - }, - 'slots': {} - }, - } - - context = {} - - canvas_lms_mock.validate_input.return_value = False - canvas_lms_mock.get_secret.return_value = { - "CanvasLMS_APIKey": "test", - "CanvasLMS_DomainName": "test.com" - } - canvas_lms_mock.json.loads.return_value = { - "Query": "CourseAssignments" - } - - event = handler(event, context) - args = canvas_lms_mock.query_course_assignments_for_student.call_args.args - canvas_lms_mock.query_course_assignments_for_student.assert_called() - self.assertEqual(args[0], {'res': {'result': {'args': [{'query': 'test'}]}}, 'req': {'_settings': {'CanvasLMS_DomainName': 'test.com', 'CanvasLMS_APIKey': 'test'}, '_userInfo': {'UserName': 'user', 'GivenName': 'User McStudent'}, 'slots': {}}}) - self.assertIsInstance(args[1], Mock) - self.assertEqual(args[2], 'user') - self.assertEqual(args[3], '') - - def test_SyllabusForCourse_called(self, canvas_lms_mock, canvas_mock): - event = { - 'res': { - 'result': { - 'args': [ - { - 'query': 'test' - } - ] - } - }, - 'req': { - '_settings': { - 'CanvasLMS_DomainName': 'test.com', - 'CanvasLMS_APIKey': 'test' - }, - '_userInfo': { - 'UserName': 'user', - 'GivenName': 'User McStudent' - }, - 'slots': {} - }, - } - - context = {} - - canvas_lms_mock.validate_input.return_value = False - canvas_lms_mock.get_secret.return_value = { - "CanvasLMS_APIKey": "test", - "CanvasLMS_DomainName": "test.com" - } - canvas_lms_mock.json.loads.return_value = { - "Query": "SyllabusForCourse" - } - - event = handler(event, context) - args = canvas_lms_mock.query_syllabus_for_student.call_args.args - canvas_lms_mock.query_syllabus_for_student.assert_called() - self.assertEqual(args[0], {'res': {'result': {'args': [{'query': 'test'}]}}, 'req': {'_settings': {'CanvasLMS_DomainName': 'test.com', 'CanvasLMS_APIKey': 'test'}, '_userInfo': {'UserName': 'user', 'GivenName': 'User McStudent'}, 'slots': {}}}) - self.assertIsInstance(args[1], Mock) - self.assertEqual(args[2], 'user') - self.assertEqual(args[3], '') - - def test_CoursesForStudent_called(self, canvas_lms_mock, canvas_mock): - event = { - 'res': { - 'result': { - 'args': [ - { - 'query': 'test' - } - ] - } - }, - 'req': { - '_settings': { - 'CanvasLMS_DomainName': 'test.com', - 'CanvasLMS_APIKey': 'test' - }, - '_userInfo': { - 'UserName': 'user', - 'GivenName': 'User McStudent' - }, - 'slots': {} - }, - } - - context = {} - - canvas_lms_mock.validate_input.return_value = False - canvas_lms_mock.get_secret.return_value = { - "CanvasLMS_APIKey": "test", - "CanvasLMS_DomainName": "test.com" - } - canvas_lms_mock.json.loads.return_value = { - "Query": "CoursesForStudent" - } - - event = handler(event, context) - args = canvas_lms_mock.query_courses_for_student.call_args.args - canvas_lms_mock.query_courses_for_student.assert_called() - self.assertEqual(args[0], {'res': {'result': {'args': [{'query': 'test'}]}}, 'req': {'_settings': {'CanvasLMS_DomainName': 'test.com', 'CanvasLMS_APIKey': 'test'}, '_userInfo': {'UserName': 'user', 'GivenName': 'User McStudent'}, 'slots': {}}}) - self.assertIsInstance(args[1], Mock) - self.assertEqual(args[2], 'user') - self.assertEqual(args[3], '') - - def test_AnnouncementsForStudent_called(self, canvas_lms_mock, canvas_mock): - event = { - 'res': { - 'result': { - 'args': [ - { - 'query': 'test' - } - ] - } - }, - 'req': { - '_settings': { - 'CanvasLMS_DomainName': 'test.com', - 'CanvasLMS_APIKey': 'test' - }, - '_userInfo': { - 'UserName': 'user', - 'GivenName': 'User McStudent' - }, - 'slots': {} - }, - } - - context = {} - - canvas_lms_mock.validate_input.return_value = False - canvas_lms_mock.get_secret.return_value = { - "CanvasLMS_APIKey": "test", - "CanvasLMS_DomainName": "test.com" - } - canvas_lms_mock.json.loads.return_value = { - "Query": "AnnouncementsForStudent" - } - - event = handler(event, context) - args = canvas_lms_mock.query_announcements_for_student.call_args.args - canvas_lms_mock.query_announcements_for_student.assert_called() - self.assertEqual(args[0], {'res': {'result': {'args': [{'query': 'test'}]}}, 'req': {'_settings': {'CanvasLMS_DomainName': 'test.com', 'CanvasLMS_APIKey': 'test'}, '_userInfo': {'UserName': 'user', 'GivenName': 'User McStudent'}, 'slots': {}}}) - self.assertIsInstance(args[1], Mock) - self.assertEqual(args[2], 'user') - - def test_GradesForStudent_called(self, canvas_lms_mock, canvas_mock): - event = { - 'res': { - 'result': { - 'args': [ - { - 'query': 'test' - } - ] - } - }, - 'req': { - '_settings': { - 'CanvasLMS_DomainName': 'test.com', - 'CanvasLMS_APIKey': 'test' - }, - '_userInfo': { - 'UserName': 'user', - 'GivenName': 'User McStudent' - }, - 'slots': {} - }, - } - - context = {} - - canvas_lms_mock.validate_input.return_value = False - canvas_lms_mock.get_secret.return_value = { - "CanvasLMS_APIKey": "test", - "CanvasLMS_DomainName": "test.com" - } - canvas_lms_mock.json.loads.return_value = { - "Query": "GradesForStudent" - } - - event = handler(event, context) - args = canvas_lms_mock.query_grades_for_student.call_args.args - canvas_lms_mock.query_grades_for_student.assert_called() - self.assertEqual(args[0], {'res': {'result': {'args': [{'query': 'test'}]}}, 'req': {'_settings': {'CanvasLMS_DomainName': 'test.com', 'CanvasLMS_APIKey': 'test'}, '_userInfo': {'UserName': 'user', 'GivenName': 'User McStudent'}, 'slots': {}}}) - self.assertIsInstance(args[1], Mock) - self.assertEqual(args[2], 'user') - self.assertEqual(args[3], '') diff --git a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/pytest.ini b/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/pytest.ini deleted file mode 100644 index b4f64c8ef..000000000 --- a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/pytest.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pytest] -testpaths = **/__tests__ \ No newline at end of file diff --git a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/requirements-dev.txt b/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/requirements-dev.txt deleted file mode 100644 index ed98b7883..000000000 --- a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/requirements-dev.txt +++ /dev/null @@ -1,4 +0,0 @@ -moto~=4.2.4 -pytest~=7.4.2 -pytest-cov~=4.1.0 -mock~=5.1.0 \ No newline at end of file diff --git a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/requirements.txt b/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/requirements.txt deleted file mode 100644 index d8ac06c91..000000000 --- a/source/templates/examples/extensions/py_lambda_hooks/CanvasLMSHook/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -canvasapi==3.2.0 -idna==3.7 -requests==2.32.3 -beautifulsoup4==4.12.0 diff --git a/source/templates/examples/extensions/py_lambda_hooks/CustomPYHook/requirements-dev.txt b/source/templates/examples/extensions/py_lambda_hooks/CustomPYHook/requirements-dev.txt index ed98b7883..4f50a96aa 100644 --- a/source/templates/examples/extensions/py_lambda_hooks/CustomPYHook/requirements-dev.txt +++ b/source/templates/examples/extensions/py_lambda_hooks/CustomPYHook/requirements-dev.txt @@ -1,4 +1,4 @@ -moto~=4.2.4 -pytest~=7.4.2 -pytest-cov~=4.1.0 +moto~=5.0.13 +pytest~=8.3.2 +pytest-cov~=5.0.0 mock~=5.1.0 \ No newline at end of file diff --git a/source/templates/examples/extensions/ui_imports/content/CanvasLMSIntegration.json b/source/templates/examples/extensions/ui_imports/content/CanvasLMSIntegration.json deleted file mode 100644 index 450878219..000000000 --- a/source/templates/examples/extensions/ui_imports/content/CanvasLMSIntegration.json +++ /dev/null @@ -1,357 +0,0 @@ -{ - "qna": [{ - "qid": "CanvasLMS.assignments", - "a": "Here is a list of assignments:", - "enableQidIntent": true, - "slots": [{ - "slotName": "CanvasLMS_course_name_slot", - "slotType": "CanvasLMS_course_names_slottype", - "slotPrompt": "For which course would you like to view assignments for?" - }], - "l": "QNA:EXTCanvasLMSHook", - "args": [ - "{\"Query\": \"CourseAssignments\"}" - ], - "type": "qna", - "q": [ - "tell me about my assignments", - "what assignments do i have due", - "what assignments do i have", - "what are my assignments", - "do i have any assignments", - "do i have any assignments due", - "tell me about my {CanvasLMS_course_name_slot} assignments" - ] - }, - { - "qid": "CanvasLMS.syllabus", - "a": "Here is your syllabus:", - "enableQidIntent": true, - "slots": [{ - "slotName": "CanvasLMS_course_name_slot", - "slotType": "CanvasLMS_course_names_slottype", - "slotPrompt": "For which course would you like to view syllabus for?" - }], - "l": "QNA:EXTCanvasLMSHook", - "args": [ - "{\"Query\": \"SyllabusForCourse\"}" - ], - "type": "qna", - "q": [ - "tell me about my syllabus", - "whats my syllabus", - "what is my syllabus", - "tell me about my {CanvasLMS_course_name_slot} syllabus" - ] - }, - { - "qid": "CanvasLMS.menu", - "a": "Please select one of the options:", - "l": "QNA:EXTCanvasLMSHook", - "args": [ - "{\"Query\": \"CanvasMenu\"}" - ], - "type": "qna", - "q": [ - "canvas menu", - "canvas" - ] - }, - { - "qid": "CanvasLMS.enrollments", - "a": "Here are the courses you are enrolled in:", - "enableQidIntent": true, - "l": "QNA:EXTCanvasLMSHook", - "args": [ - "{\"Query\": \"CourseEnrollments\"}" - ], - "type": "qna", - "q": [ - "tell me about my enrollments", - "what courses have i enrolled in", - "course enrollments", - "what are my courses" - ] - }, - { - "qid": "CanvasLMS.announcements", - "a": "Here are your announcements:", - "enableQidIntent": true, - "l": "QNA:EXTCanvasLMSHook", - "args": [ - "{\"Query\": \"AnnouncementsForStudent\"}" - ], - "type": "qna", - "q": [ - "tell me about my announcements", - "do i have any announcements" - ] - }, - { - "qid": "CanvasLMS_course_names_slottype", - "descr": "List of sample course names", - "resolutionStrategyRestrict": true, - "slotTypeValues": [{ - "samplevalue": "accounting" - }, - { - "samplevalue": "american literature" - }, - { - "samplevalue": "american literature history" - }, - { - "samplevalue": "american sign language" - }, - { - "samplevalue": "animal nutrition" - }, - { - "samplevalue": "anthropology " - }, - { - "samplevalue": "business and marketing" - }, - { - "samplevalue": "business communications" - }, - { - "samplevalue": "business ethics" - }, - { - "samplevalue": "business law" - }, - { - "samplevalue": "business management" - }, - { - "samplevalue": "advertising design", - "synonyms": "advertising" - }, - { - "samplevalue": "aerospace engineering", - "synonyms": "aerospace" - }, - { - "samplevalue": "agriculture" - }, - { - "samplevalue": "algebra" - }, - { - "samplevalue": "architectural design" - }, - { - "samplevalue": "art" - }, - { - "samplevalue": "art history" - }, - { - "samplevalue": "astronomy" - }, - { - "samplevalue": "banking and finance", - "synonyms": "banking, finance" - }, - { - "samplevalue": "biology" - }, - { - "samplevalue": "botany" - }, - { - "samplevalue": "chemistry" - }, - { - "samplevalue": "civics" - }, - { - "samplevalue": "civil engineering" - }, - { - "samplevalue": "communications" - }, - { - "samplevalue": "computer and information technology" - }, - { - "samplevalue": "computer science" - }, - { - "samplevalue": "cost accounting" - }, - { - "samplevalue": "creative writing" - }, - { - "samplevalue": "criminal justice" - }, - { - "samplevalue": "cyber security", - "synonyms": "cybersecurity" - }, - { - "samplevalue": "earth and space science", - "synonyms": "earth, space science" - }, - { - "samplevalue": "education" - }, - { - "samplevalue": "electronics" - }, - { - "samplevalue": "environmental science" - }, - { - "samplevalue": "fashion design" - }, - { - "samplevalue": "health science" - }, - { - "samplevalue": "humanities" - }, - { - "samplevalue": "income tax accounting" - }, - { - "samplevalue": "industrial arts" - }, - { - "samplevalue": "industrial design" - }, - { - "samplevalue": "information technology" - }, - { - "samplevalue": "interactive design" - }, - { - "samplevalue": "journalism" - }, - { - "samplevalue": "macro economics", - "synonyms": "macroeconomics" - }, - { - "samplevalue": "micro economics", - "synonyms": "microeconomics" - }, - { - "samplevalue": "micro biology", - "synonyms": "microbiology" - }, - { - "samplevalue": "music" - }, - { - "samplevalue": "nursing" - }, - { - "samplevalue": "nutrition science" - }, - { - "samplevalue": "philosophy" - }, - { - "samplevalue": "photography" - }, - { - "samplevalue": "physics" - }, - { - "samplevalue": "physiology" - }, - { - "samplevalue": "political science" - }, - { - "samplevalue": "public policy" - }, - { - "samplevalue": "public safety" - }, - { - "samplevalue": "robotics" - }, - { - "samplevalue": "science" - }, - { - "samplevalue": "social media" - }, - { - "samplevalue": "social science" - }, - { - "samplevalue": "social studies" - }, - { - "samplevalue": "statistics" - }, - { - "samplevalue": "travel and tourism", - "synonyms": "travel, tourism" - }, - { - "samplevalue": "visual arts" - }, - { - "samplevalue": "world history" - }, - { - "samplevalue": "zoology" - } - - ], - "type": "slottype", - "_id": "CanvasLMS_course_names_slottype" - }, - { - "qid": "CanvasLMS.course", - "a": "Please select one of the options:", - "enableQidIntent": true, - "slots": [{ - "slotRequired": true, - "slotName": "CanvasLMS_course_name_slot", - "slotType": "CanvasLMS_course_names_slottype", - "slotPrompt": "For which course would you like more information on?" - }], - "l": "QNA:EXTCanvasLMSHook", - "args": [ - "{\"Query\": \"CoursesForStudent\"}" - ], - "type": "qna", - "q": [ - "more info about my course", - "more information about my course", - "more information on {CanvasLMS_course_name_slot} course", - "more info on {CanvasLMS_course_name_slot}", - "more information about my {CanvasLMS_course_name_slot} course" - ] - }, - { - "qid": "CanvasLMS.grades", - "a": "Here are your grades:", - "enableQidIntent": true, - "slots": [{ - "slotName": "CanvasLMS_course_name_slot", - "slotType": "CanvasLMS_course_names_slottype", - "slotPrompt": "For which course would you like to view grades for?" - }], - "l": "QNA:EXTCanvasLMSHook", - "args": [ - "{\"Query\": \"GradesForStudent\"}" - ], - "type": "qna", - "q": [ - "tell me about my grades", - "what are my grades", - "how did i do in {CanvasLMS_course_name_slot}", - "tell me about my {CanvasLMS_course_name_slot} grades" - ] - } - ] -} \ No newline at end of file diff --git a/source/templates/examples/extensions/ui_imports/content/CanvasLMSIntegration.txt b/source/templates/examples/extensions/ui_imports/content/CanvasLMSIntegration.txt deleted file mode 100644 index 1ff8cef73..000000000 --- a/source/templates/examples/extensions/ui_imports/content/CanvasLMSIntegration.txt +++ /dev/null @@ -1,4 +0,0 @@ -NOTICE: Canvas LMS integration with QnABot on AWS is deprecated in this release and no longer be supported. Customers may fork the code needed for their specific use case from previous versions. The integration code will be removed in the next release. - - -Imports sample questions for interacting with Canvas LMS. More details: https://github.com/aws-solutions/qnabot-on-aws/blob/main/docs/canvaslms_integration.md \ No newline at end of file diff --git a/source/templates/examples/extensions/ui_imports/package-lock.json b/source/templates/examples/extensions/ui_imports/package-lock.json index a5c815c96..4d6d30c7b 100644 --- a/source/templates/examples/extensions/ui_imports/package-lock.json +++ b/source/templates/examples/extensions/ui_imports/package-lock.json @@ -1,16 +1,16 @@ { "name": "ui_import", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ui_import", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "cfn-response": "^1.0.1", - "handlebars": "^4.7.7", + "handlebars": "^4.7.8", "lodash": "^4.17.21" } }, @@ -19,19 +19,14 @@ "resolved": "https://registry.npmjs.org/cfn-response/-/cfn-response-1.0.1.tgz", "integrity": "sha1-qOwDlQwGg8UUlejKaA2dwLiEsTc=" }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "optional": true - }, "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", "dependencies": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, @@ -56,9 +51,10 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "node_modules/neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" }, "node_modules/source-map": { "version": "0.6.1", @@ -69,13 +65,11 @@ } }, "node_modules/uglify-js": { - "version": "3.9.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.4.tgz", - "integrity": "sha512-8RZBJq5smLOa7KslsNsVcSH+KOXf1uDU8yqLeNuVKwmT0T3FA0ZoXlinQfRad7SDcbZZRZE4ov+2v71EnxNyCA==", + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", + "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", + "license": "BSD-2-Clause", "optional": true, - "dependencies": { - "commander": "~2.20.3" - }, "bin": { "uglifyjs": "bin/uglifyjs" }, @@ -95,21 +89,15 @@ "resolved": "https://registry.npmjs.org/cfn-response/-/cfn-response-1.0.1.tgz", "integrity": "sha1-qOwDlQwGg8UUlejKaA2dwLiEsTc=" }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "optional": true - }, "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "requires": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", - "uglify-js": "^3.1.4", + "uglify-js": "^3.19.2", "wordwrap": "^1.0.0" } }, @@ -124,9 +112,9 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "source-map": { "version": "0.6.1", @@ -134,13 +122,10 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "uglify-js": { - "version": "3.9.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.4.tgz", - "integrity": "sha512-8RZBJq5smLOa7KslsNsVcSH+KOXf1uDU8yqLeNuVKwmT0T3FA0ZoXlinQfRad7SDcbZZRZE4ov+2v71EnxNyCA==", - "optional": true, - "requires": { - "commander": "~2.20.3" - } + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", + "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", + "optional": true }, "wordwrap": { "version": "1.0.0", diff --git a/source/templates/examples/extensions/ui_imports/package.json b/source/templates/examples/extensions/ui_imports/package.json index 6c28fb482..d92cbb362 100644 --- a/source/templates/examples/extensions/ui_imports/package.json +++ b/source/templates/examples/extensions/ui_imports/package.json @@ -1,6 +1,6 @@ { "name": "ui_import", - "version": "6.0.3", + "version": "6.1.0", "description": "Add new content packages for Content Designer Import Examples/Extensions listing", "main": "ui_import.js", "scripts": { @@ -13,7 +13,10 @@ "license": "Apache-2.0", "dependencies": { "cfn-response": "^1.0.1", - "handlebars": "^4.7.7", + "handlebars": "^4.7.8", "lodash": "^4.17.21" + }, + "overrides": { + "uglify-js": "^3.19.2" } } diff --git a/source/templates/examples/index.js b/source/templates/examples/index.js index 041aed946..52d9edb70 100644 --- a/source/templates/examples/index.js +++ b/source/templates/examples/index.js @@ -45,12 +45,12 @@ module.exports = { QIDLambdaArn: { Type: 'String' }, VPCSubnetIdList: { Type: 'String' }, VPCSecurityGroupIdList: { Type: 'String' }, - LexBotVersion: { Type: 'String' }, XraySetting: { Type: 'String' }, DefaultQnABotSettings: { Type: 'String' }, PrivateQnABotSettings: { Type: 'String' }, InstallLexResponseBots: { Type: 'String' }, AwsSdkLayerLambdaLayer: { Type: 'String' }, + LogRetentionPeriod: { Type: 'Number' }, }, Conditions: { VPCEnabled: { @@ -59,8 +59,7 @@ module.exports = { ], }, XRAYEnabled: { 'Fn::Equals': [{ Ref: 'XraySetting' }, 'TRUE'] }, - CreateLexV1Bots: { 'Fn::Equals': [{ Ref: 'LexBotVersion' }, 'LexV1 and LexV2'] }, CreateLexResponseBots: { 'Fn::Equals': [{ Ref: 'InstallLexResponseBots' }, 'true'] }, - CreateLexV1ResponseBots: { 'Fn::And': [{ Condition: 'CreateLexResponseBots' }, { Condition: 'CreateLexV1Bots' }] }, + LogRetentionPeriodIsNotZero: { 'Fn::Not': [{ 'Fn::Equals': [{ Ref: 'LogRetentionPeriod' }, 0] }] }, }, }; diff --git a/source/templates/examples/index.test.js b/source/templates/examples/index.test.js index b7e597d4f..4bfbe2c66 100644 --- a/source/templates/examples/index.test.js +++ b/source/templates/examples/index.test.js @@ -15,18 +15,11 @@ function create() { const file = `${__dirname}/`; return require(file); } -// NOTICE: Canvas LMS integration with QnABot on AWS is deprecated in this release and no longer be supported. Customers may fork the code needed for their specific use case from previous versions. The integration code will be removed in the next release. - it('renders examples template correctly', () => { const template = create(); expect(template).toMatchSnapshot({ Resources: { - CodeVersionCanvasLMSHook: { - Properties: { - BuildDate: expect.any(String), - }, - }, CodeVersionCreateRecentTopicsResponse: { Properties: { BuildDate: expect.any(String), diff --git a/source/templates/export/__snapshots__/index.test.js.snap b/source/templates/export/__snapshots__/index.test.js.snap index 5c69a4809..0a46c5ef8 100644 --- a/source/templates/export/__snapshots__/index.test.js.snap +++ b/source/templates/export/__snapshots__/index.test.js.snap @@ -28,6 +28,18 @@ exports[`renders export template correctly 1`] = ` }, ], }, + "LogRetentionPeriodIsNotZero": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "LogRetentionPeriod", + }, + 0, + ], + }, + ], + }, "VPCEnabled": { "Fn::Not": [ { @@ -70,15 +82,15 @@ exports[`renders export template correctly 1`] = ` "BootstrapPrefix": { "Type": "String", }, - "BotName": { - "Type": "String", - }, "CFNInvokePolicy": { "Type": "String", }, "CFNLambda": { "Type": "String", }, + "ContentDesignerOutputBucket": { + "Type": "String", + }, "CustomQnABotSettings": { "Type": "String", }, @@ -94,12 +106,6 @@ exports[`renders export template correctly 1`] = ` "ExportBucket": { "Type": "String", }, - "FallbackIntent": { - "Type": "String", - }, - "Intent": { - "Type": "String", - }, "KendraCrawlerSnsTopic": { "Type": "String", }, @@ -127,6 +133,9 @@ exports[`renders export template correctly 1`] = ` "LexVersion": { "Type": "String", }, + "LogRetentionPeriod": { + "Type": "Number", + }, "PrivateQnABotSettings": { "Type": "String", }, @@ -314,15 +323,6 @@ exports[`renders export template correctly 1`] = ` "accountId": { "Ref": "AWS::AccountId", }, - "fallBackIntent": { - "Ref": "FallbackIntent", - }, - "intent": { - "Ref": "Intent", - }, - "lexBot": { - "Ref": "BotName", - }, "outputBucket": { "Ref": "ExportBucket", }, @@ -338,6 +338,11 @@ exports[`renders export template correctly 1`] = ` "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ConnectLambdaLogGroup", + }, + }, "MemorySize": "1024", "Role": { "Fn::GetAtt": [ @@ -393,6 +398,53 @@ exports[`renders export template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "ConnectLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ConnectLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "Deployment": { "DeletionPolicy": "Retain", "DependsOn": [ @@ -473,6 +525,9 @@ exports[`renders export template correctly 1`] = ` { "Fn::Sub": "arn:aws:s3:::\${ExportBucket}*", }, + { + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}*", + }, ], }, { @@ -680,6 +735,9 @@ exports[`renders export template correctly 1`] = ` "ES_PROXY": { "Ref": "EsProxyLambda", }, + "OUTPUT_S3_BUCKET": { + "Ref": "ContentDesignerOutputBucket", + }, "SOLUTION_ID": "SO0189", "SOLUTION_VERSION": "vx.x.x", }, @@ -690,6 +748,11 @@ exports[`renders export template correctly 1`] = ` "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ExportStepLambdaLogGroup", + }, + }, "MemorySize": "1024", "Role": { "Fn::GetAtt": [ @@ -745,6 +808,53 @@ exports[`renders export template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "ExportStepLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ExportStepLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "ExportStepPermission": { "Properties": { "Action": "lambda:InvokeFunction", @@ -780,7 +890,7 @@ exports[`renders export template correctly 1`] = ` "FilterRules": [ { "Name": "prefix", - "Value": "status", + "Value": "status-export", }, ], }, @@ -792,27 +902,6 @@ exports[`renders export template correctly 1`] = ` ], }, }, - { - "Events": [ - "s3:ObjectCreated:*", - ], - "Filter": { - "Key": { - "FilterRules": [ - { - "Name": "prefix", - "Value": "kendra-data", - }, - ], - }, - }, - "LambdaFunctionArn": { - "Fn::GetAtt": [ - "KendraSyncLambda", - "Arn", - ], - }, - }, ], }, "ServiceToken": { @@ -946,15 +1035,6 @@ exports[`renders export template correctly 1`] = ` "accountId": { "Ref": "AWS::AccountId", }, - "fallBackIntent": { - "Ref": "FallbackIntent", - }, - "intent": { - "Ref": "Intent", - }, - "lexBot": { - "Ref": "BotName", - }, "outputBucket": { "Ref": "ExportBucket", }, @@ -970,6 +1050,11 @@ exports[`renders export template correctly 1`] = ` "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "GenesysLambdaLogGroup", + }, + }, "MemorySize": "1024", "Role": { "Fn::GetAtt": [ @@ -1025,6 +1110,53 @@ exports[`renders export template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "GenesysLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-GenesysLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "InvokePermissionConnectLambda": { "Properties": { "Action": "lambda:InvokeFunction", @@ -1267,6 +1399,11 @@ exports[`renders export template correctly 1`] = ` }, }, "Handler": "kendra_webcrawler.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "KendraNativeCrawlerLambdaLogGroup", + }, + }, "MemorySize": "2048", "Role": { "Fn::GetAtt": [ @@ -1322,6 +1459,53 @@ exports[`renders export template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "KendraNativeCrawlerLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-KendraNativeCrawlerLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "KendraNativeCrawlerLambdaStatusInvokePermission": { "Properties": { "Action": "lambda:InvokeFunction", @@ -1812,6 +1996,11 @@ exports[`renders export template correctly 1`] = ` }, }, "Handler": "kendra_webcrawler_schedule_updater.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "KendraNativeCrawlerScheduleUpdateLambdaLogGroup", + }, + }, "MemorySize": "2048", "Role": { "Fn::GetAtt": [ @@ -1867,6 +2056,53 @@ exports[`renders export template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "KendraNativeCrawlerScheduleUpdateLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-KendraNativeCrawlerScheduleUpdateLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "KendraNativeCrawlerStatusCodeVersion": { "Properties": { "Bucket": { @@ -1971,6 +2207,11 @@ exports[`renders export template correctly 1`] = ` }, }, "Handler": "kendra_webcrawler_status.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "KendraNativeCrawlerStatusLambdaLogGroup", + }, + }, "MemorySize": "2048", "Role": { "Fn::GetAtt": [ @@ -2026,6 +2267,53 @@ exports[`renders export template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "KendraNativeCrawlerStatusLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-KendraNativeCrawlerStatusLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "KendraS3Policy": { "Condition": "CreateKendraSyncPolicy", "Properties": { @@ -2038,10 +2326,10 @@ exports[`renders export template correctly 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::Sub": "arn:aws:s3:::\${ExportBucket}", + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}", }, { - "Fn::Sub": "arn:aws:s3:::\${ExportBucket}/*", + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}/*", }, ], }, @@ -2269,7 +2557,7 @@ exports[`renders export template correctly 1`] = ` ], }, "OUTPUT_S3_BUCKET": { - "Ref": "ExportBucket", + "Ref": "ContentDesignerOutputBucket", }, "PRIVATE_SETTINGS_PARAM": { "Ref": "PrivateQnABotSettings", @@ -2290,6 +2578,11 @@ exports[`renders export template correctly 1`] = ` "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "KendraSyncLambdaLogGroup", + }, + }, "MemorySize": "1024", "Role": { "Fn::GetAtt": [ @@ -2345,6 +2638,53 @@ exports[`renders export template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "KendraSyncLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-KendraSyncLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "KendraSyncPermission": { "Properties": { "Action": "lambda:InvokeFunction", @@ -2359,7 +2699,7 @@ exports[`renders export template correctly 1`] = ` "Ref": "AWS::AccountId", }, "SourceArn": { - "Fn::Sub": "arn:aws:s3:::\${ExportBucket}", + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}", }, }, "Type": "AWS::Lambda::Permission", @@ -2378,10 +2718,10 @@ exports[`renders export template correctly 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::Sub": "arn:aws:s3:::\${ExportBucket}", + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}", }, { - "Fn::Sub": "arn:aws:s3:::\${ExportBucket}/*", + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}/*", }, ], }, @@ -2598,6 +2938,42 @@ exports[`renders export template correctly 1`] = ` }, "Type": "AWS::IAM::Role", }, + "KendraSyncS3Trigger": { + "Properties": { + "Bucket": { + "Ref": "ContentDesignerOutputBucket", + }, + "NotificationConfiguration": { + "LambdaFunctionConfigurations": [ + { + "Events": [ + "s3:ObjectCreated:*", + ], + "Filter": { + "Key": { + "FilterRules": [ + { + "Name": "prefix", + "Value": "kendra-data-export", + }, + ], + }, + }, + "LambdaFunctionArn": { + "Fn::GetAtt": [ + "KendraSyncLambda", + "Arn", + ], + }, + }, + ], + }, + "ServiceToken": { + "Ref": "CFNLambda", + }, + }, + "Type": "Custom::S3Lambda", + }, "KendraTopicApiGateRole": { "Metadata": { "cfn_nag": { @@ -2787,6 +3163,11 @@ exports[`renders export template correctly 1`] = ` "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "TranslateLambdaLogGroup", + }, + }, "MemorySize": "1024", "Role": { "Fn::GetAtt": [ @@ -2842,6 +3223,53 @@ exports[`renders export template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "TranslateLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-TranslateLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "TranslatePolicy": { "Metadata": { "cfn_nag": { diff --git a/source/templates/export/bucket.js b/source/templates/export/bucket.js index 307e0a7cd..48a7fbcc4 100644 --- a/source/templates/export/bucket.js +++ b/source/templates/export/bucket.js @@ -25,22 +25,11 @@ module.exports = { Key: { FilterRules: [{ Name: 'prefix', - Value: 'status', + Value: 'status-export', }], }, }, - }, { - LambdaFunctionArn: { 'Fn::GetAtt': ['KendraSyncLambda', 'Arn'] }, - Events: ['s3:ObjectCreated:*'], - Filter: { - Key: { - FilterRules: [{ - Name: 'prefix', - Value: 'kendra-data', - }], - }, - }, - }, + } ], }, }, @@ -55,6 +44,28 @@ module.exports = { SourceArn: { 'Fn::Sub': 'arn:aws:s3:::${ExportBucket}' }, }, }, + KendraSyncS3Trigger: { + Type: 'Custom::S3Lambda', + Properties: { + ServiceToken: { Ref: 'CFNLambda' }, + Bucket: { Ref: 'ContentDesignerOutputBucket' }, + NotificationConfiguration: { + LambdaFunctionConfigurations: [{ + LambdaFunctionArn: { 'Fn::GetAtt': ['KendraSyncLambda', 'Arn'] }, + Events: ['s3:ObjectCreated:*'], + Filter: { + Key: { + FilterRules: [{ + Name: 'prefix', + Value: 'kendra-data-export', + }], + }, + }, + }, + ], + }, + }, + }, KendraSyncPermission: { Type: 'AWS::Lambda::Permission', Properties: { @@ -62,7 +73,7 @@ module.exports = { Action: 'lambda:InvokeFunction', Principal: 's3.amazonaws.com', SourceAccount: { Ref: 'AWS::AccountId' }, - SourceArn: { 'Fn::Sub': 'arn:aws:s3:::${ExportBucket}' }, + SourceArn: { 'Fn::Sub': 'arn:aws:s3:::${ContentDesignerOutputBucket}' }, }, }, diff --git a/source/templates/export/index.js b/source/templates/export/index.js index 6e5999f15..113d193e8 100644 --- a/source/templates/export/index.js +++ b/source/templates/export/index.js @@ -25,6 +25,7 @@ module.exports = { Description: `(SO0189n-export) QnABot nested export resources - Version v${process.env.npm_package_version}`, Outputs: require('./outputs'), Parameters: { + ContentDesignerOutputBucket: { Type: 'String' }, CFNLambda: { Type: 'String' }, CFNInvokePolicy: { Type: 'String' }, S3Clean: { Type: 'String' }, @@ -35,10 +36,6 @@ module.exports = { EsProxyLambda: { Type: 'String' }, ExportBucket: { Type: 'String' }, LexVersion: { Type: 'String' }, - // Lex V1 - FallbackIntent: { Type: 'String' }, - Intent: { Type: 'String' }, - BotName: { Type: 'String' }, // Lex V2 LexV2BotName: { Type: 'String' }, LexV2BotId: { Type: 'String' }, @@ -60,6 +57,7 @@ module.exports = { QnABotCommonLambdaLayer: { Type: 'String' }, KendraFaqIndexId: { Type: 'String' }, KendraWebPageIndexId: { Type: 'String' }, + LogRetentionPeriod: { Type: 'Number' }, }, Conditions: { VPCEnabled: { @@ -70,5 +68,6 @@ module.exports = { XRAYEnabled: { 'Fn::Equals': [{ Ref: 'XraySetting' }, 'TRUE'] }, CreateKendraSyncPolicy: { 'Fn::Not': [{ 'Fn::Equals': [{ Ref: 'KendraFaqIndexId' }, ''] }] }, CreateKendraCrawlerPolicy: { 'Fn::Not': [{ 'Fn::Equals': [{ Ref: 'KendraWebPageIndexId' }, ''] }] }, + LogRetentionPeriodIsNotZero: { 'Fn::Not': [{ 'Fn::Equals': [{ Ref: 'LogRetentionPeriod' }, 0] }] } }, }; diff --git a/source/templates/export/resources.js b/source/templates/export/resources.js index d2c1b99a9..4c3d10f5c 100644 --- a/source/templates/export/resources.js +++ b/source/templates/export/resources.js @@ -35,6 +35,30 @@ module.exports = { BuildDate: new Date().toISOString(), }, }, + ConnectLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ConnectLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ConnectLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -50,10 +74,6 @@ module.exports = { accountId: { Ref: 'AWS::AccountId' }, region: { Ref: 'AWS::Region' }, LexVersion: { Ref: 'LexVersion' }, - // Lex V1 - fallBackIntent: { Ref: 'FallbackIntent' }, - intent: { Ref: 'Intent' }, - lexBot: { Ref: 'BotName' }, // Lex V2 LexV2BotName: { Ref: 'LexV2BotName' }, LexV2BotId: { Ref: 'LexV2BotId' }, @@ -63,6 +83,9 @@ module.exports = { }, }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: "ConnectLambdaLogGroup" }, + }, MemorySize: '1024', Role: { 'Fn::GetAtt': ['ExportRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -119,6 +142,30 @@ module.exports = { BuildDate: new Date().toISOString(), }, }, + GenesysLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-GenesysLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, GenesysLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -134,10 +181,6 @@ module.exports = { accountId: { Ref: 'AWS::AccountId' }, region: { Ref: 'AWS::Region' }, LexVersion: { Ref: 'LexVersion' }, - // Lex V1 - fallBackIntent: { Ref: 'FallbackIntent' }, - intent: { Ref: 'Intent' }, - lexBot: { Ref: 'BotName' }, // Lex V2 LexV2BotName: { Ref: 'LexV2BotName' }, LexV2BotId: { Ref: 'LexV2BotId' }, @@ -147,6 +190,9 @@ module.exports = { }, }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'GenesysLambdaLogGroup' }, + }, MemorySize: '1024', Role: { 'Fn::GetAtt': ['ExportRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -191,7 +237,7 @@ module.exports = { Action: 'lambda:InvokeFunction', FunctionName: { 'Fn::GetAtt': ['GenesysLambda', 'Arn'] }, Principal: 'apigateway.amazonaws.com', - SourceAccount: { Ref: 'AWS::AccountId' }, + SourceAccount: { Ref: 'AWS::AccountId' }, }, }, Deployment: { @@ -299,6 +345,30 @@ module.exports = { BuildDate: new Date().toISOString(), }, }, + ExportStepLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ExportStepLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ExportStepLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -312,10 +382,14 @@ module.exports = { ES_INDEX: { Ref: 'VarIndex' }, ES_ENDPOINT: { Ref: 'EsEndpoint' }, ES_PROXY: { Ref: 'EsProxyLambda' }, - ...util.getCommonEnvironmentVariables() + OUTPUT_S3_BUCKET: { Ref: 'ContentDesignerOutputBucket' }, + ...util.getCommonEnvironmentVariables(), }, }, Handler: 'index.step', + LoggingConfig: { + LogGroup: { Ref: 'ExportStepLambdaLogGroup' }, + }, MemorySize: '1024', Role: { 'Fn::GetAtt': ['ExportRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -389,7 +463,8 @@ module.exports = { 's3:DeleteObject', 's3:GetObjectVersion', ], - Resource: [{ 'Fn::Sub': 'arn:aws:s3:::${ExportBucket}*' }], + Resource: [{ 'Fn::Sub': 'arn:aws:s3:::${ExportBucket}*' }, + { 'Fn::Sub': 'arn:aws:s3:::${ContentDesignerOutputBucket}*' }], }, { Effect: 'Allow', @@ -408,6 +483,30 @@ module.exports = { Bucket: { Ref: 'ExportBucket' }, }, }, + KendraSyncLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-KendraSyncLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, KendraSyncLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -421,7 +520,7 @@ module.exports = { DEFAULT_SETTINGS_PARAM: { Ref: 'DefaultQnABotSettings' }, PRIVATE_SETTINGS_PARAM: { Ref: 'PrivateQnABotSettings' }, CUSTOM_SETTINGS_PARAM: { Ref: 'CustomQnABotSettings' }, - OUTPUT_S3_BUCKET: { Ref: 'ExportBucket' }, + OUTPUT_S3_BUCKET: { Ref: 'ContentDesignerOutputBucket' }, KENDRA_ROLE: { 'Fn::GetAtt': ['KendraS3Role', 'Arn'] }, REGION: { Ref: 'AWS::Region' }, ...util.getCommonEnvironmentVariables(), @@ -429,6 +528,9 @@ module.exports = { }, Layers: [{ Ref: 'AwsSdkLayerLambdaLayer' }, { Ref: 'QnABotCommonLambdaLayer' }], Handler: 'kendraSync.performSync', + LoggingConfig: { + LogGroup: { Ref: 'KendraSyncLambdaLogGroup' }, + }, MemorySize: '1024', Role: { 'Fn::GetAtt': ['KendraSyncRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -508,8 +610,8 @@ module.exports = { 's3:List*', ], Resource: [ - { 'Fn::Sub': 'arn:aws:s3:::${ExportBucket}' }, - { 'Fn::Sub': 'arn:aws:s3:::${ExportBucket}/*' }, + { 'Fn::Sub': 'arn:aws:s3:::${ContentDesignerOutputBucket}' }, + { 'Fn::Sub': 'arn:aws:s3:::${ContentDesignerOutputBucket}/*' }, ], }, { @@ -655,6 +757,30 @@ module.exports = { BuildDate: new Date().toISOString(), }, }, + TranslateLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-TranslateLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, TranslateLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -670,6 +796,9 @@ module.exports = { }, }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'TranslateLambdaLogGroup' }, + }, MemorySize: '1024', Role: { 'Fn::GetAtt': ['TranslateRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -874,8 +1003,8 @@ module.exports = { Effect: 'Allow', Action: ['s3:GetObject'], Resource: [ - { 'Fn::Sub': 'arn:aws:s3:::${ExportBucket}' }, - { 'Fn::Sub': 'arn:aws:s3:::${ExportBucket}/*' }, + { 'Fn::Sub': 'arn:aws:s3:::${ContentDesignerOutputBucket}' }, + { 'Fn::Sub': 'arn:aws:s3:::${ContentDesignerOutputBucket}/*' }, ], }, { @@ -1021,6 +1150,30 @@ module.exports = { SourceAccount: { Ref: 'AWS::AccountId' }, }, }, + KendraNativeCrawlerLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-KendraNativeCrawlerLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, KendraNativeCrawlerLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -1076,6 +1229,9 @@ module.exports = { }, }, Handler: 'kendra_webcrawler.handler', + LoggingConfig: { + LogGroup: { Ref: 'KendraNativeCrawlerLambdaLogGroup' }, + }, MemorySize: '2048', Role: { 'Fn::GetAtt': ['KendraNativeCrawlerRole', 'Arn'] }, Runtime: process.env.npm_package_config_pythonRuntime, @@ -1110,6 +1266,30 @@ module.exports = { BuildDate: new Date().toISOString(), }, }, + KendraNativeCrawlerScheduleUpdateLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-KendraNativeCrawlerScheduleUpdateLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, KendraNativeCrawlerScheduleUpdateLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -1153,6 +1333,9 @@ module.exports = { }, }, Handler: 'kendra_webcrawler_schedule_updater.handler', + LoggingConfig: { + LogGroup: { Ref: 'KendraNativeCrawlerScheduleUpdateLambdaLogGroup' }, + }, MemorySize: '2048', Role: { 'Fn::GetAtt': ['KendraNativeCrawlerRole', 'Arn'] }, Runtime: process.env.npm_package_config_pythonRuntime, @@ -1169,6 +1352,30 @@ module.exports = { guard: util.cfnGuard('LAMBDA_CONCURRENCY_CHECK', 'LAMBDA_INSIDE_VPC'), }, }, + KendraNativeCrawlerStatusLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-KendraNativeCrawlerStatusLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, KendraNativeCrawlerStatusLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -1223,6 +1430,9 @@ module.exports = { }, }, Handler: 'kendra_webcrawler_status.handler', + LoggingConfig: { + LogGroup: { Ref: 'KendraNativeCrawlerStatusLambdaLogGroup' }, + }, MemorySize: '2048', Role: { 'Fn::GetAtt': ['KendraNativeCrawlerRole', 'Arn'] }, Runtime: process.env.npm_package_config_pythonRuntime, diff --git a/source/templates/import/UpgradeAutoImport.js b/source/templates/import/UpgradeAutoImport.js index a80ed1162..c3357fbbb 100644 --- a/source/templates/import/UpgradeAutoImport.js +++ b/source/templates/import/UpgradeAutoImport.js @@ -27,6 +27,7 @@ module.exports = { ServiceToken: { Ref: 'CFNLambda' }, importbucket: { Ref: 'ImportBucket' }, exportbucket: { Ref: 'ExportBucket' }, + contentDesignerOutputBucket : { Ref: 'ContentDesignerOutputBucket' }, id: exportfile, index: { Ref: 'VarIndex' }, es_endpoint: { Ref: 'EsEndpoint' }, @@ -40,6 +41,7 @@ module.exports = { ServiceToken: { Ref: 'CFNLambda' }, importbucket: { Ref: 'ImportBucket' }, exportbucket: { Ref: 'ExportBucket' }, + contentDesignerOutputBucket : { Ref: 'ContentDesignerOutputBucket' }, id: exportfile_metrics, index: { Ref: 'MetricsIndex' }, es_endpoint: { Ref: 'EsEndpoint' }, @@ -52,6 +54,7 @@ module.exports = { ServiceToken: { Ref: 'CFNLambda' }, importbucket: { Ref: 'ImportBucket' }, exportbucket: { Ref: 'ExportBucket' }, + contentDesignerOutputBucket : { Ref: 'ContentDesignerOutputBucket' }, id: exportfile_feedback, index: { Ref: 'FeedbackIndex' }, es_endpoint: { Ref: 'EsEndpoint' }, diff --git a/source/templates/import/__snapshots__/index.test.js.snap b/source/templates/import/__snapshots__/index.test.js.snap index a26fa18dd..3ee6fa585 100644 --- a/source/templates/import/__snapshots__/index.test.js.snap +++ b/source/templates/import/__snapshots__/index.test.js.snap @@ -36,6 +36,18 @@ exports[`renders import template correctly 1`] = ` }, ], }, + "LogRetentionPeriodIsNotZero": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "LogRetentionPeriod", + }, + 0, + ], + }, + ], + }, "VPCEnabled": { "Fn::Not": [ { @@ -78,6 +90,9 @@ exports[`renders import template correctly 1`] = ` "CommonModulesLambdaLayer": { "Type": "String", }, + "ContentDesignerOutputBucket": { + "Type": "String", + }, "CustomQnABotSettings": { "Type": "String", }, @@ -123,6 +138,9 @@ exports[`renders import template correctly 1`] = ` "ImportBucket": { "Type": "String", }, + "LogRetentionPeriod": { + "Type": "Number", + }, "MetricsIndex": { "Type": "String", }, @@ -195,6 +213,9 @@ exports[`renders import template correctly 1`] = ` { "Fn::Sub": "arn:aws:s3:::\${ImportBucket}*", }, + { + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}*", + }, ], }, { @@ -503,6 +524,9 @@ exports[`renders import template correctly 1`] = ` { "Fn::Sub": "arn:\${AWS::Partition}:bedrock:\${AWS::Region}::foundation-model/cohere.embed-multilingual-v3", }, + { + "Fn::Sub": "arn:\${AWS::Partition}:bedrock:\${AWS::Region}::foundation-model/amazon.titan-embed-text-v2:0", + }, ], }, ], @@ -565,6 +589,9 @@ exports[`renders import template correctly 1`] = ` "ES_PROXY": { "Ref": "EsProxyLambda", }, + "OUTPUT_S3_BUCKET": { + "Ref": "ContentDesignerOutputBucket", + }, "PRIVATE_SETTINGS_PARAM": { "Ref": "PrivateQnABotSettings", }, @@ -588,6 +615,11 @@ exports[`renders import template correctly 1`] = ` "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ImportStartLambdaLogGroup", + }, + }, "MemorySize": "1024", "Role": { "Fn::GetAtt": [ @@ -643,6 +675,53 @@ exports[`renders import template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "ImportStartLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ImportStartLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "ImportStartPermission": { "Properties": { "Action": "lambda:InvokeFunction", @@ -717,6 +796,9 @@ exports[`renders import template correctly 1`] = ` "ES_PROXY": { "Ref": "EsProxyLambda", }, + "OUTPUT_S3_BUCKET": { + "Ref": "ContentDesignerOutputBucket", + }, "PRIVATE_SETTINGS_PARAM": { "Ref": "PrivateQnABotSettings", }, @@ -739,6 +821,11 @@ exports[`renders import template correctly 1`] = ` "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ImportStepLambdaLogGroup", + }, + }, "MemorySize": "1024", "Role": { "Fn::GetAtt": [ @@ -794,6 +881,53 @@ exports[`renders import template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "ImportStepLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ImportStepLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "ImportStepPermission": { "Properties": { "Action": "lambda:InvokeFunction", @@ -881,6 +1015,9 @@ exports[`renders import template correctly 1`] = ` "ServiceToken": { "Ref": "CFNLambda", }, + "contentDesignerOutputBucket": { + "Ref": "ContentDesignerOutputBucket", + }, "es_endpoint": { "Ref": "EsEndpoint", }, @@ -905,6 +1042,9 @@ exports[`renders import template correctly 1`] = ` "ServiceToken": { "Ref": "CFNLambda", }, + "contentDesignerOutputBucket": { + "Ref": "ContentDesignerOutputBucket", + }, "es_endpoint": { "Ref": "EsEndpoint", }, @@ -929,6 +1069,9 @@ exports[`renders import template correctly 1`] = ` "ServiceToken": { "Ref": "CFNLambda", }, + "contentDesignerOutputBucket": { + "Ref": "ContentDesignerOutputBucket", + }, "es_endpoint": { "Ref": "EsEndpoint", }, diff --git a/source/templates/import/index.js b/source/templates/import/index.js index a006df1b7..01fdc1e4f 100644 --- a/source/templates/import/index.js +++ b/source/templates/import/index.js @@ -26,6 +26,7 @@ module.exports = { Description: `(SO0189n-import) QnABot nested import resources - Version v${process.env.npm_package_version}`, Outputs: require('./outputs'), Parameters: { + ContentDesignerOutputBucket: { Type: 'String' }, CFNLambda: { Type: 'String' }, CFNInvokePolicy: { Type: 'String' }, S3Clean: { Type: 'String' }, @@ -55,6 +56,7 @@ module.exports = { CommonModulesLambdaLayer: { Type: 'String' }, EsProxyLambdaLayer: { Type: 'String' }, QnABotCommonLambdaLayer: { Type: 'String' }, + LogRetentionPeriod: { Type: 'Number' }, }, Conditions: { VPCEnabled: { @@ -64,5 +66,6 @@ module.exports = { EmbeddingsLambdaArn: { 'Fn::Not': [{ 'Fn::Equals': [{ Ref: 'EmbeddingsLambdaArn' }, ''] }] }, EmbeddingsSagemaker: { 'Fn::Not': [{ 'Fn::Equals': [{ Ref: 'EmbeddingsSagemakerEndpointArn' }, ''] }] }, EmbeddingsBedrock: { 'Fn::Equals': [{ Ref: 'EmbeddingsApi' }, 'BEDROCK'] }, + LogRetentionPeriodIsNotZero: { 'Fn::Not': [{ 'Fn::Equals': [{ Ref: 'LogRetentionPeriod' }, 0] }] } }, }; diff --git a/source/templates/import/resources.js b/source/templates/import/resources.js index 9b07ad556..e2ff7d861 100644 --- a/source/templates/import/resources.js +++ b/source/templates/import/resources.js @@ -25,6 +25,30 @@ module.exports = Object.assign(require('./bucket'), { BuildDate: (new Date()).toISOString(), }, }, + ImportStartLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ImportStartLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ImportStartLambda: { Type: "AWS::Lambda::Function", Properties: { @@ -44,10 +68,14 @@ module.exports = Object.assign(require('./bucket'), { DEFAULT_SETTINGS_PARAM: { Ref: "DefaultQnABotSettings" }, PRIVATE_SETTINGS_PARAM: { Ref: "PrivateQnABotSettings" }, CUSTOM_SETTINGS_PARAM: { Ref: "CustomQnABotSettings" }, - ...util.getCommonEnvironmentVariables() + OUTPUT_S3_BUCKET: { Ref: "ContentDesignerOutputBucket"}, + ...util.getCommonEnvironmentVariables(), }, }, Handler: "index.start", + LoggingConfig: { + LogGroup: { Ref: 'ImportStartLambdaLogGroup' }, + }, MemorySize: "1024", Role: { "Fn::GetAtt": ["ImportRole", "Arn"] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -75,6 +103,30 @@ module.exports = Object.assign(require('./bucket'), { }, Metadata: { cfn_nag: util.cfnNag(["W92"]) }, }, + ImportStepLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ImportStepLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ImportStepLambda: { Type: "AWS::Lambda::Function", Properties: { @@ -96,10 +148,14 @@ module.exports = Object.assign(require('./bucket'), { EMBEDDINGS_API: { Ref: "EmbeddingsApi" }, EMBEDDINGS_SAGEMAKER_ENDPOINT: { Ref: "EmbeddingsSagemakerEndpoint" }, EMBEDDINGS_LAMBDA_ARN: { Ref: "EmbeddingsLambdaArn" }, - ...util.getCommonEnvironmentVariables() + OUTPUT_S3_BUCKET: { Ref: "ContentDesignerOutputBucket"}, + ...util.getCommonEnvironmentVariables(), }, }, Handler: "index.step", + LoggingConfig: { + LogGroup: { Ref: 'ImportStepLambdaLogGroup' }, + }, MemorySize: "1024", Role: { "Fn::GetAtt": ["ImportRole", "Arn"] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -204,6 +260,7 @@ module.exports = Object.assign(require('./bucket'), { { 'Fn::Sub': 'arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/amazon.titan-embed-text-v1' }, { 'Fn::Sub': 'arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/cohere.embed-english-v3' }, { 'Fn::Sub': 'arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/cohere.embed-multilingual-v3' }, + { 'Fn::Sub': 'arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/amazon.titan-embed-text-v2:0' }, ], }, ], @@ -233,7 +290,7 @@ module.exports = Object.assign(require('./bucket'), { "s3:DeleteObject", "s3:DeleteObjectVersion", ], - Resource: [{ "Fn::Sub": "arn:aws:s3:::${ImportBucket}*" }], + Resource: [{ "Fn::Sub": "arn:aws:s3:::${ImportBucket}*" }, { "Fn::Sub": "arn:aws:s3:::${ContentDesignerOutputBucket}*" }], }, { Effect: "Allow", Action: [ diff --git a/source/templates/master/UpgradeAutoExport.js b/source/templates/master/UpgradeAutoExport.js index 86f83f98c..74b5a4144 100644 --- a/source/templates/master/UpgradeAutoExport.js +++ b/source/templates/master/UpgradeAutoExport.js @@ -25,6 +25,7 @@ module.exports = { Properties: { ServiceToken: { 'Fn::GetAtt': ['CFNLambda', 'Arn'] }, bucket: { Ref: 'ExportBucket' }, + contentDesignerOutputBucket : { Ref: 'ContentDesignerOutputBucket' }, id: exportfile, index: { 'Fn::Sub': '${Var.QnaIndex}' }, PRE_UPGRADE_EXPORT_TRIGGERS: { @@ -48,6 +49,7 @@ module.exports = { Properties: { ServiceToken: { 'Fn::GetAtt': ['CFNLambda', 'Arn'] }, bucket: { Ref: 'ExportBucket' }, + contentDesignerOutputBucket : { Ref: 'ContentDesignerOutputBucket' }, id: exportfile_metrics, index: { 'Fn::Sub': '${Var.MetricsIndex}' }, PRE_UPGRADE_EXPORT_TRIGGERS: { @@ -71,6 +73,7 @@ module.exports = { Properties: { ServiceToken: { 'Fn::GetAtt': ['CFNLambda', 'Arn'] }, bucket: { Ref: 'ExportBucket' }, + contentDesignerOutputBucket : { Ref: 'ContentDesignerOutputBucket' }, id: exportfile_feedback, index: { 'Fn::Sub': '${Var.FeedbackIndex}' }, PRE_UPGRADE_EXPORT_TRIGGERS: { diff --git a/source/templates/master/__snapshots__/index.test.js.snap b/source/templates/master/__snapshots__/index.test.js.snap index 65c7e8f68..71ff813ae 100644 --- a/source/templates/master/__snapshots__/index.test.js.snap +++ b/source/templates/master/__snapshots__/index.test.js.snap @@ -75,14 +75,6 @@ exports[`Verify master template is correct renders master template correctly 1`] "EMPTY", ], }, - "CreateLexV1Bots": { - "Fn::Equals": [ - { - "Ref": "LexBotVersion", - }, - "LexV1 and LexV2", - ], - }, "Domain": { "Fn::Not": [ { @@ -251,6 +243,18 @@ exports[`Verify master template is correct renders master template correctly 1`] "SAGEMAKER", ], }, + "LogRetentionPeriodIsNotZero": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "LogRetentionPeriod", + }, + 0, + ], + }, + ], + }, "Public": { "Fn::Equals": [ { @@ -311,14 +315,14 @@ exports[`Verify master template is correct renders master template correctly 1`] "ai21.j2-mid-v1": { "MaxTokens": 8191, "ModelID": "ai21.j2-mid-v1", - "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)", + "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)", "QAPromptTemplate": "The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. Documents: {context} Instruction: Based on the above documents, provide a detailed answer for {query} Answer \\"Sorry, I don't know\\" if not present in the document. Solution:", "QueryPromptTemplate": "

    Human: Here is a chat history in tags:

    {history}

    Human: And here is a follow up question or statement from the human in tags:

    {input}

    Human: Rephrase the follow up question or statement as a standalone question or statement that makes sense without reading the chat history.

    Assistant: Here is the rephrased follow up question or statement:", }, "ai21.j2-ultra-v1": { "MaxTokens": 8191, "ModelID": "ai21.j2-ultra-v1", - "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)", + "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)", "QAPromptTemplate": "The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. Documents: {context} Instruction: Based on the above documents, provide a detailed answer for {query} Answer \\"Sorry, I don't know\\" if not present in the document. Solution:", "QueryPromptTemplate": "

    Human: Here is a chat history in tags:

    {history}

    Human: And here is a follow up question or statement from the human in tags:

    {input}

    Human: Rephrase the follow up question or statement as a standalone question or statement that makes sense without reading the chat history.

    Assistant: Here is the rephrased follow up question or statement:", }, @@ -327,59 +331,70 @@ exports[`Verify master template is correct renders master template correctly 1`] "MaxTokens": 8000, "ModelID": "amazon.titan-embed-text-v1", }, + "amazon.titan-embed-text-v2": { + "EmbeddingsDimensions": 1024, + "MaxTokens": 8000, + "ModelID": "amazon.titan-embed-text-v2:0", + }, "amazon.titan-text-express-v1": { "MaxTokens": 8000, "ModelID": "amazon.titan-text-express-v1", - "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)", + "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)", "QAPromptTemplate": "

    Human: You are a friendly AI assistant. Answer the question in tags only based on the provided reference passages. Here are reference passages in tags:

    {context}

    If the references contain the information needed to respond, then write a confident response in under 50 words, quoting the relevant references.
    Otherwise, if you can make an informed guess based on the reference passages, then write a less confident response in under 50 words, stating your assumptions.
    Finally, if the references do not have any relevant information, then respond saying \\"Sorry, I don't know\\".

    {query}


    Assistant: According to the reference passages, in under 50 words:", "QueryPromptTemplate": "Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.
    Chat History:
    {history}
    Follow up question: {input}
    Standalone question:", }, "amazon.titan-text-lite-v1": { "MaxTokens": 4000, "ModelID": "amazon.titan-text-lite-v1", - "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)", + "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)", + "QAPromptTemplate": "

    Human: You are a friendly AI assistant. Answer the question in tags only based on the provided reference passages. Here are reference passages in tags:

    {context}

    If the references contain the information needed to respond, then write a confident response in under 50 words, quoting the relevant references.
    Otherwise, if you can make an informed guess based on the reference passages, then write a less confident response in under 50 words, stating your assumptions.
    Finally, if the references do not have any relevant information, then respond saying \\"Sorry, I don't know\\".

    {query}


    Assistant: According to the reference passages, in under 50 words:", + "QueryPromptTemplate": "Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.
    Chat History:
    {history}
    Follow up question: {input}
    Standalone question:", + }, + "amazon.titan-text-premier-v1": { + "KnowledgeBasePromptTemplate": "You are a question answering bot who gives helpful, detailed, and polite answers to the user's questions. In this session, the model has access to search results and a users question, your job is to answer the user's question using only information from the search results. Model Instructions: - You should provide concise answer to simple questions when the answer is directly contained in search results, but when comes to yes/no question, provide some details. - In case the question requires multi-hop reasoning, you should find relevant information from search results and summarize the answer based on relevant information with logical reasoning. - If the search results do not contain information that can answer the question, then respond saying \\"Sorry, I don't know that.\\". - $output_format_instructions$ - DO NOT USE INFORMATION THAT IS NOT IN SEARCH RESULTS! User: $query$ Bot: Resource: Search Results: $search_results$ Bot:", + "MaxTokens": 32000, + "ModelID": "amazon.titan-text-premier-v1:0", + "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)", "QAPromptTemplate": "

    Human: You are a friendly AI assistant. Answer the question in tags only based on the provided reference passages. Here are reference passages in tags:

    {context}

    If the references contain the information needed to respond, then write a confident response in under 50 words, quoting the relevant references.
    Otherwise, if you can make an informed guess based on the reference passages, then write a less confident response in under 50 words, stating your assumptions.
    Finally, if the references do not have any relevant information, then respond saying \\"Sorry, I don't know\\".

    {query}


    Assistant: According to the reference passages, in under 50 words:", "QueryPromptTemplate": "Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.
    Chat History:
    {history}
    Follow up question: {input}
    Standalone question:", + "maxTokenCount": 3072, }, "anthropic.claude-3-haiku-v1": { + "KnowledgeBasePromptTemplate": "Human: You are a question answering agent. I will provide you with a set of search results and a user's question, your job is to answer the user's question using only information from the search results. If the search results do not contain information that can answer the question, then respond saying \\"Sorry, I don't know that.\\". Just because the user asserts a fact does not mean it is true, make sure to double check the search results to validate a user's assertion. Here are the search results in numbered order: $search_results$. Here is the user's question: $query$ $output_format_instructions$. Do NOT directly quote the $search_results$ in your answer. Your job is to answer the as concisely as possible. Assistant:", "MaxTokens": 100000, "ModelID": "anthropic.claude-3-haiku-20240307-v1:0", - "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)", + "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)", "QAPromptTemplate": "

    Human: You are a friendly AI assistant. Answer the question in tags only based on the provided reference passages. Here are reference passages in tags:

    {context}

    If the references contain the information needed to respond, then write a confident response in under 50 words, quoting the relevant references.
    Otherwise, if you can make an informed guess based on the reference passages, then write a less confident response in under 50 words, stating your assumptions.
    Finally, if the references do not have any relevant information, then respond saying \\"Sorry, I don't know\\".

    {query}


    Assistant: According to the reference passages, in under 50 words:", "QueryPromptTemplate": "

    Human: Here is a chat history in tags:

    {history}

    Human: And here is a follow up question or statement from the human in tags:

    {input}

    Human: Rephrase the follow up question or statement as a standalone question or statement that makes sense without reading the chat history.

    Assistant: Here is the rephrased follow up question or statement:", }, "anthropic.claude-3-sonnet-v1": { + "KnowledgeBasePromptTemplate": "Human: You are a question answering agent. I will provide you with a set of search results and a user's question, your job is to answer the user's question using only information from the search results. If the search results do not contain information that can answer the question, then respond saying \\"Sorry, I don't know that.\\". Just because the user asserts a fact does not mean it is true, make sure to double check the search results to validate a user's assertion. Here are the search results in numbered order: $search_results$. Here is the user's question: $query$ $output_format_instructions$. Do NOT directly quote the $search_results$ in your answer. Your job is to answer the as concisely as possible. Assistant:", "MaxTokens": 100000, "ModelID": "anthropic.claude-3-sonnet-20240229-v1:0", - "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)", + "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)", "QAPromptTemplate": "

    Human: You are a friendly AI assistant. Answer the question in tags only based on the provided reference passages. Here are reference passages in tags:

    {context}

    If the references contain the information needed to respond, then write a confident response in under 50 words, quoting the relevant references.
    Otherwise, if you can make an informed guess based on the reference passages, then write a less confident response in under 50 words, stating your assumptions.
    Finally, if the references do not have any relevant information, then respond saying \\"Sorry, I don't know\\".

    {query}


    Assistant: According to the reference passages, in under 50 words:", "QueryPromptTemplate": "

    Human: Here is a chat history in tags:

    {history}

    Human: And here is a follow up question or statement from the human in tags:

    {input}

    Human: Rephrase the follow up question or statement as a standalone question or statement that makes sense without reading the chat history.

    Assistant: Here is the rephrased follow up question or statement:", }, "anthropic.claude-instant-v1": { + "KnowledgeBasePromptTemplate": "Human: You are a question answering agent. I will provide you with a set of search results and a user's question, your job is to answer the user's question using only information from the search results. If the search results do not contain information that can answer the question, then respond saying \\"Sorry, I don't know that.\\". Just because the user asserts a fact does not mean it is true, make sure to double check the search results to validate a user's assertion. Here are the search results in numbered order: $search_results$. Here is the user's question: $query$ $output_format_instructions$. Do NOT directly quote the $search_results$ in your answer. Your job is to answer the as concisely as possible. Assistant:", "MaxTokens": 100000, "ModelID": "anthropic.claude-instant-v1", - "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)", + "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)", "QAPromptTemplate": "

    Human: You are a friendly AI assistant. Answer the question in tags only based on the provided reference passages. Here are reference passages in tags:

    {context}

    If the references contain the information needed to respond, then write a confident response in under 50 words, quoting the relevant references.
    Otherwise, if you can make an informed guess based on the reference passages, then write a less confident response in under 50 words, stating your assumptions.
    Finally, if the references do not have any relevant information, then respond saying \\"Sorry, I don't know\\".

    {query}


    Assistant: According to the reference passages, in under 50 words:", "QueryPromptTemplate": "

    Human: Here is a chat history in tags:

    {history}

    Human: And here is a follow up question or statement from the human in tags:

    {input}

    Human: Rephrase the follow up question or statement as a standalone question or statement that makes sense without reading the chat history.

    Assistant: Here is the rephrased follow up question or statement:", }, "anthropic.claude-v2.1": { + "KnowledgeBasePromptTemplate": "Human: You are a question answering agent. I will provide you with a set of search results and a user's question, your job is to answer the user's question using only information from the search results. If the search results do not contain information that can answer the question, then respond saying \\"Sorry, I don't know that.\\". Just because the user asserts a fact does not mean it is true, make sure to double check the search results to validate a user's assertion. Here are the search results in numbered order: $search_results$. Here is the user's question: $query$ $output_format_instructions$. Do NOT directly quote the $search_results$ in your answer. Your job is to answer the as concisely as possible. Assistant:", "MaxTokens": 100000, "ModelID": "anthropic.claude-v2:1", - "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)", + "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)", "QAPromptTemplate": "

    Human: You are a friendly AI assistant. Answer the question in tags only based on the provided reference passages. Here are reference passages in tags:

    {context}

    If the references contain the information needed to respond, then write a confident response in under 50 words, quoting the relevant references.
    Otherwise, if you can make an informed guess based on the reference passages, then write a less confident response in under 50 words, stating your assumptions.
    Finally, if the references do not have any relevant information, then respond saying \\"Sorry, I don't know\\".

    {query}


    Assistant: According to the reference passages, in under 50 words:", "QueryPromptTemplate": "

    Human: Here is a chat history in tags:

    {history}

    Human: And here is a follow up question or statement from the human in tags:

    {input}

    Human: Rephrase the follow up question or statement as a standalone question or statement that makes sense without reading the chat history.

    Assistant: Here is the rephrased follow up question or statement:", }, - "cohere.command-light-text-v14": { - "MaxTokens": 4000, - "ModelID": "cohere.command-light-text-v14", - "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)", - "QAPromptTemplate": "

    Human: You are a friendly AI assistant. Answer the question in tags only based on the provided reference passages. Here are reference passages in tags:

    {context}

    If the references contain the information needed to respond, then write a confident response in under 50 words, quoting the relevant references.
    Otherwise, if you can make an informed guess based on the reference passages, then write a less confident response in under 50 words, stating your assumptions.
    Finally, if the references do not have any relevant information, then respond saying \\"Sorry, I don't know\\".

    {query}


    Assistant: According to the reference passages, in under 50 words:", - "QueryPromptTemplate": "Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.
    Chat History:
    {history}
    Follow up question: {input}
    Standalone question:", - }, "cohere.command-text-v14": { "MaxTokens": 4000, "ModelID": "cohere.command-text-v14", - "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)", + "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)", "QAPromptTemplate": "

    Human: You are a friendly AI assistant. Answer the question in tags only based on the provided reference passages. Here are reference passages in tags:

    {context}

    If the references contain the information needed to respond, then write a confident response in under 50 words, quoting the relevant references.
    Otherwise, if you can make an informed guess based on the reference passages, then write a less confident response in under 50 words, stating your assumptions.
    Finally, if the references do not have any relevant information, then respond saying \\"Sorry, I don't know\\".

    {query}


    Assistant: According to the reference passages, in under 50 words:", "QueryPromptTemplate": "Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.
    Chat History:
    {history}
    Follow up question: {input}
    Standalone question:", }, @@ -396,7 +411,7 @@ exports[`Verify master template is correct renders master template correctly 1`] "meta.llama3-8b-instruct-v1": { "MaxTokens": 8000, "ModelID": "meta.llama3-8b-instruct-v1:0", - "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)", + "NoHitsRegex": "(Sorry, I don't know|unable to assist you|i don't have enough context|i could not find an exact answer|no information in the search results|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)", "QAPromptTemplate": "

    Human: You are a friendly AI assistant. Answer the question in tags only based on the provided reference passages. Here are reference passages in tags:

    {context}

    If the references contain the information needed to respond, then write a confident response in under 50 words, quoting the relevant references.
    Otherwise, if you can make an informed guess based on the reference passages, then write a less confident response in under 50 words, stating your assumptions.
    Finally, if the references do not have any relevant information, then respond saying \\"Sorry, I don't know\\".

    {query}


    Assistant: According to the reference passages, in under 50 words:", "QueryPromptTemplate": "Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.
    Chat History:
    {history}
    Follow up question: {input}
    Standalone question:", }, @@ -435,7 +450,6 @@ exports[`Verify master template is correct renders master template correctly 1`] "OpenSearchDashboardsRetentionMinutes", "OpenSearchFineGrainAccessControl", "LexV2BotLocaleIds", - "LexBotVersion", "InstallLexResponseBots", "FulfillmentConcurrency", "XraySetting", @@ -497,6 +511,7 @@ exports[`Verify master template is correct renders master template correctly 1`] "BootstrapBucket", "BootstrapPrefix", "BuildExamples", + "LogRetentionPeriod", ], }, ], @@ -516,25 +531,6 @@ exports[`Verify master template is correct renders master template correctly 1`] "Ref": "API", }, }, - "BotConsoleUrl": { - "Condition": "CreateLexV1Bots", - "Value": { - "Fn::Join": [ - "", - [ - "https://console.aws.amazon.com/lex/home?", - "region=", - { - "Ref": "AWS::Region", - }, - "#bot-editor:bot=", - { - "Ref": "LexBot", - }, - ], - ], - }, - }, "Bucket": { "Value": { "Ref": "Bucket", @@ -588,6 +584,11 @@ exports[`Verify master template is correct renders master template correctly 1`] ], }, }, + "ContentDesignerOutputBucket": { + "Value": { + "Ref": "ContentDesignerOutputBucket", + }, + }, "ContentDesignerURL": { "Value": { "Fn::Join": [ @@ -676,36 +677,6 @@ exports[`Verify master template is correct renders master template correctly 1`] "Ref": "ImportBucket", }, }, - "LexV1BotAlias": { - "Condition": "CreateLexV1Bots", - "Value": { - "Ref": "VersionAlias", - }, - }, - "LexV1BotName": { - "Condition": "CreateLexV1Bots", - "Value": { - "Ref": "LexBot", - }, - }, - "LexV1Intent": { - "Condition": "CreateLexV1Bots", - "Value": { - "Ref": "Intent", - }, - }, - "LexV1IntentFallback": { - "Condition": "CreateLexV1Bots", - "Value": { - "Ref": "IntentFallback", - }, - }, - "LexV1SlotType": { - "Condition": "CreateLexV1Bots", - "Value": { - "Ref": "SlotType", - }, - }, "LexV2BotAlias": { "Value": { "Fn::GetAtt": [ @@ -796,6 +767,11 @@ exports[`Verify master template is correct renders master template correctly 1`] "Ref": "PrivateQnABotSettings", }, }, + "TestAllBucket": { + "Value": { + "Ref": "TestAllBucket", + }, + }, "UserPool": { "Value": { "Ref": "UserPool", @@ -874,6 +850,7 @@ exports[`Verify master template is correct renders master template correctly 1`] }, "BedrockKnowledgeBaseModel": { "AllowedValues": [ + "amazon.titan-text-premier-v1", "anthropic.claude-instant-v1", "anthropic.claude-v2.1", "anthropic.claude-3-sonnet-v1", @@ -924,6 +901,7 @@ exports[`Verify master template is correct renders master template correctly 1`] "EmbeddingsBedrockModelId": { "AllowedValues": [ "amazon.titan-embed-text-v1", + "amazon.titan-embed-text-v2", "cohere.embed-english-v3", "cohere.embed-multilingual-v3", ], @@ -988,6 +966,7 @@ exports[`Verify master template is correct renders master template correctly 1`] "AllowedValues": [ "amazon.titan-text-express-v1", "amazon.titan-text-lite-v1", + "amazon.titan-text-premier-v1", "ai21.j2-ultra-v1", "ai21.j2-mid-v1", "anthropic.claude-instant-v1", @@ -1062,15 +1041,6 @@ exports[`Verify master template is correct renders master template correctly 1`] "Description": "Choose the primary Language for your QnABot deployment. Note: Picking non-English may correspond with limited functionalities", "Type": "String", }, - "LexBotVersion": { - "AllowedValues": [ - "LexV1 and LexV2", - "LexV2 Only", - ], - "Default": "LexV2 Only", - "Description": "Amazon Lex version to use for QnABot on AWS. Select 'LexV2 Only' to install QnABot in AWS regions where LexV1 is not supported.", - "Type": "String", - }, "LexV2BotLocaleIds": { "AllowedPattern": "[^ ]+", "ConstraintDescription": "Must be a valid comma separated list of Locale IDs", @@ -1078,6 +1048,37 @@ exports[`Verify master template is correct renders master template correctly 1`] "Description": "Languages for QnABot on AWS voice interaction using LexV2. Specify as a comma separated list of valid Locale IDs without empty spaces - see https://github.com/aws-solutions/qnabot-on-aws/blob/main/source/docs/multilanguage_support/README.md#supported-languages", "Type": "String", }, + "LogRetentionPeriod": { + "AllowedValues": [ + 0, + 1, + 3, + 5, + 7, + 14, + 30, + 60, + 90, + 120, + 150, + 180, + 365, + 400, + 545, + 731, + 1096, + 1827, + 2192, + 2557, + 2922, + 3288, + 3653, + ], + "Default": 0, + "Description": "Optional: The number of days to keep logs before expiring. If you would like your logs to never expire, leave this value as 0.", + "MinValue": 0, + "Type": "Number", + }, "OpenSearchDashboardsRetentionMinutes": { "Default": 43200, "Description": "To conserve storage in Amazon OpenSearch, metrics and feedback data used to populate the OpenSearch dashboards are automatically deleted after this period (default 43200 minutes = 30 days). Monitor 'Free storage space' for your OpenSearch domain to ensure that you have sufficient space available to store data for the desired retention period.", @@ -1292,7 +1293,10 @@ exports[`Verify master template is correct renders master template correctly 1`] "Fn::Sub": "arn:aws:s3:::\${ExportBucket}/data/*", }, { - "Fn::Sub": "arn:aws:s3:::\${TestAllBucket}/data/*", + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}/data-testall/*", + }, + { + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}/data-export/*", }, ], }, @@ -1328,6 +1332,17 @@ exports[`Verify master template is correct renders master template correctly 1`] }, ], }, + { + "Action": [ + "lambda:InvokeFunction", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Sub": "arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:\${SolutionHelper}", + }, + ], + }, ], "Version": "2012-10-17", }, @@ -2685,6 +2700,11 @@ exports[`Verify master template is correct renders master template correctly 1`] }, }, "Handler": "index.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "CFNLambdaLogGroup", + }, + }, "MemorySize": "3008", "Role": { "Fn::GetAtt": [ @@ -2730,6 +2750,53 @@ exports[`Verify master template is correct renders master template correctly 1`] }, "Type": "AWS::Lambda::Function", }, + "CFNLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-CFNLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "CFNLambdaRole": { "Metadata": { "cfn_nag": { @@ -3366,9 +3433,100 @@ exports[`Verify master template is correct renders master template correctly 1`] }, "Type": "Custom::S3Version", }, + "ContentDesignerOutputBucket": { + "DependsOn": [ + "MainAccessLogBucket", + "MainAccessLogsBucketPolicy", + ], + "Metadata": { + "guard": { + "SuppressedRules": [ + "S3_BUCKET_NO_PUBLIC_RW_ACL", + ], + }, + }, + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "AES256", + }, + }, + ], + }, + "CorsConfiguration": { + "CorsRules": [ + { + "AllowedHeaders": [ + "*", + ], + "AllowedMethods": [ + "GET", + ], + "AllowedOrigins": [ + "*", + ], + }, + ], + }, + "LifecycleConfiguration": { + "Rules": [ + { + "ExpirationInDays": 1, + "Status": "Enabled", + }, + ], + }, + "LoggingConfiguration": { + "DestinationBucketName": { + "Ref": "MainAccessLogBucket", + }, + "LogFilePrefix": { + "Fn::Join": [ + "", + [ + { + "Ref": "MainAccessLogBucket", + }, + "/ContentDesignerOutput/", + ], + ], + }, + }, + "PublicAccessBlockConfiguration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true, + }, + "VersioningConfiguration": { + "Status": "Enabled", + }, + }, + "Type": "AWS::S3::Bucket", + }, + "ContentDesignerOutputClean": { + "DependsOn": [ + "CFNInvokePolicy", + ], + "Properties": { + "Bucket": { + "Ref": "ContentDesignerOutputBucket", + }, + "ServiceToken": { + "Fn::GetAtt": [ + "S3Clean", + "Arn", + ], + }, + }, + "Type": "Custom::S3Clean", + }, "CustomQnABotSettings": { "Properties": { "Description": "Custom QnABot Settings - Modify to override defaults, or to add new settings", + "Tier": "Advanced", "Type": "String", "Value": "{}", }, @@ -3428,7 +3586,7 @@ exports[`Verify master template is correct renders master template correctly 1`] "Type": "String", "Value": { "Fn::Sub": [ - "{"ENABLE_DEBUG_RESPONSES":"false","ENABLE_DEBUG_LOGGING":"false","ES_USE_KEYWORD_FILTERS":"\${ES_USE_KEYWORD_FILTERS}","ES_EXPAND_CONTRACTIONS":"{\\"you're\\":\\"you are\\",\\"I'm\\":\\"I am\\",\\"can't\\":\\"cannot\\"}","ES_KEYWORD_SYNTAX_TYPES":"NOUN,PROPN,VERB,INTJ","ES_SYNTAX_CONFIDENCE_LIMIT":0.2,"ES_MINIMUM_SHOULD_MATCH":"2<75%","ES_NO_HITS_QUESTION":"no_hits","ES_ERROR_QUESTION":"error_msg","ES_USE_FUZZY_MATCH":"false","ES_PHRASE_BOOST":4,"ES_SCORE_ANSWER_FIELD":"false","ES_SCORE_TEXT_ITEM_PASSAGES":"true","ENABLE_SENTIMENT_SUPPORT":"true","ENABLE_MULTI_LANGUAGE_SUPPORT":"false","ENABLE_CUSTOM_TERMINOLOGY":"false","MINIMUM_CONFIDENCE_SCORE":0.6,"ALT_SEARCH_KENDRA_FALLBACK_CONFIDENCE_SCORE":"HIGH","ALT_SEARCH_KENDRA_FAQ_CONFIDENCE_SCORE":"HIGH","ALT_SEARCH_KENDRA_S3_SIGNED_URLS":"true","ALT_SEARCH_KENDRA_S3_SIGNED_URL_EXPIRE_SECS":300,"ALT_SEARCH_KENDRA_MAX_DOCUMENT_COUNT":2,"ALT_SEARCH_KENDRA_TOP_ANSWER_MESSAGE":"Amazon Kendra suggested answer.","ALT_SEARCH_KENDRA_FAQ_MESSAGE":"Answer from Amazon Kendra FAQ.","ALT_SEARCH_KENDRA_ANSWER_MESSAGE":"While I did not find an exact answer, these search results from Amazon Kendra might be helpful.","ALT_SEARCH_KENDRA_RESPONSE_TYPES":"ANSWER,DOCUMENT,QUESTION_ANSWER","ALT_SEARCH_KENDRA_ABBREVIATE_MESSAGE_FOR_SSML":"true","KENDRA_FAQ_CONFIG_MAX_RETRIES":8,"KENDRA_FAQ_CONFIG_RETRY_DELAY":600,"KENDRA_FAQ_ES_FALLBACK":"true","ENABLE_KENDRA_WEB_INDEXER":"false","KENDRA_INDEXER_URLS":"","KENDRA_INDEXER_CRAWL_DEPTH":3,"KENDRA_INDEXER_CRAWL_MODE":"SUBDOMAINS","KENDRA_INDEXER_SCHEDULE":"rate(1 day)","KENDRA_INDEXED_DOCUMENTS_LANGUAGES":"en","ERRORMESSAGE":"Unfortunately I encountered an error when searching for your answer. Please ask me again later.","EMPTYMESSAGE":"You stumped me! Sadly I do not know how to answer your question.","DEFAULT_ALEXA_LAUNCH_MESSAGE":"Hello, Please ask a question","DEFAULT_ALEXA_REPROMPT":"Please either answer the question, ask another question or say Goodbye to end the conversation.","DEFAULT_ALEXA_STOP_MESSAGE":"Goodbye","SMS_HINT_REMINDER_ENABLE":"true","SMS_HINT_REMINDER":" (Feedback? Reply THUMBS UP or THUMBS DOWN. Ask HELP ME at any time)","SMS_HINT_REMINDER_INTERVAL_HRS":24,"IDENTITY_PROVIDER_JWKS_URLS":[],"ENFORCE_VERIFIED_IDENTITY":"false","NO_VERIFIED_IDENTITY_QUESTION":"no_verified_identity","ELICIT_RESPONSE_MAX_RETRIES":3,"ELICIT_RESPONSE_RETRY_MESSAGE":"Please try again.","ELICIT_RESPONSE_BOT_FAILURE_MESSAGE":"Your response was not understood. Please start again.","ELICIT_RESPONSE_DEFAULT_MSG":"Ok. ","CONNECT_IGNORE_WORDS":"","CONNECT_ENABLE_VOICE_RESPONSE_INTERRUPT":"false","CONNECT_NEXT_PROMPT_VARNAME":"connect_nextPrompt","ENABLE_REDACTING":"false","REDACTING_REGEX":"\\\\b\\\\d{4}\\\\b(?![-])|\\\\b\\\\d{9}\\\\b|\\\\b\\\\d{3}-\\\\d{2}-\\\\d{4}\\\\b","ENABLE_REDACTING_WITH_COMPREHEND":"false","COMPREHEND_REDACTING_CONFIDENCE_SCORE":0.99,"COMPREHEND_REDACTING_ENTITY_TYPES":"ADDRESS,EMAIL,SSN,PHONE,PASSWORD,BANK_ACCOUNT_NUMBER,BANK_ROUTING,CREDIT_DEBIT_NUMBER","PII_REJECTION_ENABLED":false,"PII_REJECTION_QUESTION":"pii_rejection_question","PII_REJECTION_REGEX":"\\\\b\\\\d{4}\\\\b(?![-])|\\\\b\\\\d{9}\\\\b|\\\\b\\\\d{3}-\\\\d{2}-\\\\d{4}\\\\b","PII_REJECTION_ENTITY_TYPES":"ADDRESS,EMAIL,SSN,PHONE,PASSWORD,BANK_ACCOUNT_NUMBER,BANK_ROUTING,CREDIT_DEBIT_NUMBER","PII_REJECTION_CONFIDENCE_SCORE":0.99,"DISABLE_CLOUDWATCH_LOGGING":"false","MINIMAL_ES_LOGGING":"false","S3_PUT_REQUEST_ENCRYPTION":"","BOT_ROUTER_WELCOME_BACK_MSG":"Welcome back to QnABot.","BOT_ROUTER_EXIT_MSGS":"exit,quit,goodbye,leave","RUN_LAMBDAHOOK_FROM_QUERY_STEP":"true","LAMBDA_PREPROCESS_HOOK":"","LAMBDA_POSTPROCESS_HOOK":"","SEARCH_REPLACE_QUESTION_SUBSTRINGS":"","PROTECTED_UTTERANCES":"help,help me,thumbs up,thumbs down,repeat,no_hits,no_verified_identity,reset language,detect language,english,french,spanish,german,italian,chinese,arabic,greek,repeat,can you repeat that,can you please say that again,please repeat that","EMBEDDINGS_ENABLE":"\${EMBEDDINGS_ENABLE}","EMBEDDINGS_SCORE_THRESHOLD":"\${EMBEDDINGS_SCORE_THRESHOLD}","EMBEDDINGS_SCORE_ANSWER_THRESHOLD":0.8,"EMBEDDINGS_TEXT_PASSAGE_SCORE_THRESHOLD":"\${EMBEDDINGS_TEXT_PASSAGE_SCORE_THRESHOLD}","EMBEDDINGS_MAX_TOKEN_LIMIT":"\${EMBEDDINGS_MAX_TOKEN_LIMIT}","LLM_GENERATE_QUERY_ENABLE":"\${LLM_GENERATE_QUERY_ENABLE}","LLM_GENERATE_QUERY_PROMPT_TEMPLATE":"\${LLM_GENERATE_QUERY_PROMPT_TEMPLATE}","LLM_GENERATE_QUERY_MODEL_PARAMS":"\${LLM_GENERATE_QUERY_MODEL_PARAMS}","LLM_QA_ENABLE":"\${LLM_QA_ENABLE}","LLM_QA_USE_KENDRA_RETRIEVAL_API":"\${LLM_QA_ENABLE}","LLM_QA_PROMPT_TEMPLATE":"\${LLM_QA_PROMPT_TEMPLATE}","LLM_QA_MODEL_PARAMS":"\${LLM_QA_MODEL_PARAMS}","LLM_QA_PREFIX_MESSAGE":"LLM Answer:","LLM_QA_SHOW_CONTEXT_TEXT":"true","LLM_QA_SHOW_SOURCE_LINKS":"true","LLM_CHAT_HISTORY_MAX_MESSAGES":12,"LLM_QA_NO_HITS_REGEX":"\${LLM_QA_NO_HITS_REGEX}","LLM_PROMPT_MAX_TOKEN_LIMIT":"\${LLM_PROMPT_MAX_TOKEN_LIMIT}","KNOWLEDGE_BASE_PREFIX_MESSAGE":"From Knowledge Base:","KNOWLEDGE_BASE_SHOW_REFERENCES":"true","KNOWLEDGE_BASE_S3_SIGNED_URLS":"true","KNOWLEDGE_BASE_S3_SIGNED_URL_EXPIRE_SECS":300}", + "{"ENABLE_DEBUG_RESPONSES":"false","ENABLE_DEBUG_LOGGING":"false","ES_USE_KEYWORD_FILTERS":"\${ES_USE_KEYWORD_FILTERS}","ES_EXPAND_CONTRACTIONS":"{\\"you're\\":\\"you are\\",\\"I'm\\":\\"I am\\",\\"can't\\":\\"cannot\\"}","ES_KEYWORD_SYNTAX_TYPES":"NOUN,PROPN,VERB,INTJ","ES_SYNTAX_CONFIDENCE_LIMIT":0.2,"ES_MINIMUM_SHOULD_MATCH":"2<75%","ES_NO_HITS_QUESTION":"no_hits","ES_ERROR_QUESTION":"error_msg","ES_USE_FUZZY_MATCH":"false","ES_PHRASE_BOOST":4,"ES_SCORE_ANSWER_FIELD":"false","ES_SCORE_TEXT_ITEM_PASSAGES":"true","ENABLE_SENTIMENT_SUPPORT":"true","ENABLE_MULTI_LANGUAGE_SUPPORT":"false","ENABLE_CUSTOM_TERMINOLOGY":"false","MINIMUM_CONFIDENCE_SCORE":0.6,"ALT_SEARCH_KENDRA_FALLBACK_CONFIDENCE_SCORE":"HIGH","ALT_SEARCH_KENDRA_FAQ_CONFIDENCE_SCORE":"HIGH","ALT_SEARCH_KENDRA_S3_SIGNED_URLS":"true","ALT_SEARCH_KENDRA_S3_SIGNED_URL_EXPIRE_SECS":300,"ALT_SEARCH_KENDRA_MAX_DOCUMENT_COUNT":2,"ALT_SEARCH_KENDRA_TOP_ANSWER_MESSAGE":"Amazon Kendra suggested answer.","ALT_SEARCH_KENDRA_FAQ_MESSAGE":"Answer from Amazon Kendra FAQ.","ALT_SEARCH_KENDRA_ANSWER_MESSAGE":"While I did not find an exact answer, these search results from Amazon Kendra might be helpful.","ALT_SEARCH_KENDRA_RESPONSE_TYPES":"ANSWER,DOCUMENT,QUESTION_ANSWER","ALT_SEARCH_KENDRA_ABBREVIATE_MESSAGE_FOR_SSML":"true","KENDRA_FAQ_CONFIG_MAX_RETRIES":8,"KENDRA_FAQ_CONFIG_RETRY_DELAY":600,"KENDRA_FAQ_ES_FALLBACK":"true","ENABLE_KENDRA_WEB_INDEXER":"false","KENDRA_INDEXER_URLS":"","KENDRA_INDEXER_CRAWL_DEPTH":3,"KENDRA_INDEXER_CRAWL_MODE":"SUBDOMAINS","KENDRA_INDEXER_SCHEDULE":"rate(1 day)","KENDRA_INDEXED_DOCUMENTS_LANGUAGES":"en","ERRORMESSAGE":"Unfortunately I encountered an error when searching for your answer. Please ask me again later.","EMPTYMESSAGE":"You stumped me! Sadly I do not know how to answer your question.","DEFAULT_ALEXA_LAUNCH_MESSAGE":"Hello, Please ask a question","DEFAULT_ALEXA_REPROMPT":"Please either answer the question, ask another question or say Goodbye to end the conversation.","DEFAULT_ALEXA_STOP_MESSAGE":"Goodbye","SMS_HINT_REMINDER_ENABLE":"true","SMS_HINT_REMINDER":" (Feedback? Reply THUMBS UP or THUMBS DOWN. Ask HELP ME at any time)","SMS_HINT_REMINDER_INTERVAL_HRS":24,"IDENTITY_PROVIDER_JWKS_URLS":[],"ENFORCE_VERIFIED_IDENTITY":"false","NO_VERIFIED_IDENTITY_QUESTION":"no_verified_identity","ELICIT_RESPONSE_MAX_RETRIES":3,"ELICIT_RESPONSE_RETRY_MESSAGE":"Please try again.","ELICIT_RESPONSE_BOT_FAILURE_MESSAGE":"Your response was not understood. Please start again.","ELICIT_RESPONSE_DEFAULT_MSG":"Ok. ","CONNECT_IGNORE_WORDS":"","CONNECT_ENABLE_VOICE_RESPONSE_INTERRUPT":"false","CONNECT_NEXT_PROMPT_VARNAME":"connect_nextPrompt","ENABLE_REDACTING":"false","REDACTING_REGEX":"\\\\b\\\\d{4}\\\\b(?![-])|\\\\b\\\\d{9}\\\\b|\\\\b\\\\d{3}-\\\\d{2}-\\\\d{4}\\\\b","ENABLE_REDACTING_WITH_COMPREHEND":"false","COMPREHEND_REDACTING_CONFIDENCE_SCORE":0.99,"COMPREHEND_REDACTING_ENTITY_TYPES":"ADDRESS,EMAIL,SSN,PHONE,PASSWORD,BANK_ACCOUNT_NUMBER,BANK_ROUTING,CREDIT_DEBIT_NUMBER","PII_REJECTION_ENABLED":false,"PII_REJECTION_QUESTION":"pii_rejection_question","PII_REJECTION_REGEX":"\\\\b\\\\d{4}\\\\b(?![-])|\\\\b\\\\d{9}\\\\b|\\\\b\\\\d{3}-\\\\d{2}-\\\\d{4}\\\\b","PII_REJECTION_ENTITY_TYPES":"ADDRESS,EMAIL,SSN,PHONE,PASSWORD,BANK_ACCOUNT_NUMBER,BANK_ROUTING,CREDIT_DEBIT_NUMBER","PII_REJECTION_CONFIDENCE_SCORE":0.99,"DISABLE_CLOUDWATCH_LOGGING":"false","MINIMAL_ES_LOGGING":"false","S3_PUT_REQUEST_ENCRYPTION":"","BOT_ROUTER_WELCOME_BACK_MSG":"Welcome back to QnABot.","BOT_ROUTER_EXIT_MSGS":"exit,quit,goodbye,leave","RUN_LAMBDAHOOK_FROM_QUERY_STEP":"true","LAMBDA_PREPROCESS_HOOK":"","LAMBDA_POSTPROCESS_HOOK":"","SEARCH_REPLACE_QUESTION_SUBSTRINGS":"","PROTECTED_UTTERANCES":"help,help me,thumbs up,thumbs down,repeat,no_hits,no_verified_identity,reset language,detect language,english,french,spanish,german,italian,chinese,arabic,greek,repeat,can you repeat that,can you please say that again,please repeat that","EMBEDDINGS_ENABLE":"\${EMBEDDINGS_ENABLE}","EMBEDDINGS_SCORE_THRESHOLD":"\${EMBEDDINGS_SCORE_THRESHOLD}","EMBEDDINGS_SCORE_ANSWER_THRESHOLD":0.8,"EMBEDDINGS_TEXT_PASSAGE_SCORE_THRESHOLD":"\${EMBEDDINGS_TEXT_PASSAGE_SCORE_THRESHOLD}","EMBEDDINGS_MAX_TOKEN_LIMIT":"\${EMBEDDINGS_MAX_TOKEN_LIMIT}","LLM_GENERATE_QUERY_ENABLE":"\${LLM_GENERATE_QUERY_ENABLE}","LLM_GENERATE_QUERY_PROMPT_TEMPLATE":"\${LLM_GENERATE_QUERY_PROMPT_TEMPLATE}","LLM_GENERATE_QUERY_MODEL_PARAMS":"\${LLM_GENERATE_QUERY_MODEL_PARAMS}","LLM_QA_ENABLE":"\${LLM_QA_ENABLE}","LLM_QA_USE_KENDRA_RETRIEVAL_API":"\${LLM_QA_ENABLE}","LLM_QA_PROMPT_TEMPLATE":"\${LLM_QA_PROMPT_TEMPLATE}","LLM_QA_MODEL_PARAMS":"\${LLM_QA_MODEL_PARAMS}","LLM_QA_PREFIX_MESSAGE":"LLM Answer:","LLM_QA_SHOW_CONTEXT_TEXT":"true","LLM_QA_SHOW_SOURCE_LINKS":"true","LLM_CHAT_HISTORY_MAX_MESSAGES":12,"LLM_QA_NO_HITS_REGEX":"\${LLM_QA_NO_HITS_REGEX}","LLM_PROMPT_MAX_TOKEN_LIMIT":"\${LLM_PROMPT_MAX_TOKEN_LIMIT}","KNOWLEDGE_BASE_PREFIX_MESSAGE":"From Knowledge Base:","KNOWLEDGE_BASE_SHOW_REFERENCES":"true","KNOWLEDGE_BASE_S3_SIGNED_URLS":"true","KNOWLEDGE_BASE_S3_SIGNED_URL_EXPIRE_SECS":300,"KNOWLEDGE_BASE_PROMPT_TEMPLATE":"\${KNOWLEDGE_BASE_PROMPT_TEMPLATE}","KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS":"","KNOWLEDGE_BASE_SEARCH_TYPE":"DEFAULT","KNOWLEDGE_BASE_METADATA_FILTERS":"{}","KNOWLEDGE_BASE_MODEL_PARAMS":"{}","BEDROCK_GUARDRAIL_IDENTIFIER":"","BEDROCK_GUARDRAIL_VERSION":""}", { "EMBEDDINGS_ENABLE": { "Fn::If": [ @@ -3473,6 +3631,21 @@ exports[`Verify master template is correct renders master template correctly 1`] "true", ], }, + "KNOWLEDGE_BASE_PROMPT_TEMPLATE": { + "Fn::If": [ + "BedrockKnowledgeBaseEnable", + { + "Fn::FindInMap": [ + "BedrockDefaults", + { + "Ref": "BedrockKnowledgeBaseModel", + }, + "KnowledgeBasePromptTemplate", + ], + }, + "Human: You are a question answering agent. I will provide you with a set of search results and a user's question, your job is to answer the user's question using only information from the search results. If the search results do not contain information that can answer the question, then respond saying \\"Sorry, I don't know\\". Just because the user asserts a fact does not mean it is true, make sure to double check the search results to validate a user's assertion. Here are the search results in numbered order: $search_results$. Here is the user's question: $query$ $output_format_instructions$. Do NOT directly quote the $search_results$ in your answer. Your job is to answer the as concisely as possible. Assistant:", + ], + }, "LLM_GENERATE_QUERY_ENABLE": { "Fn::If": [ "LLMEnable", @@ -4004,6 +4177,11 @@ exports[`Verify master template is correct renders master template correctly 1`] "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ESCFNProxyLambdaLogGroup", + }, + }, "MemorySize": "1408", "Role": { "Fn::GetAtt": [ @@ -4049,46 +4227,93 @@ exports[`Verify master template is correct renders master template correctly 1`] }, "Type": "AWS::Lambda::Function", }, - "ESCleaningLambda": { + "ESCFNProxyLambdaLogGroup": { "Metadata": { - "cfn_nag": { - "rules_to_suppress": [ - { - "id": "W92", - "reason": "This lambda function does not require to have ReservedConcurrentExecutions", - }, - ], - }, "guard": { "SuppressedRules": [ - "LAMBDA_CONCURRENCY_CHECK", - "LAMBDA_INSIDE_VPC", + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", ], }, }, "Properties": { - "Code": { - "S3Bucket": { - "Ref": "BootstrapBucket", - }, - "S3Key": { - "Fn::Sub": "\${BootstrapPrefix}/lambda/proxy-es.zip", - }, - "S3ObjectVersion": { - "Ref": "ESProxyCodeVersion", - }, - }, - "Environment": { - "Variables": { - "ES_ADDRESS": { - "Fn::GetAtt": [ - "ESVar", - "ESAddress", - ], - }, - "ES_INDEX": { - "Fn::GetAtt": [ - "Var", + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ESCFNProxyLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, + "ESCleaningLambda": { + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W92", + "reason": "This lambda function does not require to have ReservedConcurrentExecutions", + }, + ], + }, + "guard": { + "SuppressedRules": [ + "LAMBDA_CONCURRENCY_CHECK", + "LAMBDA_INSIDE_VPC", + ], + }, + }, + "Properties": { + "Code": { + "S3Bucket": { + "Ref": "BootstrapBucket", + }, + "S3Key": { + "Fn::Sub": "\${BootstrapPrefix}/lambda/proxy-es.zip", + }, + "S3ObjectVersion": { + "Ref": "ESProxyCodeVersion", + }, + }, + "Environment": { + "Variables": { + "ES_ADDRESS": { + "Fn::GetAtt": [ + "ESVar", + "ESAddress", + ], + }, + "ES_INDEX": { + "Fn::GetAtt": [ + "Var", "QnaIndex", ], }, @@ -4117,6 +4342,11 @@ exports[`Verify master template is correct renders master template correctly 1`] "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ESCleaningLambdaLogGroup", + }, + }, "MemorySize": "1408", "Role": { "Fn::GetAtt": [ @@ -4162,6 +4392,53 @@ exports[`Verify master template is correct renders master template correctly 1`] }, "Type": "AWS::Lambda::Function", }, + "ESCleaningLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ESCleaningLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "ESCognitoRole": { "Metadata": { "cfn_nag": { @@ -4408,6 +4685,11 @@ exports.handler = async function (event, context) { "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ESInfoLambdaLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -4453,6 +4735,54 @@ exports.handler = async function (event, context) { }, "Type": "AWS::Lambda::Function", }, + "ESInfoLambdaLogGroup": { + "Condition": "DontCreateDomain", + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ESInfoLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "ESLoggingLambda": { "Metadata": { "cfn_nag": { @@ -4506,6 +4836,11 @@ exports.handler = async function (event, context) { "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ESLoggingLambdaLogGroup", + }, + }, "MemorySize": "1408", "Role": { "Fn::GetAtt": [ @@ -4551,6 +4886,53 @@ exports.handler = async function (event, context) { }, "Type": "AWS::Lambda::Function", }, + "ESLoggingLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ESLoggingLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "ESLoggingLambdaRole": { "Metadata": { "cfn_nag": { @@ -4879,6 +5261,11 @@ exports.handler = async function (event, context) { "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ESProxyLambdaLogGroup", + }, + }, "MemorySize": "1408", "Role": { "Fn::GetAtt": [ @@ -4924,6 +5311,53 @@ exports.handler = async function (event, context) { }, "Type": "AWS::Lambda::Function", }, + "ESProxyLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ESProxyLambdaLogGroup", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "ESProxyLambdaRole": { "Metadata": { "cfn_nag": { @@ -5144,23 +5578,6 @@ exports.handler = async function (event, context) { "Effect": "Allow", "Resource": "*", }, - { - "Action": [ - "lex:GetBuiltinIntent", - "lex:GetIntents", - "lex:GetBots", - "lex:GetSlotTypes", - "lex:GetBotAliases", - "lex:StartImport", - "lex:GetMigration", - "lex:GetBuiltinSlotTypes", - "lex:GetBuiltinIntents", - "lex:GetImport", - "lex:GetMigrations", - ], - "Effect": "Allow", - "Resource": "*", - }, { "Action": "lex:*", "Effect": "Allow", @@ -5209,23 +5626,6 @@ exports.handler = async function (event, context) { }, ], }, - { - "Action": [ - "lex:GetBuiltinIntent", - "lex:GetIntents", - "lex:GetBots", - "lex:GetSlotTypes", - "lex:GetBotAliases", - "lex:StartImport", - "lex:GetMigration", - "lex:GetBuiltinSlotTypes", - "lex:GetBuiltinIntents", - "lex:GetImport", - "lex:GetMigrations", - ], - "Effect": "Allow", - "Resource": "*", - }, { "Action": "lex:*", "Effect": "Allow", @@ -5580,7 +5980,28 @@ exports.handler = async function (event, context) { "Effect": "Allow", "Resource": [ { - "Fn::Sub": "arn:\${AWS::Partition}:bedrock:\${AWS::Region}::foundation-model/\${EmbeddingsBedrockModelId}", + "Fn::If": [ + "EmbeddingsBedrock", + { + "Fn::Sub": [ + "arn:\${AWS::Partition}:bedrock:\${AWS::Region}::foundation-model/\${ModelId}", + { + "ModelId": { + "Fn::FindInMap": [ + "BedrockDefaults", + { + "Ref": "EmbeddingsBedrockModelId", + }, + "ModelID", + ], + }, + }, + ], + }, + { + "Ref": "AWS::NoValue", + }, + ], }, ], }, @@ -5683,6 +6104,11 @@ exports.handler = async function (event, context) { "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ESQidLambdaLogGroup", + }, + }, "MemorySize": "1408", "Role": { "Fn::GetAtt": [ @@ -5728,6 +6154,53 @@ exports.handler = async function (event, context) { }, "Type": "AWS::Lambda::Function", }, + "ESQidLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ESQidLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "ESQueryLambda": { "Metadata": { "cfn_nag": { @@ -5765,12 +6238,6 @@ exports.handler = async function (event, context) { "DEFAULT_SETTINGS_PARAM": { "Ref": "DefaultQnABotSettings", }, - "EXTCanvasLMSHook": { - "Fn::GetAtt": [ - "ExamplesStack", - "Outputs.EXTCanvasLMSHook", - ], - }, "EXTCreateRecentTopicsResponse": { "Fn::GetAtt": [ "ExamplesStack", @@ -5859,6 +6326,11 @@ exports.handler = async function (event, context) { "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ESQueryLambdaLogGroup", + }, + }, "MemorySize": "1408", "Role": { "Fn::GetAtt": [ @@ -5904,6 +6376,53 @@ exports.handler = async function (event, context) { }, "Type": "AWS::Lambda::Function", }, + "ESQueryLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ESQueryLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "ESVar": { "Properties": { "ESAddress": { @@ -6054,6 +6573,11 @@ exports.handler = async function (event, context) { "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ESWarmerLambdaLogGroup", + }, + }, "MemorySize": "512", "Role": { "Fn::GetAtt": [ @@ -6099,6 +6623,53 @@ exports.handler = async function (event, context) { }, "Type": "AWS::Lambda::Function", }, + "ESWarmerLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ESWarmerLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "ESWarmerRule": { "Properties": { "ScheduleExpression": "rate(1 minute)", @@ -6467,6 +7038,11 @@ exports.documents = (event, context, callback) => { "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ExampleS3ListLambdaLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -6493,16 +7069,63 @@ exports.documents = (event, context, callback) => { }, ], }, - "VpcConfig": { + "VpcConfig": { + "Fn::If": [ + "VPCEnabled", + { + "SecurityGroupIds": { + "Ref": "VPCSecurityGroupIdList", + }, + "SubnetIds": { + "Ref": "VPCSubnetIdList", + }, + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Lambda::Function", + }, + "ExampleS3ListLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ExampleS3ListLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { "Fn::If": [ - "VPCEnabled", + "LogRetentionPeriodIsNotZero", { - "SecurityGroupIds": { - "Ref": "VPCSecurityGroupIdList", - }, - "SubnetIds": { - "Ref": "VPCSubnetIdList", - }, + "Ref": "LogRetentionPeriod", }, { "Ref": "AWS::NoValue", @@ -6510,7 +7133,7 @@ exports.documents = (event, context, callback) => { ], }, }, - "Type": "AWS::Lambda::Function", + "Type": "AWS::Logs::LogGroup", }, "ExampleS3ListPhotoLambda": { "Metadata": { @@ -6626,6 +7249,11 @@ exports.documents = (event, context, callback) => { "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "ExampleS3ListPhotoLambdaLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -6671,6 +7299,53 @@ exports.documents = (event, context, callback) => { }, "Type": "AWS::Lambda::Function", }, + "ExampleS3ListPhotoLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-ExampleS3ListPhotoLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "Examples": { "Properties": { "ParentId": { @@ -6808,8 +7483,8 @@ exports.documents = (event, context, callback) => { "InstallLexResponseBots": { "Ref": "InstallLexResponseBots", }, - "LexBotVersion": { - "Ref": "LexBotVersion", + "LogRetentionPeriod": { + "Ref": "LogRetentionPeriod", }, "PrivateQnABotSettings": { "Ref": "PrivateQnABotSettings", @@ -6969,15 +7644,6 @@ exports.documents = (event, context, callback) => { "BootstrapPrefix": { "Ref": "BootstrapPrefix", }, - "BotName": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "LexBot", - }, - "LexV2Only_Mode", - ], - }, "CFNInvokePolicy": { "Ref": "CFNInvokePolicy", }, @@ -6987,6 +7653,9 @@ exports.documents = (event, context, callback) => { "Arn", ], }, + "ContentDesignerOutputBucket": { + "Ref": "ContentDesignerOutputBucket", + }, "CustomQnABotSettings": { "Ref": "CustomQnABotSettings", }, @@ -7008,24 +7677,6 @@ exports.documents = (event, context, callback) => { "ExportBucket": { "Ref": "ExportBucket", }, - "FallbackIntent": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "IntentFallback", - }, - "LexV2Only_Mode", - ], - }, - "Intent": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "Intent", - }, - "LexV2Only_Mode", - ], - }, "KendraCrawlerSnsTopic": { "Ref": "KendraCrawlerSnsTopic", }, @@ -7065,12 +7716,9 @@ exports.documents = (event, context, callback) => { "botName", ], }, - "LexVersion": { - "Fn::If": [ - "CreateLexV1Bots", - "V1", - "V2", - ], + "LexVersion": "V2", + "LogRetentionPeriod": { + "Ref": "LogRetentionPeriod", }, "PrivateQnABotSettings": { "Ref": "PrivateQnABotSettings", @@ -7264,16 +7912,49 @@ exports.documents = (event, context, callback) => { "id": "W86", "reason": "LogGroup is encrypted by default.", }, - { - "id": "W84", - "reason": "LogGroup needs to be retained indefinitely", - }, + ], + }, + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", ], }, }, "Properties": { "LogGroupName": { - "Fn::Sub": "/aws/kinesisfirehose/\${AWS::StackName}-FeedbackKinesisFirehose", + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/kinesisfirehose/\${AWS::StackName}-FeedbackKinesisFirehose", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], }, }, "Type": "AWS::Logs::LogGroup", @@ -7703,12 +8384,6 @@ exports.documents = (event, context, callback) => { "QnAType", ], }, - "EXTCanvasLMSHook": { - "Fn::GetAtt": [ - "ExamplesStack", - "Outputs.EXTCanvasLMSHook", - ], - }, "EXTCreateRecentTopicsResponse": { "Fn::GetAtt": [ "ExamplesStack", @@ -7944,6 +8619,11 @@ exports.documents = (event, context, callback) => { "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "FulfillmentLambdaLogGroup", + }, + }, "MemorySize": 1408, "Role": { "Fn::GetAtt": [ @@ -8016,6 +8696,53 @@ exports.documents = (event, context, callback) => { }, "Type": "AWS::Lambda::Alias", }, + "FulfillmentLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-FulfillmentLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "FulfillmentLambdaRole": { "Metadata": { "cfn_nag": { @@ -8387,7 +9114,20 @@ exports.documents = (event, context, callback) => { "Fn::If": [ "EmbeddingsBedrock", { - "Fn::Sub": "arn:\${AWS::Partition}:bedrock:\${AWS::Region}::foundation-model/\${EmbeddingsBedrockModelId}", + "Fn::Sub": [ + "arn:\${AWS::Partition}:bedrock:\${AWS::Region}::foundation-model/\${ModelId}", + { + "ModelId": { + "Fn::FindInMap": [ + "BedrockDefaults", + { + "Ref": "EmbeddingsBedrockModelId", + }, + "ModelID", + ], + }, + }, + ], }, { "Ref": "AWS::NoValue", @@ -8444,6 +9184,18 @@ exports.documents = (event, context, callback) => { }, ], }, + { + "Action": [ + "bedrock:ApplyGuardrail", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Sub": "arn:\${AWS::Partition}:bedrock:\${AWS::Region}:\${AWS::AccountId}:guardrail/*", + }, + ], + "Sid": "ApplyGuardrailsToLLMBedrock", + }, ], "Version": "2012-10-17", }, @@ -8470,6 +9222,18 @@ exports.documents = (event, context, callback) => { "Fn::Sub": "arn:\${AWS::Partition}:bedrock:\${AWS::Region}:\${AWS::AccountId}:knowledge-base/\${BedrockKnowledgeBaseId}", }, }, + { + "Action": [ + "bedrock:ApplyGuardrail", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Sub": "arn:\${AWS::Partition}:bedrock:\${AWS::Region}:\${AWS::AccountId}:guardrail/*", + }, + ], + "Sid": "ApplyGuardrailsToKnowledgeBase", + }, ], "Version": "2012-10-17", }, @@ -8701,16 +9465,49 @@ exports.documents = (event, context, callback) => { "id": "W86", "reason": "LogGroup is encrypted by default.", }, - { - "id": "W84", - "reason": "LogGroup needs to be retained indefinitely", - }, + ], + }, + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", ], }, }, "Properties": { "LogGroupName": { - "Fn::Sub": "/aws/kinesisfirehose/\${AWS::StackName}-GeneralKinesisFirehose", + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/kinesisfirehose/\${AWS::StackName}-GeneralKinesisFirehose", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], }, }, "Type": "AWS::Logs::LogGroup", @@ -8729,14 +9526,67 @@ exports.documents = (event, context, callback) => { "LogGroupName": { "Ref": "GeneralKinesisFirehoseLogGroup", }, - "LogStreamName": "S3BackupDelivery", + "LogStreamName": "S3BackupDelivery", + }, + "Type": "AWS::Logs::LogStream", + }, + "HTTPSOnlyAssetBucketPolicy": { + "Properties": { + "Bucket": { + "Ref": "AssetBucket", + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false", + }, + }, + "Effect": "Deny", + "Principal": "*", + "Resource": [ + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "AssetBucket", + "Arn", + ], + }, + "/*", + ], + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "AssetBucket", + "Arn", + ], + }, + ], + ], + }, + ], + "Sid": "HttpsOnly", + }, + ], + "Version": "2012-10-17", + }, }, - "Type": "AWS::Logs::LogStream", + "Type": "AWS::S3::BucketPolicy", }, - "HTTPSOnlyAssetBucketPolicy": { + "HTTPSOnlyBucketPolicy": { "Properties": { "Bucket": { - "Ref": "AssetBucket", + "Ref": "Bucket", }, "PolicyDocument": { "Statement": [ @@ -8756,7 +9606,7 @@ exports.documents = (event, context, callback) => { [ { "Fn::GetAtt": [ - "AssetBucket", + "Bucket", "Arn", ], }, @@ -8770,7 +9620,7 @@ exports.documents = (event, context, callback) => { [ { "Fn::GetAtt": [ - "AssetBucket", + "Bucket", "Arn", ], }, @@ -8786,10 +9636,13 @@ exports.documents = (event, context, callback) => { }, "Type": "AWS::S3::BucketPolicy", }, - "HTTPSOnlyBucketPolicy": { + "HTTPSOnlyBuildStatusBucketPolicy": { + "Metadata": { + "aws:cdk:path": "serverless-bot-framework/CloudfrontStaticWebsite/CloudFrontToS3/S3LoggingBucket/Policy/Resource", + }, "Properties": { "Bucket": { - "Ref": "Bucket", + "Ref": "BuildStatusBucket", }, "PolicyDocument": { "Statement": [ @@ -8809,7 +9662,7 @@ exports.documents = (event, context, callback) => { [ { "Fn::GetAtt": [ - "Bucket", + "BuildStatusBucket", "Arn", ], }, @@ -8823,7 +9676,7 @@ exports.documents = (event, context, callback) => { [ { "Fn::GetAtt": [ - "Bucket", + "BuildStatusBucket", "Arn", ], }, @@ -8839,13 +9692,10 @@ exports.documents = (event, context, callback) => { }, "Type": "AWS::S3::BucketPolicy", }, - "HTTPSOnlyBuildStatusBucketPolicy": { - "Metadata": { - "aws:cdk:path": "serverless-bot-framework/CloudfrontStaticWebsite/CloudFrontToS3/S3LoggingBucket/Policy/Resource", - }, + "HTTPSOnlyContentDesignerOutputBucketPolicy": { "Properties": { "Bucket": { - "Ref": "BuildStatusBucket", + "Ref": "ContentDesignerOutputBucket", }, "PolicyDocument": { "Statement": [ @@ -8865,7 +9715,7 @@ exports.documents = (event, context, callback) => { [ { "Fn::GetAtt": [ - "BuildStatusBucket", + "ContentDesignerOutputBucket", "Arn", ], }, @@ -8879,7 +9729,7 @@ exports.documents = (event, context, callback) => { [ { "Fn::GetAtt": [ - "BuildStatusBucket", + "ContentDesignerOutputBucket", "Arn", ], }, @@ -9545,6 +10395,9 @@ exports.documents = (event, context, callback) => { "CommonModulesLambdaLayer": { "Ref": "CommonModulesLambdaLayer", }, + "ContentDesignerOutputBucket": { + "Ref": "ContentDesignerOutputBucket", + }, "CustomQnABotSettings": { "Ref": "CustomQnABotSettings", }, @@ -9626,6 +10479,9 @@ exports.documents = (event, context, callback) => { "ImportBucket": { "Ref": "ImportBucket", }, + "LogRetentionPeriod": { + "Ref": "LogRetentionPeriod", + }, "MetricsIndex": { "Fn::GetAtt": [ "Var", @@ -9757,93 +10613,6 @@ exports.documents = (event, context, callback) => { }, "Type": "Custom::Variable", }, - "Intent": { - "Condition": "CreateLexV1Bots", - "DependsOn": "QNAInvokePermission", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "CFNLambda", - "Arn", - ], - }, - "createVersion": true, - "description": "custom intent x.x.x - v1", - "fulfillmentActivity": { - "codeHook": { - "messageVersion": "1.0", - "uri": { - "Fn::Join": [ - ":", - [ - { - "Fn::GetAtt": [ - "FulfillmentLambda", - "Arn", - ], - }, - "live", - ], - ], - }, - }, - "type": "CodeHook", - }, - "prefix": "fulfilment", - "sampleUtterances": [ - "{slot}", - ], - "slots": [ - { - "name": "slot", - "priority": 1, - "slotConstraint": "Optional", - "slotType": { - "Ref": "SlotType", - }, - "slotTypeVersion": "QNABOT-AUTO-ASSIGNED", - }, - ], - }, - "Type": "Custom::LexIntent", - }, - "IntentFallback": { - "Condition": "CreateLexV1Bots", - "DependsOn": "QNAInvokePermission", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "CFNLambda", - "Arn", - ], - }, - "createVersion": true, - "description": "custom fallback intent x.x.x - v1", - "fulfillmentActivity": { - "codeHook": { - "messageVersion": "1.0", - "uri": { - "Fn::Join": [ - ":", - [ - { - "Fn::GetAtt": [ - "FulfillmentLambda", - "Arn", - ], - }, - "live", - ], - ], - }, - }, - "type": "CodeHook", - }, - "parentIntentSignature": "AMAZON.FallbackIntent", - "prefix": "qnabotfallbackfulfilment", - }, - "Type": "Custom::LexIntent", - }, "InvokePermissionESCleaningLambda": { "Properties": { "Action": "lambda:InvokeFunction", @@ -10186,12 +10955,6 @@ exports.documents = (event, context, callback) => { "Outputs.EXTCustomJSHook", ], }, - { - "Fn::GetAtt": [ - "ExamplesStack", - "Outputs.EXTCanvasLMSHook", - ], - }, { "Fn::GetAtt": [ "ExamplesStack", @@ -10313,8 +11076,6 @@ exports.documents = (event, context, callback) => { "Statement": [ { "Action": [ - "lex:PostContent", - "lex:PostText", "lex:RecognizeText", "lex:RecognizeUtterance", ], @@ -10366,46 +11127,6 @@ exports.documents = (event, context, callback) => { }, "Type": "AWS::IAM::ManagedPolicy", }, - "LexBot": { - "Condition": "CreateLexV1Bots", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "CFNLambda", - "Arn", - ], - }, - "abortStatement": { - "messages": [ - { - "content": "Sorry, I did not understand that", - "contentType": "PlainText", - }, - ], - }, - "childDirected": false, - "createVersion": true, - "description": "QnABot primary bot x.x.x - v1", - "intents": [ - { - "intentName": { - "Ref": "Intent", - }, - }, - { - "intentName": { - "Ref": "IntentFallback", - }, - }, - ], - "locale": "en-US", - "name": { - "Fn::Sub": "\${AWS::StackName}-Bot", - }, - "voiceId": "Joanna", - }, - "Type": "Custom::LexBot", - }, "LexBotPolicy": { "Metadata": { "guard": { @@ -10419,7 +11140,6 @@ exports.documents = (event, context, callback) => { "Statement": [ { "Action": [ - "lex:PostText", "lex:RecognizeText", ], "Effect": "Allow", @@ -10543,56 +11263,12 @@ exports.documents = (event, context, callback) => { ], ], }, - "BOTALIAS": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "VersionAlias", - }, - { - "Ref": "AWS::NoValue", - }, - ], - }, - "BOTNAME": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "LexBot", - }, - { - "Ref": "AWS::NoValue", - }, - ], - }, "INDEX": { "Fn::GetAtt": [ "Var", "index", ], }, - "INTENT": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "Intent", - }, - { - "Ref": "AWS::NoValue", - }, - ], - }, - "INTENTFALLBACK": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "IntentFallback", - }, - { - "Ref": "AWS::NoValue", - }, - ], - }, "LEXV2_BUILD_LAMBDA": { "Ref": "Lexv2BotLambda", }, @@ -10603,31 +11279,11 @@ exports.documents = (event, context, callback) => { "Arn", ], }, - "SLOTTYPE": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "SlotType", - }, - { - "Ref": "AWS::NoValue", - }, - ], - }, "SOLUTION_ID": "SO0189", "SOLUTION_VERSION": "vx.x.x", "STATUS_BUCKET": { "Ref": "BuildStatusBucket", }, - "STATUS_KEY": { - "Fn::If": [ - "CreateLexV1Bots", - "status.json", - { - "Ref": "AWS::NoValue", - }, - ], - }, "UTTERANCE_BUCKET": { "Ref": "AssetBucket", }, @@ -10643,6 +11299,11 @@ exports.documents = (event, context, callback) => { "Ref": "CommonModulesLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "LexBuildLambdaLogGroup", + }, + }, "MemorySize": "1024", "Role": { "Fn::GetAtt": [ @@ -10688,6 +11349,53 @@ exports.documents = (event, context, callback) => { }, "Type": "AWS::Lambda::Function", }, + "LexBuildLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-LexBuildLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "LexBuildLambdaPoll": { "Metadata": { "cfn_nag": { @@ -10789,31 +11497,11 @@ exports.handler = async function (event, context, callback) { }, "Environment": { "Variables": { - "BOT_NAME": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "LexBot", - }, - { - "Ref": "AWS::NoValue", - }, - ], - }, "SOLUTION_ID": "SO0189", "SOLUTION_VERSION": "vx.x.x", "STATUS_BUCKET": { "Ref": "BuildStatusBucket", }, - "STATUS_KEY": { - "Fn::If": [ - "CreateLexV1Bots", - "status.json", - { - "Ref": "AWS::NoValue", - }, - ], - }, }, }, "Handler": "index.handler", @@ -10825,6 +11513,11 @@ exports.handler = async function (event, context, callback) { "Ref": "CommonModulesLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "LexBuildLambdaPollLogGroup", + }, + }, "MemorySize": "1024", "Role": { "Fn::GetAtt": [ @@ -10851,16 +11544,63 @@ exports.handler = async function (event, context, callback) { }, ], }, - "VpcConfig": { + "VpcConfig": { + "Fn::If": [ + "VPCEnabled", + { + "SecurityGroupIds": { + "Ref": "VPCSecurityGroupIdList", + }, + "SubnetIds": { + "Ref": "VPCSubnetIdList", + }, + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Lambda::Function", + }, + "LexBuildLambdaPollLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-LexBuildLambdaPoll", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { "Fn::If": [ - "VPCEnabled", + "LogRetentionPeriodIsNotZero", { - "SecurityGroupIds": { - "Ref": "VPCSecurityGroupIdList", - }, - "SubnetIds": { - "Ref": "VPCSubnetIdList", - }, + "Ref": "LogRetentionPeriod", }, { "Ref": "AWS::NoValue", @@ -10868,7 +11608,7 @@ exports.handler = async function (event, context, callback) { ], }, }, - "Type": "AWS::Lambda::Function", + "Type": "AWS::Logs::LogGroup", }, "LexBuildLambdaRole": { "Metadata": { @@ -11070,23 +11810,6 @@ exports.handler = async function (event, context, callback) { "Effect": "Allow", "Resource": "*", }, - { - "Action": [ - "lex:GetBuiltinIntent", - "lex:GetIntents", - "lex:GetBots", - "lex:GetSlotTypes", - "lex:GetBotAliases", - "lex:StartImport", - "lex:GetMigration", - "lex:GetBuiltinSlotTypes", - "lex:GetBuiltinIntents", - "lex:GetImport", - "lex:GetMigrations", - ], - "Effect": "Allow", - "Resource": "*", - }, { "Action": "lex:*", "Effect": "Allow", @@ -11135,23 +11858,6 @@ exports.handler = async function (event, context, callback) { }, ], }, - { - "Action": [ - "lex:GetBuiltinIntent", - "lex:GetIntents", - "lex:GetBots", - "lex:GetSlotTypes", - "lex:GetBotAliases", - "lex:StartImport", - "lex:GetMigration", - "lex:GetBuiltinSlotTypes", - "lex:GetBuiltinIntents", - "lex:GetImport", - "lex:GetMigrations", - ], - "Effect": "Allow", - "Resource": "*", - }, { "Action": "lex:*", "Effect": "Allow", @@ -11427,22 +12133,10 @@ const crypto = require('crypto'); exports.handler = async function (event, context, callback) { const token = crypto.randomBytes(16).toString('base64'); const bucket = process.env.STATUS_BUCKET; - const lexV1StatusFile = process.env.STATUS_KEY; const lexV2StatusFile = process.env.LEXV2_STATUS_KEY; const functionName = process.env.BUILD_FUNCTION; const body = JSON.stringify({ status: 'Starting', token }); - if (lexV1StatusFile) { - console.log('Initializing ', bucket, lexV1StatusFile); - const params = { - Bucket: bucket, - Key: lexV1StatusFile, - Body: body, - }; - const putObjectCmdV1 = new PutObjectCommand(params); - await s3.send(putObjectCmdV1); - } - console.log('Initializing ', bucket, lexV2StatusFile); const params = { Bucket: bucket, @@ -11452,7 +12146,7 @@ exports.handler = async function (event, context, callback) { const putObjectCmdV2 = new PutObjectCommand(params); await s3.send(putObjectCmdV2); - // The BUILD_FUNCTION takes care of rebuilding Lex V2 bot, and (unless QnABot is set to V2 only) Lex V1 bot + // The BUILD_FUNCTION takes care of rebuilding Lex V2 bot console.log('Invoking ', functionName); const invokeParams = { FunctionName: functionName, @@ -11479,15 +12173,6 @@ exports.handler = async function (event, context, callback) { "STATUS_BUCKET": { "Ref": "BuildStatusBucket", }, - "STATUS_KEY": { - "Fn::If": [ - "CreateLexV1Bots", - "status.json", - { - "Ref": "AWS::NoValue", - }, - ], - }, }, }, "Handler": "index.handler", @@ -11499,6 +12184,11 @@ exports.handler = async function (event, context, callback) { "Ref": "CommonModulesLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "LexBuildLambdaStartLogGroup", + }, + }, "MemorySize": "1024", "Role": { "Fn::GetAtt": [ @@ -11544,6 +12234,53 @@ exports.handler = async function (event, context, callback) { }, "Type": "AWS::Lambda::Function", }, + "LexBuildLambdaStartLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-LexBuildLambdaStart", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "LexProxyLambda": { "Metadata": { "cfn_nag": { @@ -11613,6 +12350,11 @@ exports.handler = (event, context, callback) => { "Ref": "CommonModulesLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "LexProxyLambdaLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -11658,6 +12400,53 @@ exports.handler = (event, context, callback) => { }, "Type": "AWS::Lambda::Function", }, + "LexProxyLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-LexProxyLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "LexProxyLambdaRole": { "Metadata": { "cfn_nag": { @@ -11832,23 +12621,6 @@ exports.handler = (event, context, callback) => { "Effect": "Allow", "Resource": "*", }, - { - "Action": [ - "lex:GetBuiltinIntent", - "lex:GetIntents", - "lex:GetBots", - "lex:GetSlotTypes", - "lex:GetBotAliases", - "lex:StartImport", - "lex:GetMigration", - "lex:GetBuiltinSlotTypes", - "lex:GetBuiltinIntents", - "lex:GetImport", - "lex:GetMigrations", - ], - "Effect": "Allow", - "Resource": "*", - }, { "Action": "lex:*", "Effect": "Allow", @@ -11897,23 +12669,6 @@ exports.handler = (event, context, callback) => { }, ], }, - { - "Action": [ - "lex:GetBuiltinIntent", - "lex:GetIntents", - "lex:GetBots", - "lex:GetSlotTypes", - "lex:GetBotAliases", - "lex:StartImport", - "lex:GetMigration", - "lex:GetBuiltinSlotTypes", - "lex:GetBuiltinIntents", - "lex:GetImport", - "lex:GetMigrations", - ], - "Effect": "Allow", - "Resource": "*", - }, { "Action": "lex:*", "Effect": "Allow", @@ -12199,9 +12954,6 @@ function getStatusResponse(response, build) { lambdaArn: process.env.FULFILLMENT_FUNCTION_ARN, lambdaRole: process.env.FULFILLMENT_FUNCTION_ROLE, botversion: 'live', - botname: process.env.LEXV1_BOT_NAME || 'LEX V1 Bot not installed', - intent: process.env.LEXV1_INTENT || 'LEX V1 Bot not installed', - intentFallback: process.env.LEXV1_INTENT_FALLBACK || 'LEX V1 Bot not installed', lexV2botname: process.env.LEXV2_BOT_NAME || 'LEX V2 Bot not installed', lexV2botid: process.env.LEXV2_BOT_ID || 'LEX V2 Bot not installed', lexV2botalias: process.env.LEXV2_BOT_ALIAS || 'LEX V2 Bot not installed', @@ -12219,7 +12971,6 @@ exports.handler = async (event, context, callback) => { console.log('Received event:', JSON.stringify(event, null, 2)); const bucket = process.env.STATUS_BUCKET; - const lexV1StatusFile = process.env.STATUS_KEY; const lexV2StatusFile = process.env.LEXV2_STATUS_KEY; let build = { status: 'READY', token: 'token' }; let response; @@ -12229,16 +12980,6 @@ exports.handler = async (event, context, callback) => { response = await s3.send(getObjCmd); const readableStreamV2 = Buffer.concat(await response.Body.toArray()); build = JSON.parse(readableStreamV2); - // combine build status with v1 bot, if defined.. If both are READY then status is READY - if (lexV1StatusFile) { - const getObjCmd = new GetObjectCommand({ Bucket: bucket, Key: lexV1StatusFile }); - response = await s3.send(getObjCmd); - const readableStreamV2 = Buffer.concat(await response.Body.toArray()); - const v1build = JSON.parse(readableStreamV2); - if (v1build.status != 'READY' || build.status != 'READY') { - build.status = \`LEX V2: \${build.status} / LEX V1: \${v1build.status}\`; - } - } } catch (e) { console.log('Unable to read S3 lex bot status file - perhaps it doesn\\'t yet exist. Returning READY'); } @@ -12247,7 +12988,6 @@ exports.handler = async (event, context, callback) => { botId: process.env.LEXV2_BOT_ID, }); response = await lexv2.send(describeBotCmd); - // Match LexV1 bot status for code compatibility (Available = READY) const statusResponse = getStatusResponse(response, build); return statusResponse; }; @@ -12272,39 +13012,6 @@ exports.handler = async (event, context, callback) => { "FULFILLMENT_FUNCTION_ROLE": { "Ref": "FulfillmentLambdaRole", }, - "LEXV1_BOT_NAME": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "LexBot", - }, - { - "Ref": "AWS::NoValue", - }, - ], - }, - "LEXV1_INTENT": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "Intent", - }, - { - "Ref": "AWS::NoValue", - }, - ], - }, - "LEXV1_INTENT_FALLBACK": { - "Fn::If": [ - "CreateLexV1Bots", - { - "Ref": "IntentFallback", - }, - { - "Ref": "AWS::NoValue", - }, - ], - }, "LEXV2_BOT_ALIAS": { "Fn::GetAtt": [ "LexV2Bot", @@ -12353,15 +13060,6 @@ exports.handler = async (event, context, callback) => { "STATUS_BUCKET": { "Ref": "BuildStatusBucket", }, - "STATUS_KEY": { - "Fn::If": [ - "CreateLexV1Bots", - "status.json", - { - "Ref": "AWS::NoValue", - }, - ], - }, }, }, "Handler": "index.handler", @@ -12370,6 +13068,11 @@ exports.handler = async (event, context, callback) => { "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "LexStatusLambdaLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -12415,6 +13118,53 @@ exports.handler = async (event, context, callback) => { }, "Type": "AWS::Lambda::Function", }, + "LexStatusLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-LexStatusLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "LexV2Bot": { "Properties": { "BuildDate": Any, @@ -12434,6 +13184,53 @@ exports.handler = async (event, context, callback) => { }, "Type": "Custom::LexV2Bot", }, + "LexV2BotLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-LexV2BotLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "Lexv2BotCodeVersion": { "Properties": { "Bucket": { @@ -12509,6 +13306,11 @@ exports.handler = async (event, context, callback) => { }, }, "Handler": "handler.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "LexV2BotLambdaLogGroup", + }, + }, "MemorySize": "1024", "Role": { "Fn::GetAtt": [ @@ -12745,28 +13547,11 @@ exports.handler = async (event, context, callback) => { "s3:ListAllMyBuckets", "lambda:ListFunctions", "cloudwatch:DescribeAlarmsForMetric", - "kms:ListAliases", - "iam:ListRoles", - "cloudwatch:GetMetricStatistics", - "kendra:ListIndices", - "polly:DescribeVoices", - ], - "Effect": "Allow", - "Resource": "*", - }, - { - "Action": [ - "lex:GetBuiltinIntent", - "lex:GetIntents", - "lex:GetBots", - "lex:GetSlotTypes", - "lex:GetBotAliases", - "lex:StartImport", - "lex:GetMigration", - "lex:GetBuiltinSlotTypes", - "lex:GetBuiltinIntents", - "lex:GetImport", - "lex:GetMigrations", + "kms:ListAliases", + "iam:ListRoles", + "cloudwatch:GetMetricStatistics", + "kendra:ListIndices", + "polly:DescribeVoices", ], "Effect": "Allow", "Resource": "*", @@ -12819,23 +13604,6 @@ exports.handler = async (event, context, callback) => { }, ], }, - { - "Action": [ - "lex:GetBuiltinIntent", - "lex:GetIntents", - "lex:GetBots", - "lex:GetSlotTypes", - "lex:GetBotAliases", - "lex:StartImport", - "lex:GetMigration", - "lex:GetBuiltinSlotTypes", - "lex:GetBuiltinIntents", - "lex:GetImport", - "lex:GetMigrations", - ], - "Effect": "Allow", - "Resource": "*", - }, { "Action": "lex:*", "Effect": "Allow", @@ -13352,6 +14120,11 @@ function message(code, name) { "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "MessageLambdaLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -13397,6 +14170,53 @@ function message(code, name) { }, "Type": "AWS::Lambda::Function", }, + "MessageLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-MessageLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "MessagePermision": { "Properties": { "Action": "lambda:InvokeFunction", @@ -13825,10 +14645,12 @@ function message(code, name) { "id": "W86", "reason": "LogGroup is encrypted by default.", }, - { - "id": "W84", - "reason": "LogGroup needs to be retained indefinitely", - }, + ], + }, + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", ], }, }, @@ -13836,6 +14658,17 @@ function message(code, name) { "LogGroupName": { "Fn::Sub": "/aws/opensearch/\${AWS::StackName}-\${ESVar.ESDomain}", }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, }, "Type": "AWS::Logs::LogGroup", }, @@ -14439,6 +15272,9 @@ function message(code, name) { "bucket": { "Ref": "ExportBucket", }, + "contentDesignerOutputBucket": { + "Ref": "ContentDesignerOutputBucket", + }, "id": "ExportAll_QnABot_vx.x.x.json", "index": { "Fn::Sub": "\${Var.QnaIndex}", @@ -14476,6 +15312,9 @@ function message(code, name) { "bucket": { "Ref": "ExportBucket", }, + "contentDesignerOutputBucket": { + "Ref": "ContentDesignerOutputBucket", + }, "id": "ExportAll_QnABot_vx.x.x_feedback.json", "index": { "Fn::Sub": "\${Var.FeedbackIndex}", @@ -14513,6 +15352,9 @@ function message(code, name) { "bucket": { "Ref": "ExportBucket", }, + "contentDesignerOutputBucket": { + "Ref": "ContentDesignerOutputBucket", + }, "id": "ExportAll_QnABot_vx.x.x_metrics.json", "index": { "Fn::Sub": "\${Var.MetricsIndex}", @@ -14533,7 +15375,13 @@ function message(code, name) { "Fn::If": [ "EmbeddingsBedrock", { - "Ref": "EmbeddingsBedrockModelId", + "Fn::FindInMap": [ + "BedrockDefaults", + { + "Ref": "EmbeddingsBedrockModelId", + }, + "ModelID", + ], }, "", ], @@ -14924,12 +15772,6 @@ function message(code, name) { "Outputs.EXTCustomJSHook", ], }, - { - "Fn::GetAtt": [ - "ExamplesStack", - "Outputs.EXTCanvasLMSHook", - ], - }, { "Fn::GetAtt": [ "ExamplesStack", @@ -16298,6 +17140,9 @@ function message(code, name) { { "Fn::Sub": "arn:aws:s3:::\${AssetBucket}/*", }, + { + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}/*", + }, ], }, { @@ -16312,6 +17157,9 @@ function message(code, name) { { "Fn::Sub": "arn:aws:s3:::\${TestAllBucket}/*", }, + { + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}/*", + }, ], }, { @@ -16329,6 +17177,9 @@ function message(code, name) { { "Fn::Sub": "arn:aws:s3:::\${TestAllBucket}/*", }, + { + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}/*", + }, ], }, ], @@ -16366,6 +17217,11 @@ function message(code, name) { }, }, "Handler": "lambda_function.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "S3CleanLambdaLogGroup", + }, + }, "Role": { "Fn::GetAtt": [ "CFNLambdaRole", @@ -16410,6 +17266,53 @@ function message(code, name) { }, "Type": "AWS::Lambda::Function", }, + "S3CleanLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-S3CleanLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "S3ClearCodeVersion": { "Properties": { "Bucket": { @@ -16512,6 +17415,11 @@ exports.handler = (event, context, callback) => { "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "S3ListLambdaLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -16557,6 +17465,53 @@ exports.handler = (event, context, callback) => { }, "Type": "AWS::Lambda::Function", }, + "S3ListLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-S3ListLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "S3ListLambdaRole": { "Metadata": { "cfn_nag": { @@ -16872,6 +17827,11 @@ exports.handler = (event, context, callback) => { "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "SchemaLambdaLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -16935,6 +17895,53 @@ exports.handler = (event, context, callback) => { }, "Type": "Custom::S3Version", }, + "SchemaLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-SchemaLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "SchemaLambdaRole": { "Metadata": { "cfn_nag": { @@ -17223,6 +18230,11 @@ exports.handler = (event, context, callback) => { "Ref": "AwsSdkLayerLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "SignupLambdaLogGroup", + }, + }, "MemorySize": "128", "Role": { "Fn::GetAtt": [ @@ -17268,6 +18280,53 @@ exports.handler = (event, context, callback) => { }, "Type": "AWS::Lambda::Function", }, + "SignupLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-SignupLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "SignupLambdaRole": { "Metadata": { "cfn_nag": { @@ -17425,29 +18484,10 @@ exports.handler = (event, context, callback) => { "Fn::GetAtt": [ "UserPool", "Arn", - ], - }, - }, - "Type": "AWS::Lambda::Permission", - }, - "SlotType": { - "Condition": "CreateLexV1Bots", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "CFNLambda", - "Arn", - ], - }, - "createVersion": true, - "description": "custom slot type x.x.x - v1", - "enumerationValues": [ - { - "value": "dummy utterance", - }, - ], + ], + }, }, - "Type": "Custom::LexSlotType", + "Type": "AWS::Lambda::Permission", }, "SolutionHelper": { "DependsOn": [ @@ -17486,7 +18526,23 @@ exports.handler = (event, context, callback) => { }, }, "Description": "This function generates UUID for each deployment and sends anonymized data to the AWS Solutions team", + "Environment": { + "Variables": { + "CUSTOM_SETTINGS": { + "Ref": "CustomQnABotSettings", + }, + "SOLUTION_ID": "SO0189", + "SOLUTION_PARAMETER": { + "Ref": "SolutionHelperParameter", + }, + }, + }, "Handler": "lambda_function.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "SolutionHelperLogGroup", + }, + }, "Role": { "Fn::GetAtt": [ "SolutionHelperRole", @@ -17564,6 +18620,61 @@ exports.handler = (event, context, callback) => { "Type": "Custom::CreateUUID", "UpdateReplacePolicy": "Delete", }, + "SolutionHelperLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-SolutionHelper", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, + "SolutionHelperParameter": { + "Properties": { + "Description": "Solution Helper Parameter - DO NOT MODIFY", + "Type": "String", + "Value": "{}", + }, + "Type": "AWS::SSM::Parameter", + }, "SolutionHelperRole": { "Metadata": { "cfn_nag": { @@ -17706,6 +18817,104 @@ exports.handler = (event, context, callback) => { }, "PolicyName": "xrayDaemonWriteAccess", }, + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ssm:GetParameter", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Fn::Sub": "\${AWS::Partition}:", + }, + "ssm:", + { + "Fn::Sub": "\${AWS::Region}:", + }, + { + "Fn::Sub": "\${AWS::AccountId}:", + }, + "parameter/", + { + "Ref": "SolutionHelperParameter", + }, + ], + ], + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Fn::Sub": "\${AWS::Partition}:", + }, + "ssm:", + { + "Fn::Sub": "\${AWS::Region}:", + }, + { + "Fn::Sub": "\${AWS::AccountId}:", + }, + "parameter/", + { + "Ref": "CustomQnABotSettings", + }, + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "GetParameterPolicy", + }, + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ssm:PutParameter", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Fn::Sub": "\${AWS::Partition}:", + }, + "ssm:", + { + "Fn::Sub": "\${AWS::Region}:", + }, + { + "Fn::Sub": "\${AWS::AccountId}:", + }, + "parameter/", + { + "Ref": "SolutionHelperParameter", + }, + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "PutParameterPolicy", + }, ], }, "Type": "AWS::IAM::Role", @@ -17791,9 +19000,6 @@ exports.handler = (event, context, callback) => { "Language": { "Ref": "Language", }, - "LexBotVersion": { - "Ref": "LexBotVersion", - }, "OpenSearchEBSVolumeSize": { "Fn::If": [ "CreateDomain", @@ -18062,6 +19268,9 @@ exports.handler = (event, context, callback) => { "CommonModulesLambdaLayer": { "Ref": "CommonModulesLambdaLayer", }, + "ContentDesignerOutputBucket": { + "Ref": "ContentDesignerOutputBucket", + }, "EsEndpoint": { "Fn::GetAtt": [ "ESVar", @@ -18086,6 +19295,9 @@ exports.handler = (event, context, callback) => { "botId", ], }, + "LogRetentionPeriod": { + "Ref": "LogRetentionPeriod", + }, "S3Clean": { "Fn::GetAtt": [ "S3Clean", @@ -18557,6 +19769,11 @@ exports.handler = (event, context, callback) => { "Ref": "QnABotCommonLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "UtteranceLambdaLogGroup", + }, + }, "MemorySize": "1408", "Role": { "Fn::GetAtt": [ @@ -18602,6 +19819,53 @@ exports.handler = (event, context, callback) => { }, "Type": "AWS::Lambda::Function", }, + "UtteranceLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-UtteranceLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "Var": { "Properties": { "FeedbackIndex": { @@ -18639,24 +19903,6 @@ exports.handler = (event, context, callback) => { }, "Type": "Custom::Variable", }, - "VersionAlias": { - "Condition": "CreateLexV1Bots", - "DependsOn": "LexBot", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "CFNLambda", - "Arn", - ], - }, - "botName": { - "Ref": "LexBot", - }, - "description": "QnABot live alias x.x.x - v1", - "name": "live", - }, - "Type": "Custom::LexAlias", - }, "VersionLambda": { "Metadata": { "cfn_nag": { @@ -18782,6 +20028,11 @@ exports.handler = async function (event, context) { }, }, "Handler": "index.handler", + "LoggingConfig": { + "LogGroup": { + "Ref": "VersionLambdaLogGroup", + }, + }, "MemorySize": "3008", "Role": { "Fn::GetAtt": [ @@ -18827,6 +20078,53 @@ exports.handler = async function (event, context) { }, "Type": "AWS::Lambda::Function", }, + "VersionLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-VersionLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "WarmerLambdaRole": { "Metadata": { "cfn_nag": { @@ -19115,7 +20413,7 @@ exports.handler = async function (event, context) { }, ":s3:path/", { - "Ref": "ExportBucket", + "Ref": "ContentDesignerOutputBucket", }, "/status/{proxy}", ], @@ -19189,9 +20487,9 @@ exports.handler = async function (event, context) { }, ":s3:path/", { - "Ref": "ExportBucket", + "Ref": "ContentDesignerOutputBucket", }, - "/status/{proxy}", + "/status-export/{proxy}", ], ], }, @@ -19262,7 +20560,7 @@ exports.handler = async function (event, context) { "id":"$input.params('proxy')", "config":"status/$input.params('proxy')", "tmp":"tmp/$input.params('proxy')", - "key":"$inputRoot.get('prefix')data/$input.params('proxy')", + "key":"$inputRoot.get('prefix')data-export/$input.params('proxy')", "filter":"$inputRoot.get('filter')", "status":"Started" }", @@ -19281,7 +20579,7 @@ exports.handler = async function (event, context) { { "Ref": "ExportBucket", }, - "/status/{proxy}", + "/status-export/{proxy}", ], ], }, @@ -19420,8 +20718,8 @@ exports.handler = async function (event, context) { "Fn::Sub": "#set ($root="https://\${!context.domainName}/\${!context.stage}") { - "bucket":"\${ExportBucket}", - "prefix":"status/", + "bucket":"\${ContentDesignerOutputBucket}", + "prefix":"status-export/", "perpage":"$input.params('perpage')", "token":"$input.params('token')", "type":"exports", @@ -19535,9 +20833,9 @@ exports.handler = async function (event, context) { }, ":s3:path/", { - "Ref": "ImportBucket", + "Ref": "ContentDesignerOutputBucket", }, - "/status/{proxy}", + "/status-import/{proxy}", ], ], }, @@ -19609,9 +20907,9 @@ exports.handler = async function (event, context) { }, ":s3:path/", { - "Ref": "ImportBucket", + "Ref": "ContentDesignerOutputBucket", }, - "/status/{proxy}", + "/status-import/{proxy}", ], ], }, @@ -19750,8 +21048,8 @@ exports.handler = async function (event, context) { "Fn::Sub": "#set ($root="https://\${!context.domainName}/\${!context.stage}") { - "bucket":"\${ImportBucket}", - "prefix":"status/", + "bucket":"\${ContentDesignerOutputBucket}", + "prefix":"status-import/", "perpage":"$input.params('perpage')", "token":"$input.params('token')", "type":"imports", @@ -20106,6 +21404,7 @@ exports.handler = async function (event, context) { "PrivateQnABotSettings":"\${PrivateQnABotSettings}", "CustomQnABotSettings":"\${CustomQnABotSettings}", "KendraCrawlerSnsTopic":"\${KendraCrawlerSnsTopic}", + "SolutionHelper": "\${SolutionHelper}", "Id":"$stageVariables.Id", "_links":{ "root":{ @@ -20237,9 +21536,9 @@ exports.handler = async function (event, context) { }, ":s3:path/", { - "Ref": "TestAllBucket", + "Ref": "ContentDesignerOutputBucket", }, - "/status/{proxy}", + "/status-testall/{proxy}", ], ], }, @@ -20311,9 +21610,9 @@ exports.handler = async function (event, context) { }, ":s3:path/", { - "Ref": "TestAllBucket", + "Ref": "ContentDesignerOutputBucket", }, - "/status/{proxy}", + "/status-testall/{proxy}", ], ], }, @@ -20382,9 +21681,9 @@ exports.handler = async function (event, context) { "bucket":"\${TestAllBucket}", "index":"\${Var.QnaIndex}", "id":"$input.params('proxy')", - "config":"status/$input.params('proxy')", - "tmp":"tmp/$input.params('proxy')", - "key":"data/$input.params('proxy')", + "config":"status-testall/$input.params('proxy')", + "tmp":"tmp-testall/$input.params('proxy')", + "key":"data-testall/$input.params('proxy')", "filter":"$inputRoot.get('filter')", "token":"$inputRoot.get('token')", "locale":"$inputRoot.get('locale')", @@ -20407,7 +21706,7 @@ exports.handler = async function (event, context) { { "Ref": "TestAllBucket", }, - "/status/{proxy}", + "/status-testall/{proxy}", ], ], }, @@ -20546,8 +21845,8 @@ exports.handler = async function (event, context) { "Fn::Sub": "#set ($root="https://\${!context.domainName}/\${!context.stage}") { - "bucket":"\${TestAllBucket}", - "prefix":"status/", + "bucket":"\${ContentDesignerOutputBucket}", + "prefix":"status-testall/", "perpage":"$input.params('perpage')", "token":"$input.params('token')", "type":"testall", diff --git a/source/templates/master/bucket.js b/source/templates/master/bucket.js index 7235ce895..322f42563 100644 --- a/source/templates/master/bucket.js +++ b/source/templates/master/bucket.js @@ -55,18 +55,18 @@ module.exports = { Action: 's3:PutObject', Condition: { ArnLike: { - "aws:SourceArn" : "arn:aws:s3:::*" + 'aws:SourceArn': 'arn:aws:s3:::*', }, Bool: { 'aws:SecureTransport': 'true', }, StringEquals: { - "aws:SourceAccount": {Ref: 'AWS::AccountId'} - } + 'aws:SourceAccount': { Ref: 'AWS::AccountId' }, + }, }, Effect: 'Allow', Principal: { - Service: "logging.s3.amazonaws.com" + Service: 'logging.s3.amazonaws.com', }, Resource: [ { @@ -97,7 +97,7 @@ module.exports = { ], }, ], - Sid:'S3ServerAccessLogsPolicy', + Sid: 'S3ServerAccessLogsPolicy', }, { Action: '*', @@ -138,7 +138,7 @@ module.exports = { }, ], Sid: 'HttpsOnly', - } + }, ], Version: '2012-10-17', }, @@ -147,7 +147,7 @@ module.exports = { ExportBucket: { Type: 'AWS::S3::Bucket', Metadata: { guard: util.cfnGuard('S3_BUCKET_NO_PUBLIC_RW_ACL') }, - DependsOn : ['MainAccessLogBucket', 'MainAccessLogsBucketPolicy'], + DependsOn: ['MainAccessLogBucket', 'MainAccessLogsBucketPolicy'], Properties: { LifecycleConfiguration: { Rules: [{ @@ -179,8 +179,8 @@ module.exports = { }, LoggingConfiguration: { DestinationBucketName: { Ref: 'MainAccessLogBucket' }, - LogFilePrefix: {"Fn::Join": ["", [{Ref: 'MainAccessLogBucket'},"/Export/"]]}, - }, + LogFilePrefix: { 'Fn::Join': ['', [{ Ref: 'MainAccessLogBucket' }, '/Export/']] }, + }, PublicAccessBlockConfiguration: { BlockPublicAcls: true, BlockPublicPolicy: true, @@ -247,7 +247,7 @@ module.exports = { ImportBucket: { Type: 'AWS::S3::Bucket', Metadata: { guard: util.cfnGuard('S3_BUCKET_NO_PUBLIC_RW_ACL') }, - DependsOn : ['MainAccessLogBucket', 'MainAccessLogsBucketPolicy'], + DependsOn: ['MainAccessLogBucket', 'MainAccessLogsBucketPolicy'], Properties: { LifecycleConfiguration: { Rules: [{ @@ -274,8 +274,8 @@ module.exports = { }, LoggingConfiguration: { DestinationBucketName: { Ref: 'MainAccessLogBucket' }, - LogFilePrefix: {"Fn::Join": ["", [{Ref: 'MainAccessLogBucket'},"/Import/"]]}, - }, + LogFilePrefix: { 'Fn::Join': ['', [{ Ref: 'MainAccessLogBucket' }, '/Import/']] }, + }, PublicAccessBlockConfiguration: { BlockPublicAcls: true, BlockPublicPolicy: true, @@ -340,7 +340,7 @@ module.exports = { TestAllBucket: { Type: 'AWS::S3::Bucket', Metadata: { guard: util.cfnGuard('S3_BUCKET_NO_PUBLIC_RW_ACL') }, - DependsOn : ['MainAccessLogBucket', 'MainAccessLogsBucketPolicy'], + DependsOn: ['MainAccessLogBucket', 'MainAccessLogsBucketPolicy'], Properties: { LifecycleConfiguration: { Rules: [{ @@ -367,8 +367,8 @@ module.exports = { }, LoggingConfiguration: { DestinationBucketName: { Ref: 'MainAccessLogBucket' }, - LogFilePrefix: {"Fn::Join": ["", [{Ref: 'MainAccessLogBucket'},"/TestAll/"]]}, - }, + LogFilePrefix: { 'Fn::Join': ['', [{ Ref: 'MainAccessLogBucket' }, '/TestAll/']] }, + }, PublicAccessBlockConfiguration: { BlockPublicAcls: true, BlockPublicPolicy: true, @@ -430,4 +430,112 @@ module.exports = { }, }, }, + ContentDesignerOutputBucket: { + Type: 'AWS::S3::Bucket', + Metadata: { guard: util.cfnGuard('S3_BUCKET_NO_PUBLIC_RW_ACL') }, + DependsOn: ['MainAccessLogBucket', 'MainAccessLogsBucketPolicy'], + Properties: { + LifecycleConfiguration: { + Rules: [{ + ExpirationInDays: 1, + Status: 'Enabled', + }], + }, + VersioningConfiguration: { + Status: 'Enabled', + }, + CorsConfiguration: { + CorsRules: [{ + AllowedHeaders: ['*'], + AllowedMethods: ['GET'], + AllowedOrigins: ['*'], + }], + }, + BucketEncryption: { + ServerSideEncryptionConfiguration: [{ + ServerSideEncryptionByDefault: { + SSEAlgorithm: 'AES256', + }, + }], + }, + LoggingConfiguration: { + DestinationBucketName: { Ref: 'MainAccessLogBucket' }, + LogFilePrefix: { 'Fn::Join': ['', [{ Ref: 'MainAccessLogBucket' }, '/ContentDesignerOutput/']] }, + }, + PublicAccessBlockConfiguration: { + BlockPublicAcls: true, + BlockPublicPolicy: true, + IgnorePublicAcls: true, + RestrictPublicBuckets: true, + }, + }, + }, + HTTPSOnlyContentDesignerOutputBucketPolicy: { + Type: 'AWS::S3::BucketPolicy', + Properties: { + Bucket: { + Ref: 'ContentDesignerOutputBucket', + }, + PolicyDocument: { + Statement: [ + { + Action: '*', + Condition: { + Bool: { + 'aws:SecureTransport': 'false', + }, + }, + Effect: 'Deny', + Principal: '*', + Resource: [ + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'ContentDesignerOutputBucket', + 'Arn', + ], + }, + '/*', + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'ContentDesignerOutputBucket', + 'Arn', + ], + }, + ], + ], + }, + ], + Sid: 'HttpsOnly', + }, + ], + Version: '2012-10-17', + }, + }, + }, + ContentDesignerOutputClean: { + Type: 'Custom::S3Clean', + DependsOn: [ + 'CFNInvokePolicy', + ], + Properties: { + ServiceToken: { + 'Fn::GetAtt': [ + 'S3Clean', + 'Arn', + ], + }, + Bucket: { Ref: 'ContentDesignerOutputBucket' }, + }, + }, }; diff --git a/source/templates/master/cfn/index.js b/source/templates/master/cfn/index.js index 1ad8bfce3..bfd58c1be 100644 --- a/source/templates/master/cfn/index.js +++ b/source/templates/master/cfn/index.js @@ -16,6 +16,30 @@ const fs = require('fs'); const util = require('../../util'); module.exports = { + VersionLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-VersionLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, VersionLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -25,10 +49,13 @@ module.exports = { }, Environment: { Variables: { - ...util.getCommonEnvironmentVariables() + ...util.getCommonEnvironmentVariables(), }, }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'VersionLambdaLogGroup' }, + }, MemorySize: '3008', Role: { 'Fn::GetAtt': ['CFNLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -62,6 +89,30 @@ module.exports = { BuildDate: (new Date()).toISOString(), }, }, + CFNLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-CFNLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, CFNLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -77,10 +128,13 @@ module.exports = { }, Environment: { Variables: { - ...util.getCommonEnvironmentVariables() + ...util.getCommonEnvironmentVariables(), } }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'CFNLambdaLogGroup' }, + }, MemorySize: '3008', Role: { 'Fn::GetAtt': ['CFNLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, diff --git a/source/templates/master/examples.js b/source/templates/master/examples.js index 1dd09e02d..bd2dd5a7a 100644 --- a/source/templates/master/examples.js +++ b/source/templates/master/examples.js @@ -35,12 +35,12 @@ module.exports = { QIDLambdaArn: { 'Fn::GetAtt': ['ESQidLambda', 'Arn'] }, VPCSubnetIdList: { 'Fn::Join': [',', { Ref: 'VPCSubnetIdList' }] }, VPCSecurityGroupIdList: { 'Fn::Join': [',', { Ref: 'VPCSecurityGroupIdList' }] }, - LexBotVersion: { Ref: 'LexBotVersion' }, XraySetting: { Ref: 'XraySetting' }, DefaultQnABotSettings: { Ref: 'DefaultQnABotSettings' }, PrivateQnABotSettings: { Ref: 'PrivateQnABotSettings' }, InstallLexResponseBots: { Ref: 'InstallLexResponseBots' }, AwsSdkLayerLambdaLayer: { Ref: 'AwsSdkLayerLambdaLayer' }, + LogRetentionPeriod: { Ref: 'LogRetentionPeriod' }, }, }, }, diff --git a/source/templates/master/exportstack.js b/source/templates/master/exportstack.js index 29c1e6d9b..cbdedcf88 100644 --- a/source/templates/master/exportstack.js +++ b/source/templates/master/exportstack.js @@ -17,6 +17,7 @@ module.exports = { Properties: { TemplateURL: { 'Fn::Sub': 'https://${BootstrapBucket}.s3.${AWS::Region}.amazonaws.com/${BootstrapPrefix}/templates/export.json' }, Parameters: { + ContentDesignerOutputBucket: { Ref: 'ContentDesignerOutputBucket' }, CFNLambda: { 'Fn::GetAtt': ['CFNLambda', 'Arn'] }, CFNInvokePolicy: { Ref: 'CFNInvokePolicy' }, S3Clean: { 'Fn::GetAtt': ['S3Clean', 'Arn'] }, @@ -39,11 +40,7 @@ module.exports = { CustomQnABotSettings: { Ref: 'CustomQnABotSettings' }, AwsSdkLayerLambdaLayer: { Ref: 'AwsSdkLayerLambdaLayer' }, QnABotCommonLambdaLayer: { Ref: 'QnABotCommonLambdaLayer' }, - LexVersion: { 'Fn::If': ['CreateLexV1Bots', 'V1', 'V2'] }, - // Lex V1 - FallbackIntent: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'IntentFallback' }, 'LexV2Only_Mode'] }, - Intent: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'Intent' }, 'LexV2Only_Mode'] }, - BotName: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'LexBot' }, 'LexV2Only_Mode'] }, + LexVersion: 'V2', // Lex V2 LexV2BotName: { 'Fn::GetAtt': ['LexV2Bot', 'botName'] }, LexV2BotId: { 'Fn::GetAtt': ['LexV2Bot', 'botId'] }, @@ -52,6 +49,7 @@ module.exports = { LexV2BotLocaleIds: { 'Fn::GetAtt': ['LexV2Bot', 'botLocaleIds'] }, KendraFaqIndexId: { Ref: 'KendraFaqIndexId' }, KendraWebPageIndexId: { Ref: 'KendraWebPageIndexId' }, + LogRetentionPeriod: { Ref: 'LogRetentionPeriod' }, }, }, }, diff --git a/source/templates/master/importstack.js b/source/templates/master/importstack.js index 46590c4c9..f099692f0 100644 --- a/source/templates/master/importstack.js +++ b/source/templates/master/importstack.js @@ -18,6 +18,7 @@ module.exports = { Properties: { TemplateURL: { 'Fn::Sub': 'https://${BootstrapBucket}.s3.${AWS::Region}.amazonaws.com/${BootstrapPrefix}/templates/import.json' }, Parameters: { + ContentDesignerOutputBucket: { Ref: 'ContentDesignerOutputBucket' }, CFNLambda: { 'Fn::GetAtt': ['CFNLambda', 'Arn'] }, CFNInvokePolicy: { Ref: 'CFNInvokePolicy' }, S3Clean: { 'Fn::GetAtt': ['S3Clean', 'Arn'] }, @@ -59,6 +60,7 @@ module.exports = { ], }, EmbeddingsBedrockModelId: { 'Fn::FindInMap': ['BedrockDefaults', {'Ref' : 'EmbeddingsBedrockModelId'}, 'ModelID'] }, + LogRetentionPeriod: { Ref: 'LogRetentionPeriod' }, }, }, }, diff --git a/source/templates/master/index.js b/source/templates/master/index.js index f06fe77e6..d5c6109b5 100644 --- a/source/templates/master/index.js +++ b/source/templates/master/index.js @@ -70,41 +70,6 @@ module.exports = { ImportBucket: { Value: { Ref: 'ImportBucket' }, }, - BotConsoleUrl: { - Condition: 'CreateLexV1Bots', - Value: { - 'Fn::Join': [ - '', - [ - 'https://console.aws.amazon.com/lex/home?', - 'region=', - { Ref: 'AWS::Region' }, - '#bot-editor:bot=', - { Ref: 'LexBot' }, - ], - ], - }, - }, - LexV1BotName: { - Condition: 'CreateLexV1Bots', - Value: { Ref: 'LexBot' }, - }, - LexV1BotAlias: { - Condition: 'CreateLexV1Bots', - Value: { Ref: 'VersionAlias' }, - }, - LexV1SlotType: { - Condition: 'CreateLexV1Bots', - Value: { Ref: 'SlotType' }, - }, - LexV1Intent: { - Condition: 'CreateLexV1Bots', - Value: { Ref: 'Intent' }, - }, - LexV1IntentFallback: { - Condition: 'CreateLexV1Bots', - Value: { Ref: 'IntentFallback' }, - }, LexV2BotName: { Value: { 'Fn::GetAtt': ['LexV2Bot', 'botName'] }, }, @@ -231,6 +196,12 @@ module.exports = { MetricsBucket: { Value: { Ref: 'MetricsBucket' }, }, + TestAllBucket: { + Value: { Ref: 'TestAllBucket' }, + }, + ContentDesignerOutputBucket: { + Value: { Ref: 'ContentDesignerOutputBucket' }, + } }, Parameters: { OpenSearchName: { @@ -388,13 +359,6 @@ module.exports = { AllowedPattern: '[^ ]+', ConstraintDescription: 'Must be a valid comma separated list of Locale IDs', }, - LexBotVersion: { - Description: - 'Amazon Lex version to use for QnABot on AWS. Select \'LexV2 Only\' to install QnABot in AWS regions where LexV1 is not supported.', - Type: 'String', - AllowedValues: ['LexV1 and LexV2', 'LexV2 Only'], - Default: 'LexV2 Only', - }, InstallLexResponseBots: { Description: 'You can configure your chatbot to ask questions and process your end user\'s answers for surveys, quizzes,... (Elicit Response Feature). If the Elicit Response feature is not needed, choose \'false\' to skip the sample Lex Response Bot installation - see https://docs.aws.amazon.com/solutions/latest/qnabot-on-aws/configuring-the-chatbot-to-ask-the-questions-and-use-response-bots.html', @@ -429,6 +393,7 @@ module.exports = { 'Required when EmbeddingsApi is BEDROCK. Please ensure you have requested access to the LLMs in Bedrock console (https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html), before deploying.', AllowedValues: [ 'amazon.titan-embed-text-v1', + 'amazon.titan-embed-text-v2', 'cohere.embed-english-v3', 'cohere.embed-multilingual-v3', ], @@ -470,6 +435,7 @@ module.exports = { AllowedValues: [ 'amazon.titan-text-express-v1', 'amazon.titan-text-lite-v1', + 'amazon.titan-text-premier-v1', 'ai21.j2-ultra-v1', 'ai21.j2-mid-v1', 'anthropic.claude-instant-v1', @@ -494,10 +460,11 @@ module.exports = { Description: 'Required if BedrockKnowledgeBaseId is not empty. Sets the preferred LLM model to use with the Bedrock knowledge base. Please ensure you have requested access to the LLMs in Bedrock console (https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html), before deploying', AllowedValues: [ + 'amazon.titan-text-premier-v1', 'anthropic.claude-instant-v1', 'anthropic.claude-v2.1', 'anthropic.claude-3-sonnet-v1', - 'anthropic.claude-3-haiku-v1' + 'anthropic.claude-3-haiku-v1', ], Default: 'anthropic.claude-instant-v1', }, @@ -524,6 +491,15 @@ module.exports = { Default: '', ConstraintDescription: 'Must be a valid Lambda ARN or leave blank', }, + LogRetentionPeriod: { + Type: 'Number', + Description: 'Optional: The number of days to keep logs before expiring. If you would like your logs to never expire, leave this value as 0.', + Default: 0, + AllowedValues: [ + 0, 1, 3, 5, 7, 14 , 30 , 60 , 90 , 120 , 150 , 180 , 365 , 400 , 545 , 731 , 1096 , 1827 , 2192 , 2557 , 2922 , 3288 , 3653 + ], + MinValue: 0, + }, }, Conditions: { Public: { 'Fn::Equals': [{ Ref: 'PublicOrPrivate' }, 'PUBLIC'] }, @@ -534,7 +510,6 @@ module.exports = { BuildExamples: { 'Fn::Equals': [{ Ref: 'BuildExamples' }, 'TRUE'] }, CreateDomain: { 'Fn::Equals': [{ Ref: 'OpenSearchName' }, 'EMPTY'] }, DontCreateDomain: { 'Fn::Not': [{ 'Fn::Equals': [{ Ref: 'OpenSearchName' }, 'EMPTY'] }] }, - CreateLexV1Bots: { 'Fn::Equals': [{ Ref: 'LexBotVersion' }, 'LexV1 and LexV2'] }, VPCEnabled: { 'Fn::Not': [ { @@ -566,6 +541,7 @@ module.exports = { { 'Fn::Not': [{ 'Fn::Equals': [{ Ref: 'AltSearchKendraIndexes' }, ''] }] }, ], }, + LogRetentionPeriodIsNotZero: { 'Fn::Not': [{ 'Fn::Equals': [{ Ref: 'LogRetentionPeriod' }, 0] }] } }, Rules: { RequireLambdaArnForLambdaEmbeddingsApi: { @@ -584,8 +560,7 @@ module.exports = { }, Metadata: { 'AWS::CloudFormation::Interface': { - ParameterGroups: [ - { + ParameterGroups: [ { Label: { default: 'Step 2A: Set Basic Chatbot Parameters (required)', }, @@ -601,7 +576,6 @@ module.exports = { 'OpenSearchDashboardsRetentionMinutes', 'OpenSearchFineGrainAccessControl', 'LexV2BotLocaleIds', - 'LexBotVersion', 'InstallLexResponseBots', 'FulfillmentConcurrency', 'XraySetting', @@ -663,6 +637,7 @@ module.exports = { 'BootstrapBucket', 'BootstrapPrefix', 'BuildExamples', + 'LogRetentionPeriod' ], }, ], diff --git a/source/templates/master/lex-build/__tests__/start.test.js b/source/templates/master/lex-build/__tests__/start.test.js index 0b728741c..65e95be69 100644 --- a/source/templates/master/lex-build/__tests__/start.test.js +++ b/source/templates/master/lex-build/__tests__/start.test.js @@ -34,9 +34,8 @@ describe('lex poll', () => { process.env = { ...OLD_ENV }; }); - it('initializes lex v1 and v2 and updates s3', async () => { + it('initializes lex v2 and updates s3', async () => { process.env.STATUS_BUCKET = 'test-bucket'; - process.env.STATUS_KEY = 'test-key'; process.env.LEXV2_STATUS_KEY = 'test-status-key'; process.env.BUILD_FUNCTION = 'test-lambda'; @@ -50,14 +49,6 @@ describe('lex poll', () => { await handler({}, {}, mockCallback); expect(s3ClientMock).toHaveReceivedNthCommandWith(1, PutObjectCommand, { - Bucket: 'test-bucket', - Key: process.env.STATUS_KEY, - Body: JSON.stringify({ - status: 'Starting', - token: '', - }), - }); - expect(s3ClientMock).toHaveReceivedNthCommandWith(2, PutObjectCommand, { Bucket: 'test-bucket', Key: process.env.LEXV2_STATUS_KEY, Body: JSON.stringify({ diff --git a/source/templates/master/lex-build/index.js b/source/templates/master/lex-build/index.js index 901e7671c..8ffeb7297 100644 --- a/source/templates/master/lex-build/index.js +++ b/source/templates/master/lex-build/index.js @@ -15,6 +15,30 @@ const fs = require('fs'); const util = require('../../util'); module.exports = { + LexBuildLambdaLogGroup:{ + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-LexBuildLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, LexBuildLambda: lambda({ S3Bucket: { Ref: 'BootstrapBucket' }, S3Key: { 'Fn::Sub': '${BootstrapPrefix}/lambda/lex-build.zip' }, @@ -24,35 +48,84 @@ module.exports = { UTTERANCE_KEY: 'default-utterances.json', POLL_LAMBDA: { 'Fn::GetAtt': ['LexBuildLambdaPoll', 'Arn'] }, STATUS_BUCKET: { Ref: 'BuildStatusBucket' }, - STATUS_KEY: { 'Fn::If': ['CreateLexV1Bots', 'status.json', { Ref: 'AWS::NoValue' }] }, LEXV2_STATUS_KEY: 'lexV2status.json', - BOTNAME: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'LexBot' }, { Ref: 'AWS::NoValue' }] }, - BOTALIAS: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'VersionAlias' }, { Ref: 'AWS::NoValue' }] }, - SLOTTYPE: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'SlotType' }, { Ref: 'AWS::NoValue' }] }, - INTENT: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'Intent' }, { Ref: 'AWS::NoValue' }] }, - INTENTFALLBACK: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'IntentFallback' }, { Ref: 'AWS::NoValue' }] }, LEXV2_BUILD_LAMBDA: { Ref: 'Lexv2BotLambda' }, ADDRESS: { 'Fn::Join': ['', ['https://', { 'Fn::GetAtt': ['ESVar', 'ESAddress'] }]] }, INDEX: { 'Fn::GetAtt': ['Var', 'index'] }, - ...util.getCommonEnvironmentVariables() - }, process.env.npm_package_config_lambdaRuntime), + ...util.getCommonEnvironmentVariables(), + }, process.env.npm_package_config_lambdaRuntime, + { + LogGroup: { Ref: 'LexBuildLambdaLogGroup' }, + }, + ), + LexBuildLambdaStartLogGroup:{ + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-LexBuildLambdaStart' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, LexBuildLambdaStart: lambda({ ZipFile: fs.readFileSync(`${__dirname}/start.js`, 'utf8'), }, { STATUS_BUCKET: { Ref: 'BuildStatusBucket' }, - STATUS_KEY: { 'Fn::If': ['CreateLexV1Bots', 'status.json', { Ref: 'AWS::NoValue' }] }, LEXV2_STATUS_KEY: 'lexV2status.json', BUILD_FUNCTION: { 'Fn::GetAtt': ['LexBuildLambda', 'Arn'] }, - ...util.getCommonEnvironmentVariables() - }, process.env.npm_package_config_lambdaRuntime), + ...util.getCommonEnvironmentVariables(), + }, process.env.npm_package_config_lambdaRuntime, + { + LogGroup: { Ref: 'LexBuildLambdaStartLogGroup' }, + }), + LexBuildLambdaPollLogGroup:{ + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-LexBuildLambdaPoll' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, LexBuildLambdaPoll: lambda({ ZipFile: fs.readFileSync(`${__dirname}/poll.js`, 'utf8'), }, { - STATUS_KEY: { 'Fn::If': ['CreateLexV1Bots', 'status.json', { Ref: 'AWS::NoValue' }] }, STATUS_BUCKET: { Ref: 'BuildStatusBucket' }, - BOT_NAME: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'LexBot' }, { Ref: 'AWS::NoValue' }] }, - ...util.getCommonEnvironmentVariables() - }, process.env.npm_package_config_lambdaRuntime), + ...util.getCommonEnvironmentVariables(), + }, process.env.npm_package_config_lambdaRuntime, + { + LogGroup: { Ref: 'LexBuildLambdaPollLogGroup' }, + }), LexBuildCodeVersion: { Type: 'Custom::S3Version', Properties: { @@ -160,7 +233,7 @@ module.exports = { LoggingConfiguration: { DestinationBucketName: { Ref: 'MainAccessLogBucket' }, LogFilePrefix: {"Fn::Join": ["", [{Ref: 'MainAccessLogBucket'},"/BuildStatus/"]]}, - }, + }, BucketEncryption: { ServerSideEncryptionConfiguration: [{ ServerSideEncryptionByDefault: { @@ -201,7 +274,7 @@ module.exports = { '/*', ], ], - }, + }, { 'Fn::Join': [ '', @@ -214,7 +287,7 @@ module.exports = { }, ], ], - } + }, ], Sid: 'HttpsOnly', }, @@ -236,7 +309,7 @@ module.exports = { }, }; -function lambda(code, variable, runtime) { +function lambda(code, variable, runtime, loggingConfig) { return { Type: 'AWS::Lambda::Function', Properties: { @@ -245,6 +318,7 @@ function lambda(code, variable, runtime) { Variables: variable, }, Handler: 'index.handler', + LoggingConfig: loggingConfig, MemorySize: '1024', Role: { 'Fn::GetAtt': ['LexBuildLambdaRole', 'Arn'] }, Runtime: runtime, @@ -261,7 +335,7 @@ function lambda(code, variable, runtime) { }, Layers: [ { Ref: 'AwsSdkLayerLambdaLayer' }, - { Ref: 'CommonModulesLambdaLayer' } + { Ref: 'CommonModulesLambdaLayer' }, ], Tags: [{ Key: 'Type', diff --git a/source/templates/master/lex-build/start.js b/source/templates/master/lex-build/start.js index ef397f656..f038c5850 100644 --- a/source/templates/master/lex-build/start.js +++ b/source/templates/master/lex-build/start.js @@ -23,22 +23,10 @@ const crypto = require('crypto'); exports.handler = async function (event, context, callback) { const token = crypto.randomBytes(16).toString('base64'); const bucket = process.env.STATUS_BUCKET; - const lexV1StatusFile = process.env.STATUS_KEY; const lexV2StatusFile = process.env.LEXV2_STATUS_KEY; const functionName = process.env.BUILD_FUNCTION; const body = JSON.stringify({ status: 'Starting', token }); - if (lexV1StatusFile) { - console.log('Initializing ', bucket, lexV1StatusFile); - const params = { - Bucket: bucket, - Key: lexV1StatusFile, - Body: body, - }; - const putObjectCmdV1 = new PutObjectCommand(params); - await s3.send(putObjectCmdV1); - } - console.log('Initializing ', bucket, lexV2StatusFile); const params = { Bucket: bucket, @@ -48,7 +36,7 @@ exports.handler = async function (event, context, callback) { const putObjectCmdV2 = new PutObjectCommand(params); await s3.send(putObjectCmdV2); - // The BUILD_FUNCTION takes care of rebuilding Lex V2 bot, and (unless QnABot is set to V2 only) Lex V1 bot + // The BUILD_FUNCTION takes care of rebuilding Lex V2 bot console.log('Invoking ', functionName); const invokeParams = { FunctionName: functionName, diff --git a/source/templates/master/lex/bot.js b/source/templates/master/lex/bot.js index d7d1d9e39..ac5a38cdb 100644 --- a/source/templates/master/lex/bot.js +++ b/source/templates/master/lex/bot.js @@ -32,126 +32,6 @@ module.exports = { SourceAccount: { Ref: 'AWS::AccountId' }, }, }, - SlotType: { - Type: 'Custom::LexSlotType', - Condition: 'CreateLexV1Bots', - Properties: { - ServiceToken: { 'Fn::GetAtt': ['CFNLambda', 'Arn'] }, - createVersion: true, - description: `custom slot type ${qnabotversion}`, - enumerationValues: config.utterances.map((x) => ({ value: x })), - }, - }, - Intent: { - Type: 'Custom::LexIntent', - Condition: 'CreateLexV1Bots', - Properties: { - ServiceToken: { - 'Fn::GetAtt': ['CFNLambda', 'Arn'], - }, - prefix: 'fulfilment', - description: `custom intent ${qnabotversion}`, - createVersion: true, - sampleUtterances: [ - '{slot}', - ], - slots: [{ - name: 'slot', - slotType: { Ref: 'SlotType' }, - slotConstraint: 'Optional', - slotTypeVersion: 'QNABOT-AUTO-ASSIGNED', - priority: 1, - }, - ], - fulfillmentActivity: { - type: 'CodeHook', - codeHook: { - uri: { - 'Fn::Join': [':', [ - { 'Fn::GetAtt': ['FulfillmentLambda', 'Arn'] }, - 'live', - ]], - }, - messageVersion: '1.0', - }, - }, - }, - DependsOn: 'QNAInvokePermission', - }, - IntentFallback: { - Type: 'Custom::LexIntent', - Condition: 'CreateLexV1Bots', - Properties: { - ServiceToken: { - 'Fn::GetAtt': ['CFNLambda', 'Arn'], - }, - prefix: 'qnabotfallbackfulfilment', - description: `custom fallback intent ${qnabotversion}`, - createVersion: true, - fulfillmentActivity: { - type: 'CodeHook', - codeHook: { - uri: { - 'Fn::Join': [':', [ - { 'Fn::GetAtt': ['FulfillmentLambda', 'Arn'] }, - 'live', - ]], - }, - messageVersion: '1.0', - }, - }, - parentIntentSignature: 'AMAZON.FallbackIntent', - }, - DependsOn: 'QNAInvokePermission', - }, - LexBot: { - Type: 'Custom::LexBot', - Condition: 'CreateLexV1Bots', - Properties: { - ServiceToken: { - 'Fn::GetAtt': [ - 'CFNLambda', - 'Arn', - ], - }, - name: { 'Fn::Sub': '${AWS::StackName}-Bot' }, - description: `QnABot primary bot ${qnabotversion}`, - locale: 'en-US', - voiceId: config.voiceId, - childDirected: false, - createVersion: true, - intents: [ - { intentName: { Ref: 'Intent' } }, - { intentName: { Ref: 'IntentFallback' } }, - ], - abortStatement: { - messages: [ - { - content: config.Abort, - contentType: 'PlainText', - }, - ], - }, - }, - }, - VersionAlias: { - Type: 'Custom::LexAlias', - Condition: 'CreateLexV1Bots', - DependsOn: 'LexBot', - Properties: { - ServiceToken: { - 'Fn::GetAtt': [ - 'CFNLambda', - 'Arn', - ], - }, - botName: { - Ref: 'LexBot', - }, - name: 'live', - description: `QnABot live alias ${qnabotversion}`, - }, - }, LexV2Bot: { Type: 'Custom::LexV2Bot', Properties: { diff --git a/source/templates/master/lex/fulfillment.js b/source/templates/master/lex/fulfillment.js index 1b7878192..c1da1f7d5 100644 --- a/source/templates/master/lex/fulfillment.js +++ b/source/templates/master/lex/fulfillment.js @@ -34,7 +34,7 @@ module.exports = { ]], }, Principal: 'alexa-appkit.amazon.com', - SourceAccount: { Ref: 'AWS::AccountId' }, + SourceAccount: { Ref: 'AWS::AccountId' }, }, }, FulfillmentCodeVersion: { @@ -46,6 +46,30 @@ module.exports = { BuildDate: (new Date()).toISOString(), }, }, + FulfillmentLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-FulfillmentLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, FulfillmentLambda: { Type: 'AWS::Lambda::Function', DependsOn: 'FulfillmentCodeVersion', @@ -93,10 +117,13 @@ module.exports = { LLM_LAMBDA_ARN: { Ref: 'LLMLambdaArn' }, ...examples, ...responsebots, - ...util.getCommonEnvironmentVariables() + ...util.getCommonEnvironmentVariables(), }, }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'FulfillmentLambdaLogGroup' }, + }, Layers: [ { Ref: 'AwsSdkLayerLambdaLayer' }, { Ref: 'CommonModulesLambdaLayer' }, @@ -234,7 +261,6 @@ module.exports = { Statement: [{ Effect: 'Allow', Action: [ - 'lex:PostText', 'lex:RecognizeText', ], Resource: [ @@ -405,10 +431,18 @@ module.exports = { 'bedrock:InvokeModel', ], Resource: [ - { 'Fn::If': ['EmbeddingsBedrock', { 'Fn::Sub': 'arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/${EmbeddingsBedrockModelId}' }, { Ref: 'AWS::NoValue' }] }, - { 'Fn::If': ['LLMBedrock', { 'Fn::Sub': ['arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/${ModelId}', {'ModelId': { 'Fn::FindInMap': ['BedrockDefaults', {'Ref' : 'LLMBedrockModelId'}, 'ModelID'] }}] }, { Ref: 'AWS::NoValue' }] }, - { 'Fn::If': ['BedrockKnowledgeBaseEnable', { 'Fn::Sub': ['arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/${ModelId}', {'ModelId': { 'Fn::FindInMap': ['BedrockDefaults', {'Ref' : 'BedrockKnowledgeBaseModel'}, 'ModelID'] }}] }, { Ref: 'AWS::NoValue' }] }, + { 'Fn::If': ['EmbeddingsBedrock', { 'Fn::Sub': ['arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/${ModelId}', {ModelId: { 'Fn::FindInMap': ['BedrockDefaults', {Ref : 'EmbeddingsBedrockModelId'}, 'ModelID'] }}] }, { Ref: 'AWS::NoValue' }] }, + { 'Fn::If': ['LLMBedrock', { 'Fn::Sub': ['arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/${ModelId}', {ModelId: { 'Fn::FindInMap': ['BedrockDefaults', {Ref : 'LLMBedrockModelId'}, 'ModelID'] }}] }, { Ref: 'AWS::NoValue' }] }, + { 'Fn::If': ['BedrockKnowledgeBaseEnable', { 'Fn::Sub': ['arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/${ModelId}', {ModelId: { 'Fn::FindInMap': ['BedrockDefaults', {Ref : 'BedrockKnowledgeBaseModel'}, 'ModelID'] }}] }, { Ref: 'AWS::NoValue' }] }, + ], + }, + { + Sid: 'ApplyGuardrailsToLLMBedrock', // https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-permissions.html#guardrails-permissions-invoke + Effect: 'Allow', + Action: [ + 'bedrock:ApplyGuardrail', ], + Resource: [{ 'Fn::Sub': 'arn:${AWS::Partition}:bedrock:${AWS::Region}:${AWS::AccountId}:guardrail/*' }], }, ], }, @@ -432,6 +466,14 @@ module.exports = { ], Resource: { 'Fn::Sub': 'arn:${AWS::Partition}:bedrock:${AWS::Region}:${AWS::AccountId}:knowledge-base/${BedrockKnowledgeBaseId}' }, }, + { + Sid: 'ApplyGuardrailsToKnowledgeBase', // https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-permissions.html#guardrails-permissions-invoke + Effect: 'Allow', + Action: [ + 'bedrock:ApplyGuardrail', + ], + Resource: [{ 'Fn::Sub': 'arn:${AWS::Partition}:bedrock:${AWS::Region}:${AWS::AccountId}:guardrail/*' }], + }, ], }, }, @@ -472,6 +514,30 @@ module.exports = { BuildDate: (new Date()).toISOString(), }, }, + ESWarmerLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ESWarmerLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ESWarmerLambda: { DependsOn: ['ESWarmerCodeVersion'], Type: 'AWS::Lambda::Function', @@ -490,10 +556,13 @@ module.exports = { DEFAULT_SETTINGS_PARAM: { Ref: 'DefaultQnABotSettings' }, PRIVATE_SETTINGS_PARAM: { Ref: 'PrivateQnABotSettings' }, CUSTOM_SETTINGS_PARAM: { Ref: 'CustomQnABotSettings' }, - ...util.getCommonEnvironmentVariables() + ...util.getCommonEnvironmentVariables(), }, }, Handler: 'index.warmer', + LoggingConfig: { + LogGroup: { Ref: 'ESWarmerLambdaLogGroup' }, + }, MemorySize: '512', Role: { 'Fn::GetAtt': ['WarmerLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, diff --git a/source/templates/master/lexv2-build/index.js b/source/templates/master/lexv2-build/index.js index cbc3c75da..cedfb9ae7 100644 --- a/source/templates/master/lexv2-build/index.js +++ b/source/templates/master/lexv2-build/index.js @@ -14,6 +14,30 @@ const util = require('../../util'); module.exports = { + LexV2BotLambdaLogGroup:{ + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-LexV2BotLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, Lexv2BotLambda: lambda({ S3Bucket: { Ref: 'BootstrapBucket' }, S3Key: { 'Fn::Sub': '${BootstrapPrefix}/lambda/lexv2-build.zip' }, @@ -28,8 +52,11 @@ module.exports = { }, LOCALES: { Ref: 'LexV2BotLocaleIds' }, PYTHONPATH: '/var/task/py_modules:/var/runtime:/opt/python', - ...util.getCommonEnvironmentVariables() - }, process.env.npm_package_config_pythonRuntime), + ...util.getCommonEnvironmentVariables(), + }, process.env.npm_package_config_pythonRuntime, + { + LogGroup: { Ref: 'LexV2BotLambdaLogGroup' }, + }), Lexv2BotCodeVersion: { Type: 'Custom::S3Version', Properties: { @@ -142,7 +169,7 @@ module.exports = { }, }; -function lambda(code, variable, runtime) { +function lambda(code, variable, runtime, loggingConfig) { return { Type: 'AWS::Lambda::Function', Properties: { @@ -151,6 +178,7 @@ function lambda(code, variable, runtime) { Variables: variable, }, Handler: 'handler.handler', + LoggingConfig: loggingConfig, MemorySize: '1024', Role: { 'Fn::GetAtt': ['Lexv2BotLambdaRole', 'Arn'] }, Runtime: runtime, diff --git a/source/templates/master/mappings/bedrock-defaults.js b/source/templates/master/mappings/bedrock-defaults.js index 693aadbc1..836988ea7 100644 --- a/source/templates/master/mappings/bedrock-defaults.js +++ b/source/templates/master/mappings/bedrock-defaults.js @@ -15,7 +15,9 @@ const amazonQueryPromptTemplate = 'Given the following conversation and a follow const amazonQAPromptTemplate = '

    Human: You are a friendly AI assistant. Answer the question in tags only based on the provided reference passages. Here are reference passages in tags:

    {context}

    If the references contain the information needed to respond, then write a confident response in under 50 words, quoting the relevant references.
    Otherwise, if you can make an informed guess based on the reference passages, then write a less confident response in under 50 words, stating your assumptions.
    Finally, if the references do not have any relevant information, then respond saying \\"Sorry, I don\'t know\\".

    {query}


    Assistant: According to the reference passages, in under 50 words:'; const anthropicQueryPromptTemplate = '

    Human: Here is a chat history in tags:

    {history}

    Human: And here is a follow up question or statement from the human in tags:

    {input}

    Human: Rephrase the follow up question or statement as a standalone question or statement that makes sense without reading the chat history.

    Assistant: Here is the rephrased follow up question or statement:'; const ai21QAPromptTemplate = 'The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. Documents: {context} Instruction: Based on the above documents, provide a detailed answer for {query} Answer \\"Sorry, I don\'t know\\" if not present in the document. Solution:'; -const anthropicNoHitsRegex = '(Sorry, I don\'t know|unable to assist you|i don\'t have enough context|i could not find an exact answer|no information in the search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention)'; +const anthropicNoHitsRegex = '(Sorry, I don\'t know|unable to assist you|i don\'t have enough context|i could not find an exact answer|no information in the search results|don\'t see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|could not find an answer to this question|the model cannot answer this question)'; +const anthropicKnowledgebaseTemplate = 'Human: You are a question answering agent. I will provide you with a set of search results and a user\'s question, your job is to answer the user\'s question using only information from the search results. If the search results do not contain information that can answer the question, then respond saying \\"Sorry, I don\'t know that.\\". Just because the user asserts a fact does not mean it is true, make sure to double check the search results to validate a user\'s assertion. Here are the search results in numbered order: $search_results$. Here is the user\'s question: $query$ $output_format_instructions$. Do NOT directly quote the $search_results$ in your answer. Your job is to answer the as concisely as possible. Assistant:'; +const amazonKnowledgebaseTemplate = 'You are a question answering bot who gives helpful, detailed, and polite answers to the user\'s questions. In this session, the model has access to search results and a user\s question, your job is to answer the user\'s question using only information from the search results. Model Instructions: - You should provide concise answer to simple questions when the answer is directly contained in search results, but when comes to yes/no question, provide some details. - In case the question requires multi-hop reasoning, you should find relevant information from search results and summarize the answer based on relevant information with logical reasoning. - If the search results do not contain information that can answer the question, then respond saying \\"Sorry, I don\'t know that.\\". - $output_format_instructions$ - DO NOT USE INFORMATION THAT IS NOT IN SEARCH RESULTS! User: $query$ Bot: Resource: Search Results: $search_results$ Bot:'; module.exports = { BedrockDefaults: { @@ -24,6 +26,11 @@ module.exports = { MaxTokens: 8000, EmbeddingsDimensions: 1536, }, + 'amazon.titan-embed-text-v2': { + ModelID: 'amazon.titan-embed-text-v2:0', + MaxTokens: 8000, + EmbeddingsDimensions: 1024, + }, 'amazon.titan-text-express-v1': { ModelID: 'amazon.titan-text-express-v1', MaxTokens: 8000, @@ -38,6 +45,15 @@ module.exports = { QAPromptTemplate: amazonQAPromptTemplate, NoHitsRegex: anthropicNoHitsRegex, }, + 'amazon.titan-text-premier-v1': { + ModelID: 'amazon.titan-text-premier-v1:0', + MaxTokens: 32000, + maxTokenCount: 3072, + QueryPromptTemplate: amazonQueryPromptTemplate, + QAPromptTemplate: amazonQAPromptTemplate, + NoHitsRegex: anthropicNoHitsRegex, + KnowledgeBasePromptTemplate: amazonKnowledgebaseTemplate, + }, 'ai21.j2-ultra-v1': { ModelID: 'ai21.j2-ultra-v1', MaxTokens: 8191, @@ -58,6 +74,7 @@ module.exports = { QueryPromptTemplate: anthropicQueryPromptTemplate, QAPromptTemplate: amazonQAPromptTemplate, NoHitsRegex: anthropicNoHitsRegex, + KnowledgeBasePromptTemplate: anthropicKnowledgebaseTemplate, }, 'anthropic.claude-v2.1': { ModelID: 'anthropic.claude-v2:1', @@ -65,6 +82,7 @@ module.exports = { QueryPromptTemplate: anthropicQueryPromptTemplate, QAPromptTemplate: amazonQAPromptTemplate, NoHitsRegex: anthropicNoHitsRegex, + KnowledgeBasePromptTemplate: anthropicKnowledgebaseTemplate, }, 'anthropic.claude-3-haiku-v1': { ModelID: 'anthropic.claude-3-haiku-20240307-v1:0', @@ -72,6 +90,7 @@ module.exports = { QueryPromptTemplate: anthropicQueryPromptTemplate, QAPromptTemplate: amazonQAPromptTemplate, NoHitsRegex: anthropicNoHitsRegex, + KnowledgeBasePromptTemplate: anthropicKnowledgebaseTemplate, }, 'anthropic.claude-3-sonnet-v1': { ModelID: 'anthropic.claude-3-sonnet-20240229-v1:0', @@ -79,6 +98,7 @@ module.exports = { QueryPromptTemplate: anthropicQueryPromptTemplate, QAPromptTemplate: amazonQAPromptTemplate, NoHitsRegex: anthropicNoHitsRegex, + KnowledgeBasePromptTemplate: anthropicKnowledgebaseTemplate, }, 'cohere.command-text-v14': { ModelID: 'cohere.command-text-v14', @@ -87,13 +107,6 @@ module.exports = { QAPromptTemplate: amazonQAPromptTemplate, NoHitsRegex: anthropicNoHitsRegex, }, - 'cohere.command-light-text-v14': { - ModelID: 'cohere.command-light-text-v14', - MaxTokens: 4000, - QueryPromptTemplate: amazonQueryPromptTemplate, - QAPromptTemplate: amazonQAPromptTemplate, - NoHitsRegex: anthropicNoHitsRegex, - }, 'cohere.embed-english-v3': { ModelID: 'cohere.embed-english-v3', MaxTokens: 512, diff --git a/source/templates/master/opensearch/firehose.js b/source/templates/master/opensearch/firehose.js index 3393b9d2e..91f9919b8 100644 --- a/source/templates/master/opensearch/firehose.js +++ b/source/templates/master/opensearch/firehose.js @@ -17,7 +17,22 @@ module.exports = { FeedbackKinesisFirehoseLogGroup: { Type: 'AWS::Logs::LogGroup', Properties: { - LogGroupName: { 'Fn::Sub': '/aws/kinesisfirehose/${AWS::StackName}-FeedbackKinesisFirehose' } + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/kinesisfirehose/${AWS::StackName}-FeedbackKinesisFirehose' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, }, Metadata: { cfn_nag: { @@ -26,12 +41,9 @@ module.exports = { id: 'W86', reason: 'LogGroup is encrypted by default.', }, - { - id: 'W84', - reason: 'LogGroup needs to be retained indefinitely', - }, ], }, + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), }, }, FeedbackKinesisFirehoseStreamOpenSearch: { @@ -39,16 +51,16 @@ module.exports = { DependsOn: ['FeedbackKinesisFirehoseLogGroup'], Properties: { LogGroupName: { Ref: 'FeedbackKinesisFirehoseLogGroup' }, - LogStreamName: 'OpenSearchDestinationDelivery' - } + LogStreamName: 'OpenSearchDestinationDelivery', + }, }, FeedbackKinesisFirehoseStreamS3: { Type: 'AWS::Logs::LogStream', DependsOn: ['FeedbackKinesisFirehoseLogGroup'], Properties: { LogGroupName: { Ref: 'FeedbackKinesisFirehoseLogGroup' }, - LogStreamName: 'S3BackupDelivery' - } + LogStreamName: 'S3BackupDelivery', + }, }, FeedbackKinesisFirehose: { Type: 'AWS::KinesisFirehose::DeliveryStream', @@ -62,23 +74,23 @@ module.exports = { Properties: { DeliveryStreamType: 'DirectPut', DeliveryStreamEncryptionConfigurationInput: { - KeyType: 'AWS_OWNED_CMK' + KeyType: 'AWS_OWNED_CMK', }, AmazonopensearchserviceDestinationConfiguration: { BufferingHints: { IntervalInSeconds: 60, - SizeInMBs: 5 + SizeInMBs: 5, }, CloudWatchLoggingOptions: { Enabled: true, LogGroupName: { Ref: 'FeedbackKinesisFirehoseLogGroup' }, - LogStreamName: { Ref: 'FeedbackKinesisFirehoseStreamOpenSearch' } + LogStreamName: { Ref: 'FeedbackKinesisFirehoseStreamOpenSearch' }, }, DomainARN: { 'Fn::GetAtt': ['ESVar', 'ESArn'] }, IndexName: { 'Fn::Sub': '${Var.FeedbackIndex}' }, IndexRotationPeriod: 'NoRotation', RetryOptions: { - DurationInSeconds: 300 + DurationInSeconds: 300, }, RoleARN: { 'Fn::GetAtt': ['FirehoseESS3Role', 'Arn'] }, S3BackupMode: 'AllDocuments', @@ -87,15 +99,15 @@ module.exports = { CloudWatchLoggingOptions: { Enabled: true, LogGroupName: { Ref: 'FeedbackKinesisFirehoseLogGroup' }, - LogStreamName: { Ref: 'FeedbackKinesisFirehoseStreamS3' } + LogStreamName: { Ref: 'FeedbackKinesisFirehoseStreamS3' }, }, BufferingHints: { IntervalInSeconds: 60, - SizeInMBs: 5 + SizeInMBs: 5, }, Prefix: 'feedback/', CompressionFormat: 'UNCOMPRESSED', - RoleARN: { 'Fn::GetAtt': ['FirehoseESS3Role', 'Arn'] } + RoleARN: { 'Fn::GetAtt': ['FirehoseESS3Role', 'Arn'] }, }, TypeName: '', VpcConfiguration: { @@ -104,18 +116,33 @@ module.exports = { { RoleARN: { 'Fn::GetAtt': ['FirehoseESS3Role', 'Arn'] }, SubnetIds: { Ref: 'VPCSubnetIdList' }, - SecurityGroupIds: { Ref: 'VPCSecurityGroupIdList' } + SecurityGroupIds: { Ref: 'VPCSecurityGroupIdList' }, }, - { Ref: 'AWS::NoValue' } - ] - } + { Ref: 'AWS::NoValue' }, + ], + }, }, - } + }, }, GeneralKinesisFirehoseLogGroup: { Type: 'AWS::Logs::LogGroup', Properties: { - LogGroupName: { 'Fn::Sub': '/aws/kinesisfirehose/${AWS::StackName}-GeneralKinesisFirehose' } + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/kinesisfirehose/${AWS::StackName}-GeneralKinesisFirehose' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, }, Metadata: { cfn_nag: { @@ -124,27 +151,24 @@ module.exports = { id: 'W86', reason: 'LogGroup is encrypted by default.', }, - { - id: 'W84', - reason: 'LogGroup needs to be retained indefinitely', - }, ], }, + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), }, }, GeneralKinesisFirehoseStreamOpenSearch: { Type: 'AWS::Logs::LogStream', Properties: { LogGroupName: { Ref: 'GeneralKinesisFirehoseLogGroup' }, - LogStreamName: 'OpenSearchDestinationDelivery' - } + LogStreamName: 'OpenSearchDestinationDelivery', + }, }, GeneralKinesisFirehoseStreamS3: { Type: 'AWS::Logs::LogStream', Properties: { LogGroupName: { Ref: 'GeneralKinesisFirehoseLogGroup' }, - LogStreamName: 'S3BackupDelivery' - } + LogStreamName: 'S3BackupDelivery', + }, }, GeneralKinesisFirehose: { Type: 'AWS::KinesisFirehose::DeliveryStream', @@ -158,23 +182,23 @@ module.exports = { Properties: { DeliveryStreamType: 'DirectPut', DeliveryStreamEncryptionConfigurationInput: { - KeyType: 'AWS_OWNED_CMK' + KeyType: 'AWS_OWNED_CMK', }, AmazonopensearchserviceDestinationConfiguration: { BufferingHints: { IntervalInSeconds: 60, - SizeInMBs: 5 + SizeInMBs: 5, }, CloudWatchLoggingOptions: { Enabled: true, LogGroupName: { Ref: 'GeneralKinesisFirehoseLogGroup' }, - LogStreamName: { Ref: 'GeneralKinesisFirehoseStreamOpenSearch' } + LogStreamName: { Ref: 'GeneralKinesisFirehoseStreamOpenSearch' }, }, DomainARN: { 'Fn::GetAtt': ['ESVar', 'ESArn'] }, IndexName: { 'Fn::Sub': '${Var.MetricsIndex}' }, IndexRotationPeriod: 'NoRotation', RetryOptions: { - DurationInSeconds: 300 + DurationInSeconds: 300, }, RoleARN: { 'Fn::GetAtt': ['FirehoseESS3Role', 'Arn'] }, S3BackupMode: 'AllDocuments', @@ -183,15 +207,15 @@ module.exports = { CloudWatchLoggingOptions: { Enabled: true, LogGroupName: { Ref: 'GeneralKinesisFirehoseLogGroup' }, - LogStreamName: { Ref: 'GeneralKinesisFirehoseStreamS3' } + LogStreamName: { Ref: 'GeneralKinesisFirehoseStreamS3' }, }, Prefix: 'metrics/', BufferingHints: { IntervalInSeconds: 60, - SizeInMBs: 5 + SizeInMBs: 5, }, CompressionFormat: 'UNCOMPRESSED', - RoleARN: { 'Fn::GetAtt': ['FirehoseESS3Role', 'Arn'] } + RoleARN: { 'Fn::GetAtt': ['FirehoseESS3Role', 'Arn'] }, }, TypeName: '', VpcConfiguration: { @@ -200,13 +224,13 @@ module.exports = { { RoleARN: { 'Fn::GetAtt': ['FirehoseESS3Role', 'Arn'] }, SubnetIds: { Ref: 'VPCSubnetIdList' }, - SecurityGroupIds: { Ref: 'VPCSecurityGroupIdList' } + SecurityGroupIds: { Ref: 'VPCSecurityGroupIdList' }, }, - { Ref: 'AWS::NoValue' } - ] - } + { Ref: 'AWS::NoValue' }, + ], + }, }, - } + }, }, MetricsBucket: { Type: 'AWS::S3::Bucket', @@ -215,7 +239,7 @@ module.exports = { DeletionPolicy: 'Delete', Properties: { VersioningConfiguration: { - Status: 'Enabled' + Status: 'Enabled', }, BucketEncryption: { ServerSideEncryptionConfiguration: [{ @@ -226,27 +250,27 @@ module.exports = { }, LoggingConfiguration: { DestinationBucketName: { Ref: 'MainAccessLogBucket' }, - LogFilePrefix: { 'Fn::Join': ['', [{ Ref: 'MainAccessLogBucket' }, '/Metrics/']] } + LogFilePrefix: { 'Fn::Join': ['', [{ Ref: 'MainAccessLogBucket' }, '/Metrics/']] }, }, PublicAccessBlockConfiguration: { BlockPublicAcls: true, BlockPublicPolicy: true, IgnorePublicAcls: true, - RestrictPublicBuckets: true + RestrictPublicBuckets: true, }, Tags: [ { Key: 'Use', - Value: 'Metrics' - } - ] - } + Value: 'Metrics', + }, + ], + }, }, HTTPSOnlyMetricBucketsPolicy: { Type: 'AWS::S3::BucketPolicy', Properties: { Bucket: { - Ref: 'MetricsBucket' + Ref: 'MetricsBucket', }, PolicyDocument: { Statement: [ @@ -254,8 +278,8 @@ module.exports = { Action: '*', Condition: { Bool: { - 'aws:SecureTransport': 'false' - } + 'aws:SecureTransport': 'false', + }, }, Effect: 'Deny', Principal: '*', @@ -265,37 +289,37 @@ module.exports = { '', [ { - 'Fn::GetAtt': ['MetricsBucket', 'Arn'] + 'Fn::GetAtt': ['MetricsBucket', 'Arn'], }, - '/*' - ] - ] + '/*', + ], + ], }, { 'Fn::Join': [ '', [ { - 'Fn::GetAtt': ['MetricsBucket', 'Arn'] - } - ] - ] - } + 'Fn::GetAtt': ['MetricsBucket', 'Arn'], + }, + ], + ], + }, ], - Sid: 'HttpsOnly' - } + Sid: 'HttpsOnly', + }, ], - Version: '2012-10-17' - } - } + Version: '2012-10-17', + }, + }, }, MetricsBucketClean: { Type: 'Custom::S3Clean', DependsOn: ['CFNInvokePolicy', 'HTTPSOnlyMetricBucketsPolicy'], Properties: { ServiceToken: { 'Fn::GetAtt': ['S3Clean', 'Arn'] }, - Bucket: { Ref: 'MetricsBucket' } - } + Bucket: { Ref: 'MetricsBucket' }, + }, }, FirehoseESS3Role: { Type: 'AWS::IAM::Role', @@ -306,11 +330,11 @@ module.exports = { { Effect: 'Allow', Principal: { - Service: 'firehose.amazonaws.com' + Service: 'firehose.amazonaws.com', }, - Action: 'sts:AssumeRole' - } - ] + Action: 'sts:AssumeRole', + }, + ], }, Path: '/', Policies: [ @@ -327,12 +351,12 @@ module.exports = { 's3:GetObject', 's3:ListBucket', 's3:ListBucketMultipartUploads', - 's3:PutObject' + 's3:PutObject', ], Resource: [ { 'Fn::GetAtt': ['MetricsBucket', 'Arn'] }, - { 'Fn::Join': ['', [{ 'Fn::GetAtt': ['MetricsBucket', 'Arn'] }, '/*']] } - ] + { 'Fn::Join': ['', [{ 'Fn::GetAtt': ['MetricsBucket', 'Arn'] }, '/*']] }, + ], }, { Sid: 'FirehoseLambdaPermissions', @@ -347,11 +371,11 @@ module.exports = { { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, - ':function:%FIREHOSE_DEFAULT_FUNCTION%:%FIREHOSE_DEFAULT_VERSION%' - ] - ] - } - ] + ':function:%FIREHOSE_DEFAULT_FUNCTION%:%FIREHOSE_DEFAULT_VERSION%', + ], + ], + }, + ], }, { Sid: 'FirehoseOpenSearchDestinationPermissions', @@ -362,12 +386,12 @@ module.exports = { 'es:DescribeDomainConfig', 'es:ESHttpPost', 'es:ESHttpPut', - 'es:ESHttpGet' + 'es:ESHttpGet', ], Resource: [ { 'Fn::GetAtt': ['ESVar', 'ESArn'] }, - { 'Fn::Join': ['', [{ 'Fn::GetAtt': ['ESVar', 'ESArn'] }, '/*']] } - ] + { 'Fn::Join': ['', [{ 'Fn::GetAtt': ['ESVar', 'ESArn'] }, '/*']] }, + ], }, { Sid: 'FirehoseLogsPermissions', @@ -382,11 +406,11 @@ module.exports = { { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, - ':log-group:/aws/kinesisfirehose/*' - ] - ] - } - ] + ':log-group:/aws/kinesisfirehose/*', + ], + ], + }, + ], }, { Sid: 'FireHoseVPCConfiguration', // https://docs.aws.amazon.com/firehose/latest/APIReference/API_VpcConfigurationDescription.html @@ -399,19 +423,19 @@ module.exports = { 'ec2:DescribeNetworkInterfaces', 'ec2:CreateNetworkInterface', 'ec2:CreateNetworkInterfacePermission', - 'ec2:DeleteNetworkInterface' + 'ec2:DeleteNetworkInterface', ], - Resource: '*' // these actions cannot be bound to resources other than * - } - ] + Resource: '*', // these actions cannot be bound to resources other than * + }, + ], }, - PolicyName: 'QnAFirehose' - } - ] + PolicyName: 'QnAFirehose', + }, + ], }, Metadata: { cfn_nag: util.cfnNag(['W11']), guard: util.cfnGuard('IAM_NO_INLINE_POLICY_CHECK'), }, - } + }, }; diff --git a/source/templates/master/opensearch/info.js b/source/templates/master/opensearch/info.js index 98a09591a..200ad5ec0 100644 --- a/source/templates/master/opensearch/info.js +++ b/source/templates/master/opensearch/info.js @@ -24,6 +24,31 @@ module.exports = { name: { Ref: 'OpenSearchName' }, }, }, + ESInfoLambdaLogGroup:{ + Type: 'AWS::Logs::LogGroup', + Condition: 'DontCreateDomain', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ESInfoLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ESInfoLambda: { Type: 'AWS::Lambda::Function', Condition: 'DontCreateDomain', @@ -32,6 +57,9 @@ module.exports = { ZipFile: fs.readFileSync(`${__dirname}/handler.js`, 'utf-8'), }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'ESInfoLambdaLogGroup' }, + }, MemorySize: '128', Role: { 'Fn::GetAtt': ['ESProxyLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, diff --git a/source/templates/master/opensearch/proxy.js b/source/templates/master/opensearch/proxy.js index 6e09589e8..dca9bf632 100644 --- a/source/templates/master/opensearch/proxy.js +++ b/source/templates/master/opensearch/proxy.js @@ -14,6 +14,30 @@ const util = require('../../util'); module.exports = { + ESCFNProxyLambdaLogGroup:{ + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ESCFNProxyLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ESCFNProxyLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -36,6 +60,9 @@ module.exports = { { Ref: 'EsProxyLambdaLayer' }, { Ref: 'QnABotCommonLambdaLayer' }], Handler: 'resource.handler', + LoggingConfig: { + LogGroup: { Ref: 'ESCFNProxyLambdaLogGroup' }, + }, MemorySize: '1408', Role: { 'Fn::GetAtt': ['ESProxyLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -121,7 +148,7 @@ module.exports = { { 'Fn::If': [ 'EmbeddingsBedrock', - { 'Fn::FindInMap': ['BedrockDefaults', {'Ref' : 'EmbeddingsBedrockModelId'}, 'EmbeddingsDimensions'] }, + { 'Fn::FindInMap': ['BedrockDefaults', {Ref : 'EmbeddingsBedrockModelId'}, 'EmbeddingsDimensions'] }, 'INVALID EMBEDDINGS API - Cannot determine dimensions', ], }, diff --git a/source/templates/master/opensearch/updates.js b/source/templates/master/opensearch/updates.js index 60cfd4bcb..bc3d706cb 100644 --- a/source/templates/master/opensearch/updates.js +++ b/source/templates/master/opensearch/updates.js @@ -17,7 +17,14 @@ module.exports = { Type: 'AWS::Logs::LogGroup', Condition: 'FGACEnabled', Properties: { - LogGroupName: { 'Fn::Sub': '/aws/opensearch/${AWS::StackName}-${ESVar.ESDomain}' } + LogGroupName: { 'Fn::Sub': '/aws/opensearch/${AWS::StackName}-${ESVar.ESDomain}' }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' } + ] + }, }, Metadata: { cfn_nag: { @@ -25,13 +32,10 @@ module.exports = { { id: 'W86', reason: 'LogGroup is encrypted by default.', - }, - { - id: 'W84', - reason: 'LogGroup needs to be retained indefinitely', - }, + } ], }, + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), }, }, OpenSearchLogGroupResourcePolicy: { diff --git a/source/templates/master/policies.json b/source/templates/master/policies.json index 6c2540b40..638de6887 100644 --- a/source/templates/master/policies.json +++ b/source/templates/master/policies.json @@ -7,8 +7,6 @@ "Statement": [{ "Effect": "Allow", "Action": [ - "lex:PostContent", - "lex:PostText", "lex:RecognizeText", "lex:RecognizeUtterance" ], diff --git a/source/templates/master/proxy-es.js b/source/templates/master/proxy-es.js index 5b261c35a..8bbc67f6e 100644 --- a/source/templates/master/proxy-es.js +++ b/source/templates/master/proxy-es.js @@ -28,7 +28,30 @@ module.exports = { BuildDate: (new Date()).toISOString(), }, }, - + UtteranceLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-UtteranceLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, UtteranceLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -51,6 +74,9 @@ module.exports = { }, }, Handler: 'index.utterances', + LoggingConfig: { + LogGroup: { Ref: 'UtteranceLambdaLogGroup' }, + }, MemorySize: '1408', Role: { 'Fn::GetAtt': ['ESProxyLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -75,6 +101,30 @@ module.exports = { guard: util.cfnGuard('LAMBDA_CONCURRENCY_CHECK', 'LAMBDA_INSIDE_VPC'), }, }, + ESQidLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ESQidLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ESQidLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -91,10 +141,13 @@ module.exports = { Variables: { ES_INDEX: { 'Fn::GetAtt': ['Var', 'QnaIndex'] }, ES_ADDRESS: { 'Fn::GetAtt': ['ESVar', 'ESAddress'] }, - ...util.getCommonEnvironmentVariables() + ...util.getCommonEnvironmentVariables(), }, }, Handler: 'index.qid', + LoggingConfig: { + LogGroup: { Ref: 'ESQidLambdaLogGroup' }, + }, MemorySize: '1408', Role: { 'Fn::GetAtt': ['ESProxyLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -119,6 +172,30 @@ module.exports = { guard: util.cfnGuard('LAMBDA_CONCURRENCY_CHECK', 'LAMBDA_INSIDE_VPC'), }, }, + ESCleaningLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ESCleaningLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ESCleaningLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -141,6 +218,9 @@ module.exports = { }, }, Handler: 'index.cleanmetrics', + LoggingConfig: { + LogGroup: { Ref: 'ESCleaningLambdaLogGroup' }, + }, MemorySize: '1408', Role: { 'Fn::GetAtt': ['ESProxyLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -186,6 +266,30 @@ module.exports = { SourceArn: { 'Fn::GetAtt': ['ScheduledESCleaning', 'Arn'] }, }, }, + ESLoggingLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ESLoggingLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ESLoggingLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -202,10 +306,13 @@ module.exports = { Environment: { Variables: { FIREHOSE_NAME: { Ref: 'GeneralKinesisFirehose' }, - ...util.getCommonEnvironmentVariables() + ...util.getCommonEnvironmentVariables(), }, }, Handler: 'index.logging', + LoggingConfig: { + LogGroup: { Ref: 'ESLoggingLambdaLogGroup' }, + }, MemorySize: '1408', Role: { 'Fn::GetAtt': ['ESLoggingLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -230,6 +337,30 @@ module.exports = { guard: util.cfnGuard('LAMBDA_CONCURRENCY_CHECK', 'LAMBDA_INSIDE_VPC'), }, }, + ESQueryLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ESQueryLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ESQueryLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -244,7 +375,7 @@ module.exports = { PRIVATE_SETTINGS_PARAM: { Ref: 'PrivateQnABotSettings' }, CUSTOM_SETTINGS_PARAM: { Ref: 'CustomQnABotSettings' }, ...examples, - ...util.getCommonEnvironmentVariables() + ...util.getCommonEnvironmentVariables(), }, }, Layers: [{ Ref: 'AwsSdkLayerLambdaLayer' }, @@ -252,6 +383,9 @@ module.exports = { { Ref: 'EsProxyLambdaLayer' }, { Ref: 'QnABotCommonLambdaLayer' }], Handler: 'index.query', + LoggingConfig: { + LogGroup: { Ref: 'ESQueryLambdaLogGroup' }, + }, MemorySize: '1408', Role: { 'Fn::GetAtt': ['ESProxyLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -276,6 +410,30 @@ module.exports = { guard: util.cfnGuard('LAMBDA_CONCURRENCY_CHECK', 'LAMBDA_INSIDE_VPC'), }, }, + ESProxyLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ESProxyLambdaLogGroup' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ESProxyLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -306,10 +464,13 @@ module.exports = { ], }, EMBEDDINGS_LAMBDA_ARN: { Ref: 'EmbeddingsLambdaArn' }, - ...util.getCommonEnvironmentVariables() + ...util.getCommonEnvironmentVariables(), }, }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'ESProxyLambdaLogGroup' }, + }, MemorySize: '1408', Role: { 'Fn::GetAtt': ['ESProxyLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -466,7 +627,7 @@ module.exports = { 'bedrock:InvokeModel', ], Resource: [ - { 'Fn::Sub': 'arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/${EmbeddingsBedrockModelId}' }, + { 'Fn::If': ['EmbeddingsBedrock', { 'Fn::Sub': ['arn:${AWS::Partition}:bedrock:${AWS::Region}::foundation-model/${ModelId}', {'ModelId': { 'Fn::FindInMap': ['BedrockDefaults', {'Ref' : 'EmbeddingsBedrockModelId'}, 'ModelID'] }}] }, { Ref: 'AWS::NoValue' }] }, ], }, { Ref: 'AWS::NoValue' }, diff --git a/source/templates/master/proxy-lex/index.js b/source/templates/master/proxy-lex/index.js index e6813c548..4335ad286 100644 --- a/source/templates/master/proxy-lex/index.js +++ b/source/templates/master/proxy-lex/index.js @@ -15,6 +15,30 @@ const fs = require('fs'); const util = require('../../util'); module.exports = { + LexProxyLambdaLogGroup:{ + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-LexProxyLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, LexProxyLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -23,10 +47,13 @@ module.exports = { }, Environment: { Variables: { - ...util.getCommonEnvironmentVariables() - } + ...util.getCommonEnvironmentVariables(), + }, }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'LexProxyLambdaLogGroup' }, + }, MemorySize: '128', Role: { 'Fn::GetAtt': ['LexProxyLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -43,7 +70,7 @@ module.exports = { }, Layers: [ { Ref: 'AwsSdkLayerLambdaLayer' }, - { Ref: 'CommonModulesLambdaLayer' } + { Ref: 'CommonModulesLambdaLayer' }, ], Tags: [{ Key: 'Type', @@ -55,6 +82,30 @@ module.exports = { guard: util.cfnGuard('LAMBDA_CONCURRENCY_CHECK', 'LAMBDA_INSIDE_VPC'), }, }, + LexStatusLambdaLogGroup:{ + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-LexStatusLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, LexStatusLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -64,7 +115,6 @@ module.exports = { Environment: { Variables: { STATUS_BUCKET: { Ref: 'BuildStatusBucket' }, - STATUS_KEY: { 'Fn::If': ['CreateLexV1Bots', 'status.json', { Ref: 'AWS::NoValue' }] }, LEXV2_STATUS_KEY: 'lexV2status.json', FULFILLMENT_FUNCTION_ARN: { 'Fn::Join': [':', [ @@ -73,9 +123,6 @@ module.exports = { ]], }, FULFILLMENT_FUNCTION_ROLE: { Ref: 'FulfillmentLambdaRole' }, - LEXV1_BOT_NAME: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'LexBot' }, { Ref: 'AWS::NoValue' }] }, - LEXV1_INTENT: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'Intent' }, { Ref: 'AWS::NoValue' }] }, - LEXV1_INTENT_FALLBACK: { 'Fn::If': ['CreateLexV1Bots', { Ref: 'IntentFallback' }, { Ref: 'AWS::NoValue' }] }, LEXV2_BOT_NAME: { 'Fn::GetAtt': ['LexV2Bot', 'botName'] }, LEXV2_BOT_ID: { 'Fn::GetAtt': ['LexV2Bot', 'botId'] }, LEXV2_BOT_ALIAS: { 'Fn::GetAtt': ['LexV2Bot', 'botAlias'] }, @@ -83,10 +130,13 @@ module.exports = { LEXV2_INTENT: { 'Fn::GetAtt': ['LexV2Bot', 'botIntent'] }, LEXV2_INTENT_FALLBACK: { 'Fn::GetAtt': ['LexV2Bot', 'botIntentFallback'] }, LEXV2_BOT_LOCALE_IDS: { 'Fn::GetAtt': ['LexV2Bot', 'botLocaleIds'] }, - ...util.getCommonEnvironmentVariables() + ...util.getCommonEnvironmentVariables(), }, }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'LexStatusLambdaLogGroup' }, + }, MemorySize: '128', Role: { 'Fn::GetAtt': ['LexProxyLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, diff --git a/source/templates/master/proxy-lex/status.js b/source/templates/master/proxy-lex/status.js index 6bdb03b8b..54095c4d6 100644 --- a/source/templates/master/proxy-lex/status.js +++ b/source/templates/master/proxy-lex/status.js @@ -26,9 +26,6 @@ function getStatusResponse(response, build) { lambdaArn: process.env.FULFILLMENT_FUNCTION_ARN, lambdaRole: process.env.FULFILLMENT_FUNCTION_ROLE, botversion: 'live', - botname: process.env.LEXV1_BOT_NAME || 'LEX V1 Bot not installed', - intent: process.env.LEXV1_INTENT || 'LEX V1 Bot not installed', - intentFallback: process.env.LEXV1_INTENT_FALLBACK || 'LEX V1 Bot not installed', lexV2botname: process.env.LEXV2_BOT_NAME || 'LEX V2 Bot not installed', lexV2botid: process.env.LEXV2_BOT_ID || 'LEX V2 Bot not installed', lexV2botalias: process.env.LEXV2_BOT_ALIAS || 'LEX V2 Bot not installed', @@ -46,7 +43,6 @@ exports.handler = async (event, context, callback) => { console.log('Received event:', JSON.stringify(event, null, 2)); const bucket = process.env.STATUS_BUCKET; - const lexV1StatusFile = process.env.STATUS_KEY; const lexV2StatusFile = process.env.LEXV2_STATUS_KEY; let build = { status: 'READY', token: 'token' }; let response; @@ -56,16 +52,6 @@ exports.handler = async (event, context, callback) => { response = await s3.send(getObjCmd); const readableStreamV2 = Buffer.concat(await response.Body.toArray()); build = JSON.parse(readableStreamV2); - // combine build status with v1 bot, if defined.. If both are READY then status is READY - if (lexV1StatusFile) { - const getObjCmd = new GetObjectCommand({ Bucket: bucket, Key: lexV1StatusFile }); - response = await s3.send(getObjCmd); - const readableStreamV2 = Buffer.concat(await response.Body.toArray()); - const v1build = JSON.parse(readableStreamV2); - if (v1build.status != 'READY' || build.status != 'READY') { - build.status = `LEX V2: ${build.status} / LEX V1: ${v1build.status}`; - } - } } catch (e) { console.log('Unable to read S3 lex bot status file - perhaps it doesn\'t yet exist. Returning READY'); } @@ -74,7 +60,6 @@ exports.handler = async (event, context, callback) => { botId: process.env.LEXV2_BOT_ID, }); response = await lexv2.send(describeBotCmd); - // Match LexV1 bot status for code compatibility (Available = READY) const statusResponse = getStatusResponse(response, build); return statusResponse; }; diff --git a/source/templates/master/roles.json b/source/templates/master/roles.json index 878692387..b25ba83de 100644 --- a/source/templates/master/roles.json +++ b/source/templates/master/roles.json @@ -185,7 +185,10 @@ "Fn::Sub": "arn:aws:s3:::${ExportBucket}/data/*" }, { - "Fn::Sub": "arn:aws:s3:::${TestAllBucket}/data/*" + "Fn::Sub": "arn:aws:s3:::${ContentDesignerOutputBucket}/data-testall/*" + }, + { + "Fn::Sub": "arn:aws:s3:::${ContentDesignerOutputBucket}/data-export/*" } ] }, @@ -220,6 +223,17 @@ "Fn::Sub": "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${CustomQnABotSettings}" } ] + }, + { + "Effect": "Allow", + "Action": [ + "lambda:InvokeFunction" + ], + "Resource": [ + { + "Fn::Sub": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${SolutionHelper}" + } + ] } ] } diff --git a/source/templates/master/routes/examples/index.js b/source/templates/master/routes/examples/index.js index 02ba2d585..f1364e421 100644 --- a/source/templates/master/routes/examples/index.js +++ b/source/templates/master/routes/examples/index.js @@ -82,6 +82,30 @@ module.exports = { }, authorization: 'AWS_IAM', }), + ExampleS3ListLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ExampleS3ListLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ExampleS3ListLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -94,6 +118,9 @@ module.exports = { } }, Handler: 'index.documents', + LoggingConfig: { + LogGroup: { Ref: 'ExampleS3ListLambdaLogGroup' }, + }, MemorySize: '128', Role: { 'Fn::GetAtt': ['S3ListLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -121,6 +148,30 @@ module.exports = { guard: util.cfnGuard('LAMBDA_CONCURRENCY_CHECK', 'LAMBDA_INSIDE_VPC'), }, }, + ExampleS3ListPhotoLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-ExampleS3ListPhotoLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, ExampleS3ListPhotoLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -133,6 +184,9 @@ module.exports = { } }, Handler: 'index.photos', + LoggingConfig: { + LogGroup: { Ref: 'ExampleS3ListPhotoLambdaLogGroup' }, + }, MemorySize: '128', Role: { 'Fn::GetAtt': ['S3ListLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, diff --git a/source/templates/master/routes/jobs/export-start.vm b/source/templates/master/routes/jobs/export-start.vm index e95d9d4cb..8652cc541 100644 --- a/source/templates/master/routes/jobs/export-start.vm +++ b/source/templates/master/routes/jobs/export-start.vm @@ -6,7 +6,7 @@ "id":"$input.params('proxy')", "config":"status/$input.params('proxy')", "tmp":"tmp/$input.params('proxy')", - "key":"$inputRoot.get('prefix')data/$input.params('proxy')", + "key":"$inputRoot.get('prefix')data-export/$input.params('proxy')", "filter":"$inputRoot.get('filter')", "status":"Started" } \ No newline at end of file diff --git a/source/templates/master/routes/jobs/index.js b/source/templates/master/routes/jobs/index.js index e93ad42e5..66c8d4f34 100644 --- a/source/templates/master/routes/jobs/index.js +++ b/source/templates/master/routes/jobs/index.js @@ -44,7 +44,7 @@ module.exports = { auth: 'AWS_IAM', method: 'PUT', bucket: { Ref: 'TestAllBucket' }, - path: '/status/{proxy}', + path: '/status-testall/{proxy}', template: fs.readFileSync(`${__dirname}/testall-start.vm`, 'utf-8'), requestParams: { 'integration.request.path.proxy': 'method.request.path.proxy', @@ -54,8 +54,8 @@ module.exports = { resource: { Ref: 'testall' }, auth: 'AWS_IAM', method: 'GET', - bucket: { Ref: 'TestAllBucket' }, - path: '/status/{proxy}', + bucket: { Ref: 'ContentDesignerOutputBucket' }, + path: '/status-testall/{proxy}', requestParams: { 'integration.request.path.proxy': 'method.request.path.proxy', }, @@ -64,8 +64,8 @@ module.exports = { resource: { Ref: 'testall' }, auth: 'AWS_IAM', method: 'delete', - bucket: { Ref: 'TestAllBucket' }, - path: '/status/{proxy}', + bucket: { Ref: 'ContentDesignerOutputBucket' }, + path: '/status-testall/{proxy}', requestParams: { 'integration.request.path.proxy': 'method.request.path.proxy', }, @@ -89,7 +89,7 @@ module.exports = { auth: 'AWS_IAM', method: 'PUT', bucket: { Ref: 'ExportBucket' }, - path: '/status/{proxy}', + path: '/status-export/{proxy}', template: fs.readFileSync(`${__dirname}/export-start.vm`, 'utf-8'), requestParams: { 'integration.request.path.proxy': 'method.request.path.proxy', @@ -99,8 +99,8 @@ module.exports = { resource: { Ref: 'export' }, auth: 'AWS_IAM', method: 'GET', - bucket: { Ref: 'ExportBucket' }, - path: '/status/{proxy}', + bucket: { Ref: 'ContentDesignerOutputBucket' }, + path: '/status-export/{proxy}', requestParams: { 'integration.request.path.proxy': 'method.request.path.proxy', }, @@ -109,7 +109,7 @@ module.exports = { resource: { Ref: 'export' }, auth: 'AWS_IAM', method: 'delete', - bucket: { Ref: 'ExportBucket' }, + bucket: { Ref: 'ContentDesignerOutputBucket' }, path: '/status/{proxy}', requestParams: { 'integration.request.path.proxy': 'method.request.path.proxy', @@ -131,8 +131,8 @@ module.exports = { resource: { Ref: 'import' }, auth: 'AWS_IAM', method: 'get', - bucket: { Ref: 'ImportBucket' }, - path: '/status/{proxy}', + bucket: { Ref: 'ContentDesignerOutputBucket' }, + path: '/status-import/{proxy}', requestParams: { 'integration.request.path.proxy': 'method.request.path.proxy', }, @@ -141,12 +141,36 @@ module.exports = { resource: { Ref: 'import' }, auth: 'AWS_IAM', method: 'delete', - bucket: { Ref: 'ImportBucket' }, - path: '/status/{proxy}', + bucket: { Ref: 'ContentDesignerOutputBucket' }, + path: '/status-import/{proxy}', requestParams: { 'integration.request.path.proxy': 'method.request.path.proxy', }, }), + S3ListLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-S3ListLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, S3ListLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -159,6 +183,9 @@ module.exports = { } }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'S3ListLambdaLogGroup' }, + }, MemorySize: '128', Role: { 'Fn::GetAtt': ['S3ListLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, diff --git a/source/templates/master/routes/jobs/list-export.vm b/source/templates/master/routes/jobs/list-export.vm index e9c5a1b3a..237c10ff2 100644 --- a/source/templates/master/routes/jobs/list-export.vm +++ b/source/templates/master/routes/jobs/list-export.vm @@ -1,8 +1,8 @@ #set ($root="https://${!context.domainName}/${!context.stage}") { - "bucket":"${ExportBucket}", - "prefix":"status/", + "bucket":"${ContentDesignerOutputBucket}", + "prefix":"status-export/", "perpage":"$input.params('perpage')", "token":"$input.params('token')", "type":"exports", diff --git a/source/templates/master/routes/jobs/list-testall.vm b/source/templates/master/routes/jobs/list-testall.vm index 9db48677d..2d291050a 100644 --- a/source/templates/master/routes/jobs/list-testall.vm +++ b/source/templates/master/routes/jobs/list-testall.vm @@ -1,8 +1,8 @@ #set ($root="https://${!context.domainName}/${!context.stage}") { - "bucket":"${TestAllBucket}", - "prefix":"status/", + "bucket":"${ContentDesignerOutputBucket}", + "prefix":"status-testall/", "perpage":"$input.params('perpage')", "token":"$input.params('token')", "type":"testall", diff --git a/source/templates/master/routes/jobs/list.vm b/source/templates/master/routes/jobs/list.vm index 577a485ce..66f3049df 100644 --- a/source/templates/master/routes/jobs/list.vm +++ b/source/templates/master/routes/jobs/list.vm @@ -1,8 +1,8 @@ #set ($root="https://${!context.domainName}/${!context.stage}") { - "bucket":"${ImportBucket}", - "prefix":"status/", + "bucket":"${ContentDesignerOutputBucket}", + "prefix":"status-import/", "perpage":"$input.params('perpage')", "token":"$input.params('token')", "type":"imports", diff --git a/source/templates/master/routes/jobs/testall-start.vm b/source/templates/master/routes/jobs/testall-start.vm index dafbafff3..c401a2ce2 100644 --- a/source/templates/master/routes/jobs/testall-start.vm +++ b/source/templates/master/routes/jobs/testall-start.vm @@ -4,9 +4,9 @@ "bucket":"${TestAllBucket}", "index":"${Var.QnaIndex}", "id":"$input.params('proxy')", - "config":"status/$input.params('proxy')", - "tmp":"tmp/$input.params('proxy')", - "key":"data/$input.params('proxy')", + "config":"status-testall/$input.params('proxy')", + "tmp":"tmp-testall/$input.params('proxy')", + "key":"data-testall/$input.params('proxy')", "filter":"$inputRoot.get('filter')", "token":"$inputRoot.get('token')", "locale":"$inputRoot.get('locale')", diff --git a/source/templates/master/routes/root/info.vm b/source/templates/master/routes/root/info.vm index 89e2db808..f5ca6ce37 100644 --- a/source/templates/master/routes/root/info.vm +++ b/source/templates/master/routes/root/info.vm @@ -18,6 +18,7 @@ "PrivateQnABotSettings":"${PrivateQnABotSettings}", "CustomQnABotSettings":"${CustomQnABotSettings}", "KendraCrawlerSnsTopic":"${KendraCrawlerSnsTopic}", + "SolutionHelper": "${SolutionHelper}", "Id":"$stageVariables.Id", "_links":{ "root":{ diff --git a/source/templates/master/s3-clean/index.js b/source/templates/master/s3-clean/index.js index db423e15a..c06cbac06 100644 --- a/source/templates/master/s3-clean/index.js +++ b/source/templates/master/s3-clean/index.js @@ -22,6 +22,30 @@ module.exports = { BuildDate: (new Date()).toISOString(), }, }, + S3CleanLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-S3CleanLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, S3Clean: { Type: 'AWS::Lambda::Function', Metadata: { guard: util.cfnGuard('LAMBDA_CONCURRENCY_CHECK', 'LAMBDA_INSIDE_VPC') }, @@ -32,11 +56,14 @@ module.exports = { }, Environment: { Variables: { - ...util.getCommonEnvironmentVariables() + ...util.getCommonEnvironmentVariables(), }, }, Description: 'This function clears all S3 objects from the bucket of a given S3-based resource', Handler: 'lambda_function.handler', + LoggingConfig: { + LogGroup: { Ref: 'S3CleanLambdaLogGroup' }, + }, Role: { 'Fn::GetAtt': ['CFNLambdaRole', 'Arn'], }, diff --git a/source/templates/master/s3.js b/source/templates/master/s3.js index e121f6a2b..adc5b7bf1 100644 --- a/source/templates/master/s3.js +++ b/source/templates/master/s3.js @@ -102,6 +102,7 @@ module.exports = { { 'Fn::Sub': 'arn:aws:s3:::${TestAllBucket}/*' }, { 'Fn::Sub': 'arn:aws:s3:::${Bucket}/*' }, { 'Fn::Sub': 'arn:aws:s3:::${AssetBucket}/*' }, + { 'Fn::Sub': 'arn:aws:s3:::${ContentDesignerOutputBucket}/*' }, ], }, { Effect: 'Allow', @@ -111,6 +112,7 @@ module.exports = { Resource: [ { 'Fn::Sub': 'arn:aws:s3:::${ExportBucket}/*' }, { 'Fn::Sub': 'arn:aws:s3:::${TestAllBucket}/*' }, + { 'Fn::Sub': 'arn:aws:s3:::${ContentDesignerOutputBucket}/*' }, ], }, { Effect: 'Allow', @@ -121,6 +123,7 @@ module.exports = { { 'Fn::Sub': 'arn:aws:s3:::${ImportBucket}/*' }, { 'Fn::Sub': 'arn:aws:s3:::${ExportBucket}/*' }, { 'Fn::Sub': 'arn:aws:s3:::${TestAllBucket}/*' }, + { 'Fn::Sub': 'arn:aws:s3:::${ContentDesignerOutputBucket}/*' }, ], }, ], diff --git a/source/templates/master/schemaLambda.js b/source/templates/master/schemaLambda.js index 1432e8890..bf79f1c9f 100644 --- a/source/templates/master/schemaLambda.js +++ b/source/templates/master/schemaLambda.js @@ -23,6 +23,30 @@ module.exports = { BuildDate: (new Date()).toISOString(), }, }, + SchemaLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-SchemaLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, SchemaLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -32,6 +56,9 @@ module.exports = { S3ObjectVersion: { Ref: 'SchemaLambdaCodeVersion' }, }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'SchemaLambdaLogGroup' }, + }, MemorySize: '128', Role: { 'Fn::GetAtt': ['SchemaLambdaRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, diff --git a/source/templates/master/settings.js b/source/templates/master/settings.js index b018473cd..8aececd65 100644 --- a/source/templates/master/settings.js +++ b/source/templates/master/settings.js @@ -112,6 +112,13 @@ const defaultSettings = { KNOWLEDGE_BASE_SHOW_REFERENCES: 'true', // Enables the knowledge base to provide full-text references to the sources the knowledge base generated text from KNOWLEDGE_BASE_S3_SIGNED_URLS: 'true', // Enables the knowledge base to provide signed URLs for the knowledge base documents. KNOWLEDGE_BASE_S3_SIGNED_URL_EXPIRE_SECS: 300, // The number of seconds the signed URL will be valid for. + KNOWLEDGE_BASE_PROMPT_TEMPLATE: '${KNOWLEDGE_BASE_PROMPT_TEMPLATE}', // The template used to construct a prompt that is sent to the model for response generation. + KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS: '', // Sets maximum number of retrieved result where each result corresponds to a source chunk. When querying a knowledge base, Amazon Bedrock returns up to five results by default. + KNOWLEDGE_BASE_SEARCH_TYPE: 'DEFAULT', // Select the search type which defines how data sources in the knowledge base are queried. If using an Amazon OpenSearch Serverless vector store that contains a filterable text field, you can specify whether to query the knowledge base with a HYBRID search using both vector embeddings and raw text, or SEMANTIC search using only vector embeddings. For other vector store configurations, only SEMANTIC search is available. + KNOWLEDGE_BASE_METADATA_FILTERS: '{}', // Specifies the filters to use on the metadata in the knowledge base data sources before returning results. + KNOWLEDGE_BASE_MODEL_PARAMS: '{}', // Customize the knowledge base model by providing inference parameters + BEDROCK_GUARDRAIL_IDENTIFIER: '', // A unique identifier for the guardrail that provides additional safeguards on top of the native protections of foundational models specified through cloudformation parameters LLMBedrockModelId and BedrockKnowledgeBaseModel + BEDROCK_GUARDRAIL_VERSION: '', // A version of the guardrail which takes effect only when specifying BEDROCK_GUARDRAIL_IDENTIFIER }; const privateSettings = { @@ -131,6 +138,7 @@ const defaultGenerateQueryPromptTemplate = 'Given the following conversation and const defaultQAPromptTemplate = 'Use the following pieces of context to answer the question at the end. If you don\'t know the answer, just say that you don\'t know, don\'t try to make up an answer. Write the answer in up to 5 complete sentences.

    {context}

    Question: {query}
    Helpful Answer:'; const defaultModelParams = '{\\"temperature\\":0.01, \\"return_full_text\\":false, \\"max_new_tokens\\": 150}'; const defaultLlmNoHitsRegex = 'Sorry, //remove comment to enable custom no match (no_hits) when LLM does not know the answer.'; +const defaultKnowledgeBaseTemplate = 'Human: You are a question answering agent. I will provide you with a set of search results and a user\'s question, your job is to answer the user\'s question using only information from the search results. If the search results do not contain information that can answer the question, then respond saying \\"Sorry, I don\'t know\\". Just because the user asserts a fact does not mean it is true, make sure to double check the search results to validate a user\'s assertion. Here are the search results in numbered order: $search_results$. Here is the user\'s question: $query$ $output_format_instructions$. Do NOT directly quote the $search_results$ in your answer. Your job is to answer the as concisely as possible. Assistant:'; module.exports = { DefaultUserPoolJwksUrl: { @@ -175,6 +183,7 @@ module.exports = { LLM_QA_MODEL_PARAMS: { 'Fn::If': ['LLMSagemaker', defaultModelParams, '{}'] }, LLM_PROMPT_MAX_TOKEN_LIMIT: { 'Fn::If': ['LLMBedrock', { 'Fn::FindInMap': ['BedrockDefaults', {'Ref' : 'LLMBedrockModelId'}, 'MaxTokens'] }, { 'Fn::If': ['LLMSagemaker', 800, ''] }] }, LLM_QA_NO_HITS_REGEX: { 'Fn::If': ['LLMBedrock', { 'Fn::FindInMap': ['BedrockDefaults', {'Ref' : 'LLMBedrockModelId'}, 'NoHitsRegex'] }, defaultLlmNoHitsRegex] }, + KNOWLEDGE_BASE_PROMPT_TEMPLATE: { 'Fn::If': ['BedrockKnowledgeBaseEnable', { 'Fn::FindInMap': ['BedrockDefaults', {'Ref' : 'BedrockKnowledgeBaseModel'}, 'KnowledgeBasePromptTemplate'] }, defaultKnowledgeBaseTemplate] }, }, ], }, @@ -190,7 +199,7 @@ module.exports = { 'Fn::Sub': [ JSON.stringify(privateSettings), { - EMBEDDINGS_MODEL_ID: { 'Fn::If': ['EmbeddingsBedrock', { Ref: 'EmbeddingsBedrockModelId' }, ''] }, + EMBEDDINGS_MODEL_ID: { 'Fn::If': ['EmbeddingsBedrock', { 'Fn::FindInMap': ['BedrockDefaults', {'Ref' : 'EmbeddingsBedrockModelId'}, 'ModelID'] }, ''] }, LLM_MODEL_ID: { 'Fn::If': ['LLMBedrock', { 'Fn::FindInMap': ['BedrockDefaults', {'Ref' : 'LLMBedrockModelId'}, 'ModelID'] }, ''] }, KNOWLEDGE_BASE_MODEL_ID: { 'Fn::If': ['BedrockKnowledgeBaseEnable', { 'Fn::FindInMap': ['BedrockDefaults', {'Ref' : 'BedrockKnowledgeBaseModel'}, 'ModelID'] }, ''] }, KNOWLEDGE_BASE_ID: { 'Fn::If': ['BedrockKnowledgeBaseEnable', {'Ref' : 'BedrockKnowledgeBaseId'}, ''] }, @@ -204,6 +213,15 @@ module.exports = { Properties: { Description: 'Custom QnABot Settings - Modify to override defaults, or to add new settings', Type: 'String', + Tier: 'Advanced', + Value: '{}', + }, + }, + SolutionHelperParameter: { + Type: 'AWS::SSM::Parameter', + Properties: { + Description: 'Solution Helper Parameter - DO NOT MODIFY', + Type: 'String', Value: '{}', }, }, diff --git a/source/templates/master/signup/index.js b/source/templates/master/signup/index.js index 74c671d6a..448d42673 100644 --- a/source/templates/master/signup/index.js +++ b/source/templates/master/signup/index.js @@ -33,6 +33,31 @@ module.exports = { SourceArn: { 'Fn::GetAtt': ['UserPool', 'Arn'] }, }, }, + MessageLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-MessageLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, MessageLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -40,6 +65,9 @@ module.exports = { ZipFile: fs.readFileSync(`${__dirname}/message.js`, 'utf8'), }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'MessageLambdaLogGroup' }, + }, MemorySize: '128', Environment: { Variables: { @@ -84,6 +112,30 @@ module.exports = { guard: util.cfnGuard('LAMBDA_CONCURRENCY_CHECK', 'LAMBDA_INSIDE_VPC'), }, }, + SignupLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-SignupLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, SignupLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -91,6 +143,9 @@ module.exports = { ZipFile: fs.readFileSync(`${__dirname}/signup.js`, 'utf8'), }, Handler: 'index.handler', + LoggingConfig: { + LogGroup: { Ref: 'SignupLambdaLogGroup' }, + }, MemorySize: '128', Environment: { Variables: { diff --git a/source/templates/master/solution-helper/index.js b/source/templates/master/solution-helper/index.js index f03de99d9..c88ef5855 100644 --- a/source/templates/master/solution-helper/index.js +++ b/source/templates/master/solution-helper/index.js @@ -33,6 +33,68 @@ module.exports = { util.basicLambdaExecutionPolicy(), util.lambdaVPCAccessExecutionRole(), util.xrayDaemonWriteAccess(), + { + PolicyName: 'GetParameterPolicy', + PolicyDocument: { + Version: '2012-10-17', + Statement: [{ + Effect: 'Allow', + Action: ['ssm:GetParameter'], + Resource: [ + { + 'Fn::Join': [ + '', [ + 'arn:', + { 'Fn::Sub': '${AWS::Partition}:' }, + 'ssm:', + { 'Fn::Sub': '${AWS::Region}:' }, + { 'Fn::Sub': '${AWS::AccountId}:' }, + 'parameter/', + { Ref: 'SolutionHelperParameter' }, + ], + ], + }, { + 'Fn::Join': [ + '', [ + 'arn:', + { 'Fn::Sub': '${AWS::Partition}:' }, + 'ssm:', + { 'Fn::Sub': '${AWS::Region}:' }, + { 'Fn::Sub': '${AWS::AccountId}:' }, + 'parameter/', + { Ref: 'CustomQnABotSettings' }, + ], + ], + }, + ], + }], + }, + }, + { + PolicyName: 'PutParameterPolicy', + PolicyDocument: { + Version: '2012-10-17', + Statement: [{ + Effect: 'Allow', + Action: ['ssm:PutParameter'], + Resource: [ + { + 'Fn::Join': [ + '', [ + 'arn:', + { 'Fn::Sub': '${AWS::Partition}:' }, + 'ssm:', + { 'Fn::Sub': '${AWS::Region}:' }, + { 'Fn::Sub': '${AWS::AccountId}:' }, + 'parameter/', + { Ref: 'SolutionHelperParameter' }, + ], + ], + }, + ], + }], + }, + }, ], }, Metadata: { @@ -49,6 +111,30 @@ module.exports = { BuildDate: (new Date()).toISOString(), }, }, + SolutionHelperLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-SolutionHelper' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, SolutionHelper: { Type: 'AWS::Lambda::Function', Properties: { @@ -59,9 +145,19 @@ module.exports = { }, Description: 'This function generates UUID for each deployment and sends anonymized data to the AWS Solutions team', Handler: 'lambda_function.handler', + LoggingConfig: { + LogGroup: { Ref: 'SolutionHelperLogGroup' }, + }, Role: { 'Fn::GetAtt': ['SolutionHelperRole', 'Arn'], }, + Environment: { + Variables: { + SOLUTION_PARAMETER: { Ref: 'SolutionHelperParameter' }, + CUSTOM_SETTINGS: { Ref: 'CustomQnABotSettings' }, + SOLUTION_ID : util.getCommonEnvironmentVariables().SOLUTION_ID, + }, + }, Runtime: process.env.npm_package_config_pythonRuntime, Timeout: 300, VpcConfig: { @@ -152,7 +248,6 @@ module.exports = { ], }, FulfillmentConcurrency: { Ref: 'FulfillmentConcurrency' }, - LexBotVersion: { Ref: 'LexBotVersion' }, InstallLexResponseBots: { Ref: 'InstallLexResponseBots' }, EmbeddingsApi: { Ref: 'EmbeddingsApi' }, EmbeddingsBedrockModelId: { diff --git a/source/templates/master/tstallstack.js b/source/templates/master/tstallstack.js index 4d3b59f21..e0c560b99 100644 --- a/source/templates/master/tstallstack.js +++ b/source/templates/master/tstallstack.js @@ -28,11 +28,13 @@ module.exports = { EsEndpoint: { 'Fn::GetAtt': ['ESVar', 'ESAddress'] }, EsProxyLambda: { 'Fn::GetAtt': ['ESProxyLambda', 'Arn'] }, TestAllBucket: { Ref: 'TestAllBucket' }, + ContentDesignerOutputBucket: { Ref: 'ContentDesignerOutputBucket' }, VPCSubnetIdList: { 'Fn::Join': [',', { Ref: 'VPCSubnetIdList' }] }, VPCSecurityGroupIdList: { 'Fn::Join': [',', { Ref: 'VPCSecurityGroupIdList' }] }, XraySetting: { Ref: 'XraySetting' }, AwsSdkLayerLambdaLayer: { Ref: 'AwsSdkLayerLambdaLayer' }, CommonModulesLambdaLayer:{ Ref: 'CommonModulesLambdaLayer' }, + LogRetentionPeriod: { Ref: 'LogRetentionPeriod' }, }, }, }, diff --git a/source/templates/package-lock.json b/source/templates/package-lock.json index 0ec6dd463..1f6d8b81d 100644 --- a/source/templates/package-lock.json +++ b/source/templates/package-lock.json @@ -1,12 +1,12 @@ { "name": "qnabot-on-aws-infrastructure", - "version": "6.0.3", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "qnabot-on-aws-infrastructure", - "version": "6.0.3", + "version": "6.1.0", "license": "Apache-2.0", "devDependencies": { "@aws-sdk/client-s3": "^3.621.0", @@ -2420,16 +2420,16 @@ } }, "node_modules/@smithy/core": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.2.tgz", - "integrity": "sha512-in5wwt6chDBcUv1Lw1+QzZxN9fBffi+qOixfb65yK4sDuKG7zAUO9HAFqmVzsZM3N+3tTyvZjtnDXePpvp007Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.1.tgz", + "integrity": "sha512-BC7VMXx/1BCmRPCVzzn4HGWAtsrb7/0758EtwOGFJQrlSwJBEjCcDLNZLFoL/68JexYa2s+KmgL/UfmXdG6v1w==", "dev": true, "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", - "@smithy/middleware-retry": "^3.0.14", + "@smithy/middleware-retry": "^3.0.13", "@smithy/middleware-serde": "^3.0.3", "@smithy/protocol-http": "^4.1.0", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "tslib": "^2.6.2" @@ -2641,15 +2641,15 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.14.tgz", - "integrity": "sha512-7ZaWZJOjUxa5hgmuMspyt8v/zVsh0GXYuF7OvCmdcbVa/xbnKQoYC+uYKunAqRGTkxjOyuOCw9rmFUFOqqC0eQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", "dev": true, "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", "@smithy/service-error-classification": "^3.0.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -2815,9 +2815,9 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", - "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", "dev": true, "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", @@ -2915,13 +2915,13 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.14.tgz", - "integrity": "sha512-0iwTgKKmAIf+vFLV8fji21Jb2px11ktKVxbX6LIDPAUJyWQqGqBVfwba7xwa1f2FZUoolYQgLvxQEpJycXuQ5w==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", "dev": true, "dependencies": { "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -2931,16 +2931,16 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.14.tgz", - "integrity": "sha512-e9uQarJKfXApkTMMruIdxHprhcXivH1flYCe8JRDTzkkLx8dA3V5J8GZlST9yfDiRWkJpZJlUXGN9Rc9Ade3OQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", "dev": true, "dependencies": { "@smithy/config-resolver": "^3.0.5", "@smithy/credential-provider-imds": "^3.2.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.12", + "@smithy/smithy-client": "^3.1.11", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, diff --git a/source/templates/package.json b/source/templates/package.json index 0b671ad08..abb232983 100644 --- a/source/templates/package.json +++ b/source/templates/package.json @@ -1,6 +1,6 @@ { "name": "qnabot-on-aws-infrastructure", - "version": "6.0.3", + "version": "6.1.0", "description": "QnABot infrastructure", "scripts": { "clean": "rm -rf node_modules", diff --git a/source/templates/public-vpc-support/index.js b/source/templates/public-vpc-support/index.js index b068a70c5..8f49b6638 100644 --- a/source/templates/public-vpc-support/index.js +++ b/source/templates/public-vpc-support/index.js @@ -24,10 +24,6 @@ module.exports = Promise.resolve(require('../master')).then((base) => { 'ClientURL', 'DashboardURL', 'UserPoolURL', - 'LexV1BotName', - 'LexV1BotAlias', - 'LexV1Intent', - 'LexV1IntentFallback', 'LexV2BotName', 'LexV2BotId', 'LexV2BotAlias', @@ -40,6 +36,8 @@ module.exports = Promise.resolve(require('../master')).then((base) => { 'OpenSearchEndpoint', 'ElasticsearchIndex', 'MetricsBucket', + 'TestAllBucket', + 'ContentDesignerOutputBucket' ]); base.Parameters = _.pick(base.Parameters, [ 'Email', @@ -74,6 +72,7 @@ module.exports = Promise.resolve(require('../master')).then((base) => { 'LLMLambdaArn', 'BedrockKnowledgeBaseId', 'BedrockKnowledgeBaseModel', + 'LogRetentionPeriod', ]); base.Metadata = { 'AWS::CloudFormation::Interface': { diff --git a/source/templates/public/index.js b/source/templates/public/index.js index 39e6391cc..f567a0e6a 100644 --- a/source/templates/public/index.js +++ b/source/templates/public/index.js @@ -24,10 +24,6 @@ module.exports = Promise.resolve(require('../master')).then((base) => { 'ClientURL', 'DashboardURL', 'UserPoolURL', - 'LexV1BotName', - 'LexV1BotAlias', - 'LexV1Intent', - 'LexV1IntentFallback', 'LexV2BotName', 'LexV2BotId', 'LexV2BotAlias', @@ -40,6 +36,8 @@ module.exports = Promise.resolve(require('../master')).then((base) => { 'OpenSearchEndpoint', 'ElasticsearchIndex', 'MetricsBucket', + 'TestAllBucket', + 'ContentDesignerOutputBucket' ]); base.Parameters = _.pick(base.Parameters, [ 'Email', @@ -72,6 +70,7 @@ module.exports = Promise.resolve(require('../master')).then((base) => { 'LLMLambdaArn', 'BedrockKnowledgeBaseId', 'BedrockKnowledgeBaseModel', + 'LogRetentionPeriod' ]); base.Metadata = { 'AWS::CloudFormation::Interface': { diff --git a/source/templates/sagemaker-qa-summarize-llm/__snapshots__/index.test.js.snap b/source/templates/sagemaker-qa-summarize-llm/__snapshots__/index.test.js.snap index 3c8b701b0..600991dd1 100644 --- a/source/templates/sagemaker-qa-summarize-llm/__snapshots__/index.test.js.snap +++ b/source/templates/sagemaker-qa-summarize-llm/__snapshots__/index.test.js.snap @@ -166,7 +166,7 @@ exports[`renders sagemaker-qa-summarize-llm template correctly 1`] = ` "SM_NUM_GPUS": "4", }, "Image": { - "Fn::Sub": "763104351884.dkr.ecr.\${AWS::Region}.amazonaws.com/huggingface-pytorch-tgi-inference:2.0.1-tgi1.1.0-gpu-py39-cu118-ubuntu20.04", + "Fn::Sub": "763104351884.dkr.ecr.\${AWS::Region}.amazonaws.com/huggingface-pytorch-tgi-inference:2.3.0-tgi2.2.0-gpu-py310-cu121-ubuntu22.04-v2.0", }, "ModelDataSource": { "S3DataSource": { @@ -176,7 +176,7 @@ exports[`renders sagemaker-qa-summarize-llm template correctly 1`] = ` }, "S3DataType": "S3Prefix", "S3Uri": { - "Fn::Sub": "s3://jumpstart-private-cache-prod-\${AWS::Region}/meta-textgeneration/meta-textgeneration-llama-2-13b-f/artifacts/inference-prepack/v1.0.0/", + "Fn::Sub": "s3://jumpstart-private-cache-prod-\${AWS::Region}/meta-textgeneration/meta-textgeneration-llama-2-13b-f/artifacts/inference-prepack/v1.1.0/", }, }, }, diff --git a/source/templates/sagemaker-qa-summarize-llm/index.js b/source/templates/sagemaker-qa-summarize-llm/index.js index 7d56302cc..1b6bd6300 100644 --- a/source/templates/sagemaker-qa-summarize-llm/index.js +++ b/source/templates/sagemaker-qa-summarize-llm/index.js @@ -43,11 +43,11 @@ module.exports = { Properties: { PrimaryContainer: { Image: { - 'Fn::Sub': '763104351884.dkr.ecr.${AWS::Region}.amazonaws.com/huggingface-pytorch-tgi-inference:2.0.1-tgi1.1.0-gpu-py39-cu118-ubuntu20.04' + 'Fn::Sub': '763104351884.dkr.ecr.${AWS::Region}.amazonaws.com/huggingface-pytorch-tgi-inference:2.3.0-tgi2.2.0-gpu-py310-cu121-ubuntu22.04-v2.0' }, ModelDataSource: { S3DataSource: { - S3Uri: {'Fn::Sub': 's3://jumpstart-private-cache-prod-${AWS::Region}/meta-textgeneration/meta-textgeneration-llama-2-13b-f/artifacts/inference-prepack/v1.0.0/' }, + S3Uri: {'Fn::Sub': 's3://jumpstart-private-cache-prod-${AWS::Region}/meta-textgeneration/meta-textgeneration-llama-2-13b-f/artifacts/inference-prepack/v1.1.0/' }, S3DataType: "S3Prefix", CompressionType: "None", ModelAccessConfig: { diff --git a/source/templates/testall/__snapshots__/index.test.js.snap b/source/templates/testall/__snapshots__/index.test.js.snap index db1971e24..248e38596 100644 --- a/source/templates/testall/__snapshots__/index.test.js.snap +++ b/source/templates/testall/__snapshots__/index.test.js.snap @@ -4,6 +4,18 @@ exports[`renders testall template correctly 1`] = ` { "AWSTemplateFormatVersion": "2010-09-09", "Conditions": { + "LogRetentionPeriodIsNotZero": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "LogRetentionPeriod", + }, + 0, + ], + }, + ], + }, "VPCEnabled": { "Fn::Not": [ { @@ -46,6 +58,9 @@ exports[`renders testall template correctly 1`] = ` "CommonModulesLambdaLayer": { "Type": "String", }, + "ContentDesignerOutputBucket": { + "Type": "String", + }, "EsEndpoint": { "Type": "String", }, @@ -58,6 +73,9 @@ exports[`renders testall template correctly 1`] = ` "LexV2BotId": { "Type": "String", }, + "LogRetentionPeriod": { + "Type": "Number", + }, "S3Clean": { "Type": "String", }, @@ -259,6 +277,9 @@ exports[`renders testall template correctly 1`] = ` { "Fn::Sub": "arn:aws:s3:::\${TestAllBucket}*", }, + { + "Fn::Sub": "arn:aws:s3:::\${ContentDesignerOutputBucket}*", + }, ], }, { @@ -338,6 +359,9 @@ exports[`renders testall template correctly 1`] = ` "LEXV2_BOT_ID": { "Ref": "LexV2BotId", }, + "OUTPUT_S3_BUCKET": { + "Ref": "ContentDesignerOutputBucket", + }, "SOLUTION_ID": "SO0189", "SOLUTION_VERSION": "vx.x.x", }, @@ -351,6 +375,11 @@ exports[`renders testall template correctly 1`] = ` "Ref": "CommonModulesLambdaLayer", }, ], + "LoggingConfig": { + "LogGroup": { + "Ref": "TestAllStepLambdaLogGroup", + }, + }, "MemorySize": "1280", "Role": { "Fn::GetAtt": [ @@ -406,6 +435,53 @@ exports[`renders testall template correctly 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "TestAllStepLambdaLogGroup": { + "Metadata": { + "guard": { + "SuppressedRules": [ + "CLOUDWATCH_LOG_GROUP_ENCRYPTED", + "CW_LOGGROUP_RETENTION_PERIOD_CHECK", + ], + }, + }, + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "-", + [ + { + "Fn::Sub": "/aws/lambda/\${AWS::StackName}-TestAllStepLambda", + }, + { + "Fn::Select": [ + "2", + { + "Fn::Split": [ + "/", + { + "Ref": "AWS::StackId", + }, + ], + }, + ], + }, + ], + ], + }, + "RetentionInDays": { + "Fn::If": [ + "LogRetentionPeriodIsNotZero", + { + "Ref": "LogRetentionPeriod", + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + }, "TestAllStepPermission": { "Properties": { "Action": "lambda:InvokeFunction", diff --git a/source/templates/testall/index.js b/source/templates/testall/index.js index f65ef3ae5..4a0051994 100644 --- a/source/templates/testall/index.js +++ b/source/templates/testall/index.js @@ -31,12 +31,14 @@ module.exports = { S3Clean: { Type: 'String' }, LexV2BotId: { Type: 'String' }, LexV2BotAliasId: { Type: 'String' }, + LogRetentionPeriod: { Type: 'Number' }, BootstrapBucket: { Type: 'String' }, BootstrapPrefix: { Type: 'String' }, VarIndex: { Type: 'String' }, EsEndpoint: { Type: 'String' }, EsProxyLambda: { Type: 'String' }, TestAllBucket: { Type: 'String' }, + ContentDesignerOutputBucket: { Type: 'String' }, VPCSubnetIdList: { Type: 'String' }, VPCSecurityGroupIdList: { Type: 'String' }, XraySetting: { Type: 'String' }, @@ -46,5 +48,6 @@ module.exports = { Conditions: { VPCEnabled: { 'Fn::Not': [{ 'Fn::Equals': ['', { Ref: 'VPCSecurityGroupIdList' }] }] }, XRAYEnabled: { 'Fn::Equals': [{ Ref: 'XraySetting' }, 'TRUE'] }, + LogRetentionPeriodIsNotZero: { 'Fn::Not': [{ 'Fn::Equals': [{ Ref: 'LogRetentionPeriod' }, 0] }] } }, }; diff --git a/source/templates/testall/resources.js b/source/templates/testall/resources.js index d9cfdb09d..cce169324 100644 --- a/source/templates/testall/resources.js +++ b/source/templates/testall/resources.js @@ -26,6 +26,31 @@ module.exports = { BuildDate: new Date().toISOString(), }, }, + TestAllStepLambdaLogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: { + 'Fn::Join': [ + '-', + [ + { 'Fn::Sub': '/aws/lambda/${AWS::StackName}-TestAllStepLambda' }, + { 'Fn::Select': ['2', { 'Fn::Split': ['/', { Ref: 'AWS::StackId' }] }] }, + ], + ], + }, + + RetentionInDays: { + 'Fn::If': [ + 'LogRetentionPeriodIsNotZero', + { Ref: 'LogRetentionPeriod' }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + Metadata: { + guard: util.cfnGuard('CLOUDWATCH_LOG_GROUP_ENCRYPTED', 'CW_LOGGROUP_RETENTION_PERIOD_CHECK'), + }, + }, TestAllStepLambda: { Type: 'AWS::Lambda::Function', Properties: { @@ -41,10 +66,14 @@ module.exports = { ES_PROXY: { Ref: 'EsProxyLambda' }, LEXV2_BOT_ID: { Ref: 'LexV2BotId' }, LEXV2_BOT_ALIAS_ID: { Ref: 'LexV2BotAliasId' }, - ...util.getCommonEnvironmentVariables() + OUTPUT_S3_BUCKET: { Ref: 'ContentDesignerOutputBucket'}, + ...util.getCommonEnvironmentVariables(), }, }, Handler: 'index.step', + LoggingConfig: { + LogGroup: { Ref: 'TestAllStepLambdaLogGroup' }, + }, MemorySize: '1280', Role: { 'Fn::GetAtt': ['TestAllRole', 'Arn'] }, Runtime: process.env.npm_package_config_lambdaRuntime, @@ -64,7 +93,7 @@ module.exports = { }, Layers: [ { Ref: 'AwsSdkLayerLambdaLayer' }, - { Ref: 'CommonModulesLambdaLayer' } + { Ref: 'CommonModulesLambdaLayer' }, ], Tags: [ { @@ -112,7 +141,10 @@ module.exports = { 's3:DeleteObject', 's3:DeleteObjectVersion', ], - Resource: [{ 'Fn::Sub': 'arn:aws:s3:::${TestAllBucket}*' }], + Resource: [ + { 'Fn::Sub': 'arn:aws:s3:::${TestAllBucket}*' }, + { 'Fn::Sub': 'arn:aws:s3:::${ContentDesignerOutputBucket}*' }, + ], }, { Effect: 'Allow', diff --git a/source/templates/util.js b/source/templates/util.js index ac32ff084..edf29741c 100644 --- a/source/templates/util.js +++ b/source/templates/util.js @@ -263,23 +263,6 @@ exports.lexFullAccess = function () { ], Resource: '*', // these actions cannot be bound to resources other than * }, - { // Lex V1 policies - Effect: 'Allow', - Action: [ - 'lex:GetBuiltinIntent', - 'lex:GetIntents', - 'lex:GetBots', - 'lex:GetSlotTypes', - 'lex:GetBotAliases', - 'lex:StartImport', - 'lex:GetMigration', - 'lex:GetBuiltinSlotTypes', - 'lex:GetBuiltinIntents', - 'lex:GetImport', - 'lex:GetMigrations', - ], - Resource: '*', // these actions cannot be bound to resources other than * - }, { Effect: 'Allow', Action: 'lex:*', @@ -312,23 +295,6 @@ exports.lexFullAccess = function () { { 'Fn::Sub': 'arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*' }, ], }, - { // Lex V1 policies - Effect: 'Allow', - Action: [ - 'lex:GetBuiltinIntent', - 'lex:GetIntents', - 'lex:GetBots', - 'lex:GetSlotTypes', - 'lex:GetBotAliases', - 'lex:StartImport', - 'lex:GetMigration', - 'lex:GetBuiltinSlotTypes', - 'lex:GetBuiltinIntents', - 'lex:GetImport', - 'lex:GetMigrations', - ], - Resource: '*', // these actions cannot be bound to resources other than * - }, { Effect: 'Allow', Action: 'lex:*', diff --git a/source/website/js/admin.vue b/source/website/js/admin.vue index 04420507a..a83a05240 100644 --- a/source/website/js/admin.vue +++ b/source/website/js/admin.vue @@ -51,6 +51,8 @@ v-app a(href="https://aws.amazon.com/blogs/machine-learning/creating-virtual-guided-navigation-using-a-question-and-answer-bot-with-amazon-lex-and-amazon-alexa/" target="_blank") Guided Navigation using QnABot v-list-item-title a(href="https://aws.amazon.com/blogs/machine-learning/create-a-questionnaire-bot-with-amazon-lex-and-amazon-alexa/" target="_blank") Create a questionnaire using QnABot + v-list-item-title + a(href="https://aws.amazon.com/blogs/machine-learning/delight-your-customers-with-great-conversational-experiences-via-qnabot-a-generative-ai-chatbot/" target="_blank") Delight your customers with great conversational experiences via QnABot, a generative AI chatbot v-app-bar() v-app-bar-nav-icon.text-primary(id="nav-open" @click.stop="drawer = !drawer") v-app-bar-title diff --git a/source/website/js/components/designer/menu-testall.vue b/source/website/js/components/designer/menu-testall.vue index 33629ef76..9c5d2e6c5 100644 --- a/source/website/js/components/designer/menu-testall.vue +++ b/source/website/js/components/designer/menu-testall.vue @@ -171,6 +171,7 @@ export default { locale: this.selectedLocale, token, }); + await new Promise(resolve => setTimeout(resolve, 3000)); await this.refresh(); } catch (e) { this.error = err; diff --git a/source/website/js/components/designer/synckendra.vue b/source/website/js/components/designer/synckendra.vue index 919a406ab..15421aa24 100644 --- a/source/website/js/components/designer/synckendra.vue +++ b/source/website/js/components/designer/synckendra.vue @@ -123,6 +123,7 @@ module.exports = { name: this.filename, filter: '', }); + await new Promise(resolve => setTimeout(resolve, 3000)); await this.refresh(); } catch (e) { // never enters this block diff --git a/source/website/js/components/export.vue b/source/website/js/components/export.vue index 5bbd12cc2..971b27a21 100644 --- a/source/website/js/components/export.vue +++ b/source/website/js/components/export.vue @@ -113,6 +113,7 @@ module.exports = { name: this.filename, filter: this.filter, }); + await new Promise(resolve => setTimeout(resolve, 3000)); await this.refresh(); } catch (e) { this.error = e; diff --git a/source/website/js/components/genesys/index.vue b/source/website/js/components/genesys/index.vue index fb4f87d8c..22732450b 100644 --- a/source/website/js/components/genesys/index.vue +++ b/source/website/js/components/genesys/index.vue @@ -47,22 +47,22 @@ v-container v-card(flat) v-card-title(class="text-center") {{ steps[2].title }} v-card-text(v-html="steps[2].text") - v-card-actions - v-btn( - :id="steps[2].buttons[0].id" - :loading="steps[2].buttons[0].loading" - @click="copy(steps[2].buttons[0])" - ) {{ steps[2].buttons[0].text }} - template(#item.4) - v-card(flat) - v-card-title(class="text-center") {{ steps[3].title }} - v-card-text(v-html="steps[3].text") img( - v-if="steps[3].image" - :src="steps[3].image" + v-if="steps[2].image" + :src="steps[2].image" style="max-width:75%;display:block;margin:auto;" contain ) + template(#item.4) + v-card(flat) + v-card-title(class="text-center") {{ steps[3].title }} + v-card-text(v-html="steps[3].text") + v-card-actions + v-btn( + :id="steps[3].buttons[0].id" + :loading="steps[3].buttons[0].loading" + @click="copy(steps[3].buttons[0])" + ) {{ steps[3].buttons[0].text }} template(#item.5) v-card(flat) v-card-title(class="text-center") {{ steps[4].title }} diff --git a/source/website/js/components/settings.vue b/source/website/js/components/settings.vue index 7a76f9e4c..6b041423c 100644 --- a/source/website/js/components/settings.vue +++ b/source/website/js/components/settings.vue @@ -269,7 +269,7 @@ module.exports = { this.alertTitle = 'Error'; } }); - fileReader.readAsBinaryString(files[0]); + fileReader.readAsText(files[0]); }, downloadBlobAsFile: (function closure_shell() { const a = document.createElement('a'); diff --git a/source/website/js/lib/store/api/actions/settings.js b/source/website/js/lib/store/api/actions/settings.js index 3c680dd0e..2374865d5 100644 --- a/source/website/js/lib/store/api/actions/settings.js +++ b/source/website/js/lib/store/api/actions/settings.js @@ -12,6 +12,7 @@ ******************************************************************************************************************** */ const _ = require('lodash'); const { SSMClient, GetParameterCommand, GetParametersCommand, PutParameterCommand } = require('@aws-sdk/client-ssm'); +const { LambdaClient, InvokeCommand } = require('@aws-sdk/client-lambda'); const util = require('../../../../capability/util'); const chatbotTestingIndex = 0; @@ -489,6 +490,22 @@ const settingsMap = { }, ], }, + bedrockGuardrails: { + id: 'text_generation_guardrail_subgroup', + label: 'Guardrail for Amazon Bedrock and Knowledge Base Integrations', + collapsed: true, + members: [ + + { + id: 'BEDROCK_GUARDRAIL_IDENTIFIER', + hint: 'Enter a pre-configurated Bedrock Guardrail identifier (e.g. 4ojm24q0yada) that you want to be applied to the requests made to the LLM models configured in CloudFormation parameters LLMBedrockModelId and BedrockKnowledgeBaseModel. If you don\'t provide a value, no guardrail is applied to the LLM invocation. If you provide a identifier, you must also provide a BEDROCK_GUARDRAIL_VERSION', + }, + { + id: 'BEDROCK_GUARDRAIL_VERSION', + hint: 'Enter the version (e.g. 1 or DRAFT) of the guardrail specifed in BEDROCK_GUARDRAIL_IDENTIFIER', + }, + ], + }, kendraSettings: { id: 'amazon_kendra_subgroup', label: 'Retrieval Augmented Generation (RAG) with Amazon Kendra', @@ -544,6 +561,11 @@ const settingsMap = { label: 'Retrieval Augmented Generation (RAG) with Amazon Bedrock Knowledge Base', collapsed: true, members: [ + { + id: 'KNOWLEDGE_BASE_PROMPT_TEMPLATE', + type: 'textarea', + hint: 'The template used to construct a prompt that is sent to the model for response generation. To opt out of sending a prompt to the Knowledge Base model, simply leave this field empty. For more information, see Bedrock Knowledge base (https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base.html)', + }, { id: 'KNOWLEDGE_BASE_PREFIX_MESSAGE', hint: 'Message used to prefix a Knowledge Base generated answer', @@ -563,6 +585,25 @@ const settingsMap = { type: 'number', hint: 'Determines length of time in seconds for the validity of signed S3 Urls for Bedrock Knowledge Base answers', }, + { + id: 'KNOWLEDGE_BASE_MODEL_PARAMS', + hint: 'Customize the knowledge base model by providing inference parameters (e.g. anthropic model parameters can be customized as `{"temperature":0.1}` or `{"temperature":0.3, "maxTokens": 262, "topP":0.9, "top_k": 240 }`). For more information, please refer to Inference parameters (https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html)', + }, + { + id: 'KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS', + type: 'number', + hint: 'Sets maximum number of retrieved result where each result corresponds to a source chunk. When querying a knowledge base, Amazon Bedrock returns up to five results by default. For more information, please refer to Maximum number of retrieved results (https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html)', + }, + { + id: 'KNOWLEDGE_BASE_SEARCH_TYPE', + type: 'enum', + enums: ['DEFAULT', 'HYBRID', 'SEMANTIC'], + hint: 'Select the search type which defines how data sources in the knowledge base are queried. If using an Amazon OpenSearch Serverless vector store that contains a filterable text field, you can specify whether to query the knowledge base with a HYBRID search using both vector embeddings and raw text, or SEMANTIC search using only vector embeddings. For other vector store configurations, only SEMANTIC search is available. For more information, please refer to Search type (https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html)', + }, + { + id: 'KNOWLEDGE_BASE_METADATA_FILTERS', + hint: 'Specifies the filters to use on the metadata in the knowledge base data sources before returning results. (e.g filters can be customized as`{"filter1": { "key": "string", "value": "string" }, "filter2": { "key": "string", "value": number }}`). For more information, please refer to Metadata and filtering (https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html)', + }, ], }, }, @@ -597,6 +638,37 @@ async function saveParameters(ssm, params) { } } +async function sendAnonymizedData(params, settings){ + const map = { event: 'UPDATE_SETTINGS' }; + map.BEDROCK_GUARDRAIL_ENABLE = settings.BEDROCK_GUARDRAIL_IDENTIFIER && settings.BEDROCK_GUARDRAIL_VERSION ? 'true' : 'false'; + map.ENABLE_MULTI_LANGUAGE_SUPPORT = settings.ENABLE_MULTI_LANGUAGE_SUPPORT || 'false'; + map.LLM_GENERATE_QUERY_ENABLE = settings.LLM_GENERATE_QUERY_ENABLE || 'true'; + map.KNOWLEDGE_BASE_SEARCH_TYPE = settings.KNOWLEDGE_BASE_SEARCH_TYPE || 'DEFAULT'; + map.PII_REJECTION_ENABLED = settings.PII_REJECTION_ENABLED || 'false'; + map.EMBEDDINGS_ENABLE = settings.EMBEDDINGS_ENABLE || 'true'; + map.LLM_QA_ENABLE = settings.LLM_QA_ENABLE || 'true'; + + + const payload = Buffer.from(JSON.stringify(map)); + const client = new LambdaClient({ + customUserAgent: util.getUserAgentString(params.version, 'C050'), + region: params.region, + credentials: params.credentials + }); + + const input = { + FunctionName: params.solutionHelper, + InvocationType: "RequestResponse", + Payload: payload, + }; + const command = new InvokeCommand(input); + const response = await client.send(command); + if (response.FunctionError) { + throw new Error('Solution Helper Function Error Occurred'); + } + return response; +} + module.exports = { async listSettings(context) { const credentials = context.rootState.user.credentials; @@ -638,10 +710,27 @@ module.exports = { async updateSettings(context, settings) { const credentials = context.rootState.user.credentials; const customParams = context.rootState.info.CustomQnABotSettings; + const region = context.rootState.info.region; + const version = context.rootState.info.Version; + const solutionHelper = context.rootState.info.SolutionHelper; const ssm = new SSMClient({ - customUserAgent: util.getUserAgentString(context.rootState.info.Version, 'C022'), - region: context.rootState.info.region, credentials + customUserAgent: util.getUserAgentString(version, 'C022'), + region, + credentials }); + + try { + const params = { + region, + credentials, + version, + solutionHelper + }; + await sendAnonymizedData(params, settings); + } catch (e) { + console.log(`Error in sending anonymized data: ${e.message}`); + } + // Note type is not required in params if the parameter exists. Some customers require this parameter // to be a SecureString and set this type post deploy of QnABot. Removing type supports // this setting.

    +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