diff --git a/docs/assets/images/usecase_agentbuilder.gif b/docs/assets/images/usecase_agentbuilder.gif new file mode 100644 index 000000000..cd5be84df Binary files /dev/null and b/docs/assets/images/usecase_agentbuilder.gif differ diff --git a/docs/en/DEPLOY_OPTION.md b/docs/en/DEPLOY_OPTION.md index a45f5e7a6..1c48ce407 100644 --- a/docs/en/DEPLOY_OPTION.md +++ b/docs/en/DEPLOY_OPTION.md @@ -689,6 +689,8 @@ Enabling `createGenericAgentCoreRuntime` will deploy the default AgentCore Runti By default, it is deployed to the `modelRegion`, but you can override this by specifying `agentCoreRegion`. The default agents available in AgentCore can utilize MCP servers defined in [mcp.json](https://github.com/aws-samples/generative-ai-use-cases/blob/main/packages/cdk/lambda-python/generic-agent-core-runtime/mcp.json). +This default agent is available in Agent Builder, and users can create any agent from MCPs that administrators have permitted. + The MCP servers defined by default are AWS-related MCP servers and MCP servers related to current time. For details, please refer to the documentation [here](https://awslabs.github.io/mcp/). When adding MCP servers, please add them to the aforementioned `mcp.json`. diff --git a/docs/ja/DEPLOY_OPTION.md b/docs/ja/DEPLOY_OPTION.md index 870044bfd..40ab84f0b 100644 --- a/docs/ja/DEPLOY_OPTION.md +++ b/docs/ja/DEPLOY_OPTION.md @@ -704,6 +704,8 @@ AgentCore で作成したエージェントと連携するユースケースで デフォルトでは `modelRegion` にデプロイされますが、`agentCoreRegion` を指定し上書きすることが可能です。 AgentCore で使用できるデフォルトのエージェントは、[mcp.json](https://github.com/aws-samples/generative-ai-use-cases/blob/main/packages/cdk/lambda-python/generic-agent-core-runtime/mcp.json) で定義する MCP サーバーを利用することができます。 +このデフォルトのエージェントは Agent Builder で利用でき、ユーザーは管理者が許可した MCP から任意のエージェントを作成することができます。 + デフォルトで定義されている MCP サーバーは、AWS に関連する MCP サーバー及び、現在時刻に関連する MCP サーバーです。 詳細は[こちら](https://awslabs.github.io/mcp/)のドキュメントをご参照ください。 MCP サーバーを追加する場合は上述の `mcp.json` に追記してください。 diff --git a/docs/overrides/home_en.html b/docs/overrides/home_en.html index 8a81b34ec..4868efc3e 100644 --- a/docs/overrides/home_en.html +++ b/docs/overrides/home_en.html @@ -188,6 +188,23 @@

Agent Chat

+
+
+ Agent Builder +

Agent Builder

+

+ Agent Builder is a comprehensive platform for creating, managing, + and deploying custom AI agents within GenU. Build agents with + specialized capabilities using MCP servers, and custom system + prompts. Organize your agents with tags and share them in the + marketplace, or integrate external Bedrock Agents and AgentCore + runtimes for enhanced functionality. +

+
+
Agent チャット

+
+
+ Agent Builder +

Agent Builder

+

+ Agent + Builderは、GenU内でカスタムAIエージェントを作成、管理、デプロイするための包括的なプラットフォームです。MCPサーバーとカスタムシステムプロンプトを使用して、専門的な機能を持つエージェントを構築できます。タグでエージェントを整理し、マーケットプレイスで共有したり、外部のBedrock + AgentsやAgentCoreランタイムを統合して機能を拡張したりできます。 +

+
+
= 14.15.0" + "node": ">= 18.0.0" }, "peerDependencies": { - "aws-cdk-lib": "^2.154.1", + "aws-cdk-lib": "^2.217.0", "constructs": "^10.0.0" } }, "node_modules/@aws-cdk/cloud-assembly-schema": { - "version": "48.3.0", - "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-48.3.0.tgz", - "integrity": "sha512-6R7aMNXeVnXGMOXgspwMmpVi1rmgRReGKYt7yl22ZKNZN/whJqdnV2C6O2CI2lnj5Th/SlgQWsuEQOMM3TI5RQ==", + "version": "48.11.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-48.11.0.tgz", + "integrity": "sha512-1qMR8EYwgVBrSEK/zIoYIEuvHNT9busOXncCrV5uqRtjJTPTOJh5oJQjuzbBBy6ERLhTyLPTR/bu8f1aI3SLGw==", "bundleDependencies": [ "jsonschema", "semver" @@ -904,85 +904,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-agentcore-control": { - "version": "3.863.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-agentcore-control/-/client-bedrock-agentcore-control-3.863.0.tgz", - "integrity": "sha512-Tnj6ACCTjzYS5toEUMslfGFIQulDz7JMQNDEqXzfkEPCUML2O2gtNZb0KH73Xe4uRHOE3e09Dmig2yf4fwtkKA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.863.0", - "@aws-sdk/credential-provider-node": "3.863.0", - "@aws-sdk/middleware-host-header": "3.862.0", - "@aws-sdk/middleware-logger": "3.862.0", - "@aws-sdk/middleware-recursion-detection": "3.862.0", - "@aws-sdk/middleware-user-agent": "3.863.0", - "@aws-sdk/region-config-resolver": "3.862.0", - "@aws-sdk/types": "3.862.0", - "@aws-sdk/util-endpoints": "3.862.0", - "@aws-sdk/util-user-agent-browser": "3.862.0", - "@aws-sdk/util-user-agent-node": "3.863.0", - "@smithy/config-resolver": "^4.1.5", - "@smithy/core": "^3.8.0", - "@smithy/fetch-http-handler": "^5.1.1", - "@smithy/hash-node": "^4.0.5", - "@smithy/invalid-dependency": "^4.0.5", - "@smithy/middleware-content-length": "^4.0.5", - "@smithy/middleware-endpoint": "^4.1.18", - "@smithy/middleware-retry": "^4.1.19", - "@smithy/middleware-serde": "^4.0.9", - "@smithy/middleware-stack": "^4.0.5", - "@smithy/node-config-provider": "^4.1.4", - "@smithy/node-http-handler": "^4.1.1", - "@smithy/protocol-http": "^5.1.3", - "@smithy/smithy-client": "^4.4.10", - "@smithy/types": "^4.3.2", - "@smithy/url-parser": "^4.0.5", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.26", - "@smithy/util-defaults-mode-node": "^4.0.26", - "@smithy/util-endpoints": "^3.0.7", - "@smithy/util-middleware": "^4.0.5", - "@smithy/util-retry": "^4.0.7", - "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.7", - "@types/uuid": "^9.0.1", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-bedrock-agentcore-control/node_modules/@aws-sdk/types": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.862.0.tgz", - "integrity": "sha512-Bei+RL0cDxxV+lW2UezLbCYYNeJm6Nzee0TpW0FfyTRBhH9C1XQh4+x+IClriXvgBnRquTMMYsmJfvx8iyLKrg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-bedrock-agentcore-control/node_modules/@smithy/util-utf8": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", - "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-bedrock-agentcore/node_modules/@aws-sdk/types": { "version": "3.862.0", "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.862.0.tgz", @@ -1145,6 +1066,506 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/client-cognito-identity-provider": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity-provider/-/client-cognito-identity-provider-3.888.0.tgz", + "integrity": "sha512-ZRrWqS3avq6KTb2vpwAWeIYFsATEirTC/SGGtRb+LQdy5dLE9Le3nyI+MpNzLnIuBCkoAtdkr7ZVNn6vR/2ivg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.888.0", + "@aws-sdk/credential-provider-node": "3.888.0", + "@aws-sdk/middleware-host-header": "3.887.0", + "@aws-sdk/middleware-logger": "3.887.0", + "@aws-sdk/middleware-recursion-detection": "3.887.0", + "@aws-sdk/middleware-user-agent": "3.888.0", + "@aws-sdk/region-config-resolver": "3.887.0", + "@aws-sdk/types": "3.887.0", + "@aws-sdk/util-endpoints": "3.887.0", + "@aws-sdk/util-user-agent-browser": "3.887.0", + "@aws-sdk/util-user-agent-node": "3.888.0", + "@smithy/config-resolver": "^4.2.1", + "@smithy/core": "^3.11.0", + "@smithy/fetch-http-handler": "^5.2.1", + "@smithy/hash-node": "^4.1.1", + "@smithy/invalid-dependency": "^4.1.1", + "@smithy/middleware-content-length": "^4.1.1", + "@smithy/middleware-endpoint": "^4.2.1", + "@smithy/middleware-retry": "^4.2.1", + "@smithy/middleware-serde": "^4.1.1", + "@smithy/middleware-stack": "^4.1.1", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/node-http-handler": "^4.2.1", + "@smithy/protocol-http": "^5.2.1", + "@smithy/smithy-client": "^4.6.1", + "@smithy/types": "^4.5.0", + "@smithy/url-parser": "^4.1.1", + "@smithy/util-base64": "^4.1.0", + "@smithy/util-body-length-browser": "^4.1.0", + "@smithy/util-body-length-node": "^4.1.0", + "@smithy/util-defaults-mode-browser": "^4.1.1", + "@smithy/util-defaults-mode-node": "^4.1.1", + "@smithy/util-endpoints": "^3.1.1", + "@smithy/util-middleware": "^4.1.1", + "@smithy/util-retry": "^4.1.1", + "@smithy/util-utf8": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/client-sso": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.888.0.tgz", + "integrity": "sha512-8CLy/ehGKUmekjH+VtZJ4w40PqDg3u0K7uPziq/4P8Q7LLgsy8YQoHNbuY4am7JU3HWrqLXJI9aaz1+vPGPoWA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.888.0", + "@aws-sdk/middleware-host-header": "3.887.0", + "@aws-sdk/middleware-logger": "3.887.0", + "@aws-sdk/middleware-recursion-detection": "3.887.0", + "@aws-sdk/middleware-user-agent": "3.888.0", + "@aws-sdk/region-config-resolver": "3.887.0", + "@aws-sdk/types": "3.887.0", + "@aws-sdk/util-endpoints": "3.887.0", + "@aws-sdk/util-user-agent-browser": "3.887.0", + "@aws-sdk/util-user-agent-node": "3.888.0", + "@smithy/config-resolver": "^4.2.1", + "@smithy/core": "^3.11.0", + "@smithy/fetch-http-handler": "^5.2.1", + "@smithy/hash-node": "^4.1.1", + "@smithy/invalid-dependency": "^4.1.1", + "@smithy/middleware-content-length": "^4.1.1", + "@smithy/middleware-endpoint": "^4.2.1", + "@smithy/middleware-retry": "^4.2.1", + "@smithy/middleware-serde": "^4.1.1", + "@smithy/middleware-stack": "^4.1.1", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/node-http-handler": "^4.2.1", + "@smithy/protocol-http": "^5.2.1", + "@smithy/smithy-client": "^4.6.1", + "@smithy/types": "^4.5.0", + "@smithy/url-parser": "^4.1.1", + "@smithy/util-base64": "^4.1.0", + "@smithy/util-body-length-browser": "^4.1.0", + "@smithy/util-body-length-node": "^4.1.0", + "@smithy/util-defaults-mode-browser": "^4.1.1", + "@smithy/util-defaults-mode-node": "^4.1.1", + "@smithy/util-endpoints": "^3.1.1", + "@smithy/util-middleware": "^4.1.1", + "@smithy/util-retry": "^4.1.1", + "@smithy/util-utf8": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/core": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.888.0.tgz", + "integrity": "sha512-L3S2FZywACo4lmWv37Y4TbefuPJ1fXWyWwIJ3J4wkPYFJ47mmtUPqThlVrSbdTHkEjnZgJe5cRfxk0qCLsFh1w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.887.0", + "@aws-sdk/xml-builder": "3.887.0", + "@smithy/core": "^3.11.0", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/property-provider": "^4.0.5", + "@smithy/protocol-http": "^5.2.1", + "@smithy/signature-v4": "^5.1.3", + "@smithy/smithy-client": "^4.6.1", + "@smithy/types": "^4.5.0", + "@smithy/util-base64": "^4.1.0", + "@smithy/util-body-length-browser": "^4.1.0", + "@smithy/util-middleware": "^4.1.1", + "@smithy/util-utf8": "^4.1.0", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.888.0.tgz", + "integrity": "sha512-shPi4AhUKbIk7LugJWvNpeZA8va7e5bOHAEKo89S0Ac8WDZt2OaNzbh/b9l0iSL2eEyte8UgIsYGcFxOwIF1VA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.888.0", + "@aws-sdk/types": "3.887.0", + "@smithy/property-provider": "^4.0.5", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.888.0.tgz", + "integrity": "sha512-Jvuk6nul0lE7o5qlQutcqlySBHLXOyoPtiwE6zyKbGc7RVl0//h39Lab7zMeY2drMn8xAnIopL4606Fd8JI/Hw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.888.0", + "@aws-sdk/types": "3.887.0", + "@smithy/fetch-http-handler": "^5.2.1", + "@smithy/node-http-handler": "^4.2.1", + "@smithy/property-provider": "^4.0.5", + "@smithy/protocol-http": "^5.2.1", + "@smithy/smithy-client": "^4.6.1", + "@smithy/types": "^4.5.0", + "@smithy/util-stream": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.888.0.tgz", + "integrity": "sha512-M82ItvS5yq+tO6ZOV1ruaVs2xOne+v8HW85GFCXnz8pecrzYdgxh6IsVqEbbWruryG/mUGkWMbkBZoEsy4MgyA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.888.0", + "@aws-sdk/credential-provider-env": "3.888.0", + "@aws-sdk/credential-provider-http": "3.888.0", + "@aws-sdk/credential-provider-process": "3.888.0", + "@aws-sdk/credential-provider-sso": "3.888.0", + "@aws-sdk/credential-provider-web-identity": "3.888.0", + "@aws-sdk/nested-clients": "3.888.0", + "@aws-sdk/types": "3.887.0", + "@smithy/credential-provider-imds": "^4.0.7", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.888.0.tgz", + "integrity": "sha512-KCrQh1dCDC8Y+Ap3SZa6S81kHk+p+yAaOQ5jC3dak4zhHW3RCrsGR/jYdemTOgbEGcA6ye51UbhWfrrlMmeJSA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.888.0", + "@aws-sdk/credential-provider-http": "3.888.0", + "@aws-sdk/credential-provider-ini": "3.888.0", + "@aws-sdk/credential-provider-process": "3.888.0", + "@aws-sdk/credential-provider-sso": "3.888.0", + "@aws-sdk/credential-provider-web-identity": "3.888.0", + "@aws-sdk/types": "3.887.0", + "@smithy/credential-provider-imds": "^4.0.7", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.888.0.tgz", + "integrity": "sha512-+aX6piSukPQ8DUS4JAH344GePg8/+Q1t0+kvSHAZHhYvtQ/1Zek3ySOJWH2TuzTPCafY4nmWLcQcqvU1w9+4Lw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.888.0", + "@aws-sdk/types": "3.887.0", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.888.0.tgz", + "integrity": "sha512-b1ZJji7LJ6E/j1PhFTyvp51in2iCOQ3VP6mj5H6f5OUnqn7efm41iNMoinKr87n0IKZw7qput5ggXVxEdPhouA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.888.0", + "@aws-sdk/core": "3.888.0", + "@aws-sdk/token-providers": "3.888.0", + "@aws-sdk/types": "3.887.0", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.888.0.tgz", + "integrity": "sha512-7P0QNtsDzMZdmBAaY/vY1BsZHwTGvEz3bsn2bm5VSKFAeMmZqsHK1QeYdNsFjLtegnVh+wodxMq50jqLv3LFlA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.888.0", + "@aws-sdk/nested-clients": "3.888.0", + "@aws-sdk/types": "3.887.0", + "@smithy/property-provider": "^4.0.5", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.887.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.887.0.tgz", + "integrity": "sha512-ulzqXv6NNqdu/kr0sgBYupWmahISHY+azpJidtK6ZwQIC+vBUk9NdZeqQpy7KVhIk2xd4+5Oq9rxapPwPI21CA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.887.0", + "@smithy/protocol-http": "^5.2.1", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/middleware-logger": { + "version": "3.887.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.887.0.tgz", + "integrity": "sha512-YbbgLI6jKp2qSoAcHnXrQ5jcuc5EYAmGLVFgMVdk8dfCfJLfGGSaOLxF4CXC7QYhO50s+mPPkhBYejCik02Kug==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.887.0", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.887.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.887.0.tgz", + "integrity": "sha512-tjrUXFtQnFLo+qwMveq5faxP5MQakoLArXtqieHphSqZTXm21wDJM73hgT4/PQQGTwgYjDKqnqsE1hvk0hcfDw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.887.0", + "@aws/lambda-invoke-store": "^0.0.1", + "@smithy/protocol-http": "^5.2.1", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.888.0.tgz", + "integrity": "sha512-ZkcUkoys8AdrNNG7ATjqw2WiXqrhTvT+r4CIK3KhOqIGPHX0p0DQWzqjaIl7ZhSUToKoZ4Ud7MjF795yUr73oA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.888.0", + "@aws-sdk/types": "3.887.0", + "@aws-sdk/util-endpoints": "3.887.0", + "@smithy/core": "^3.11.0", + "@smithy/protocol-http": "^5.2.1", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/nested-clients": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.888.0.tgz", + "integrity": "sha512-py4o4RPSGt+uwGvSBzR6S6cCBjS4oTX5F8hrHFHfPCdIOMVjyOBejn820jXkCrcdpSj3Qg1yUZXxsByvxc9Lyg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.888.0", + "@aws-sdk/middleware-host-header": "3.887.0", + "@aws-sdk/middleware-logger": "3.887.0", + "@aws-sdk/middleware-recursion-detection": "3.887.0", + "@aws-sdk/middleware-user-agent": "3.888.0", + "@aws-sdk/region-config-resolver": "3.887.0", + "@aws-sdk/types": "3.887.0", + "@aws-sdk/util-endpoints": "3.887.0", + "@aws-sdk/util-user-agent-browser": "3.887.0", + "@aws-sdk/util-user-agent-node": "3.888.0", + "@smithy/config-resolver": "^4.2.1", + "@smithy/core": "^3.11.0", + "@smithy/fetch-http-handler": "^5.2.1", + "@smithy/hash-node": "^4.1.1", + "@smithy/invalid-dependency": "^4.1.1", + "@smithy/middleware-content-length": "^4.1.1", + "@smithy/middleware-endpoint": "^4.2.1", + "@smithy/middleware-retry": "^4.2.1", + "@smithy/middleware-serde": "^4.1.1", + "@smithy/middleware-stack": "^4.1.1", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/node-http-handler": "^4.2.1", + "@smithy/protocol-http": "^5.2.1", + "@smithy/smithy-client": "^4.6.1", + "@smithy/types": "^4.5.0", + "@smithy/url-parser": "^4.1.1", + "@smithy/util-base64": "^4.1.0", + "@smithy/util-body-length-browser": "^4.1.0", + "@smithy/util-body-length-node": "^4.1.0", + "@smithy/util-defaults-mode-browser": "^4.1.1", + "@smithy/util-defaults-mode-node": "^4.1.1", + "@smithy/util-endpoints": "^3.1.1", + "@smithy/util-middleware": "^4.1.1", + "@smithy/util-retry": "^4.1.1", + "@smithy/util-utf8": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.887.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.887.0.tgz", + "integrity": "sha512-VdSMrIqJ3yjJb/fY+YAxrH/lCVv0iL8uA+lbMNfQGtO5tB3Zx6SU9LEpUwBNX8fPK1tUpI65CNE4w42+MY/7Mg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.887.0", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/types": "^4.5.0", + "@smithy/util-config-provider": "^4.0.0", + "@smithy/util-middleware": "^4.1.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/token-providers": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.888.0.tgz", + "integrity": "sha512-WA3NF+3W8GEuCMG1WvkDYbB4z10G3O8xuhT7QSjhvLYWQ9CPt3w4VpVIfdqmUn131TCIbhCzD0KN/1VJTjAjyw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.888.0", + "@aws-sdk/nested-clients": "3.888.0", + "@aws-sdk/types": "3.887.0", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/types": { + "version": "3.887.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.887.0.tgz", + "integrity": "sha512-fmTEJpUhsPsovQ12vZSpVTEP/IaRoJAMBGQXlQNjtCpkBp6Iq3KQDa/HDaPINE+3xxo6XvTdtibsNOd5zJLV9A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/util-endpoints": { + "version": "3.887.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.887.0.tgz", + "integrity": "sha512-kpegvT53KT33BMeIcGLPA65CQVxLUL/C3gTz9AzlU/SDmeusBHX4nRApAicNzI/ltQ5lxZXbQn18UczzBuwF1w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.887.0", + "@smithy/types": "^4.5.0", + "@smithy/url-parser": "^4.1.1", + "@smithy/util-endpoints": "^3.1.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.887.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.887.0.tgz", + "integrity": "sha512-X71UmVsYc6ZTH4KU6hA5urOzYowSXc3qvroagJNLJYU1ilgZ529lP4J9XOYfEvTXkLR1hPFSRxa43SrwgelMjA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.887.0", + "@smithy/types": "^4.5.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.888.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.888.0.tgz", + "integrity": "sha512-rSB3OHyuKXotIGfYEo//9sU0lXAUrTY28SUUnxzOGYuQsAt0XR5iYwBAp+RjV6x8f+Hmtbg0PdCsy1iNAXa0UQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.888.0", + "@aws-sdk/types": "3.887.0", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@aws-sdk/xml-builder": { + "version": "3.887.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.887.0.tgz", + "integrity": "sha512-lMwgWK1kNgUhHGfBvO/5uLe7TKhycwOn3eRCqsKPT9aPCx/HWuTlpcQp8oW2pCRGLS7qzcxqpQulcD+bbUL7XQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@smithy/util-utf8": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.1.0.tgz", + "integrity": "sha512-mEu1/UIXAdNYuBcyEPbjScKi/+MQVXNIuY/7Cm5XLIWe319kDrT5SizBE95jqtmEXoDbGoZxKLCMttdZdqTZKQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/types": { "version": "3.862.0", "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.862.0.tgz", @@ -8649,6 +9070,15 @@ "constructs": "^10.0.0" } }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.0.1.tgz", + "integrity": "sha512-ORHRQ2tmvnBXc8t/X9Z8IcSbBA4xTLKuN873FopzklHMeqBst7YG0d+AX97inkvDX+NChYtSr+qGfcqGFaI8Zw==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -13567,12 +13997,12 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.5.tgz", - "integrity": "sha512-jcrqdTQurIrBbUm4W2YdLVMQDoL0sA9DTxYd2s+R/y+2U9NLOP7Xf/YqfSg1FZhlZIYEnvk2mwbyvIfdLEPo8g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.1.1.tgz", + "integrity": "sha512-vkzula+IwRvPR6oKQhMYioM3A/oX/lFCZiwuxkQbRhqJS2S4YRY2k7k/SyR2jMf3607HLtbEwlRxi0ndXHMjRg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.2", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -13605,15 +14035,15 @@ } }, "node_modules/@smithy/config-resolver": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.5.tgz", - "integrity": "sha512-viuHMxBAqydkB0AfWwHIdwf/PRH2z5KHGUzqyRtS/Wv+n3IHI993Sk76VCA7dD/+GzgGOmlJDITfPcJC1nIVIw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.2.1.tgz", + "integrity": "sha512-FXil8q4QN7mgKwU2hCLm0ltab8NyY/1RiqEf25Jnf6WLS3wmb11zGAoLETqg1nur2Aoibun4w4MjeN9CMJ4G6A==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.4", - "@smithy/types": "^4.3.2", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.5", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/types": "^4.5.0", + "@smithy/util-config-provider": "^4.1.0", + "@smithy/util-middleware": "^4.1.1", "tslib": "^2.6.2" }, "engines": { @@ -13621,19 +14051,19 @@ } }, "node_modules/@smithy/core": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.8.0.tgz", - "integrity": "sha512-EYqsIYJmkR1VhVE9pccnk353xhs+lB6btdutJEtsp7R055haMJp2yE16eSxw8fv+G0WUY6vqxyYOP8kOqawxYQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/middleware-serde": "^4.0.9", - "@smithy/protocol-http": "^5.1.3", - "@smithy/types": "^4.3.2", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.5", - "@smithy/util-stream": "^4.2.4", - "@smithy/util-utf8": "^4.0.0", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.11.0.tgz", + "integrity": "sha512-Abs5rdP1o8/OINtE49wwNeWuynCu0kme1r4RI3VXVrHr4odVDG7h7mTnw1WXXfN5Il+c25QOnrdL2y56USfxkA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/middleware-serde": "^4.1.1", + "@smithy/protocol-http": "^5.2.1", + "@smithy/types": "^4.5.0", + "@smithy/util-base64": "^4.1.0", + "@smithy/util-body-length-browser": "^4.1.0", + "@smithy/util-middleware": "^4.1.1", + "@smithy/util-stream": "^4.3.1", + "@smithy/util-utf8": "^4.1.0", "@types/uuid": "^9.0.1", "tslib": "^2.6.2", "uuid": "^9.0.1" @@ -13643,12 +14073,12 @@ } }, "node_modules/@smithy/core/node_modules/@smithy/util-utf8": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", - "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.1.0.tgz", + "integrity": "sha512-mEu1/UIXAdNYuBcyEPbjScKi/+MQVXNIuY/7Cm5XLIWe319kDrT5SizBE95jqtmEXoDbGoZxKLCMttdZdqTZKQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-buffer-from": "^4.1.0", "tslib": "^2.6.2" }, "engines": { @@ -13656,15 +14086,15 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.7.tgz", - "integrity": "sha512-dDzrMXA8d8riFNiPvytxn0mNwR4B3h8lgrQ5UjAGu6T9z/kRg/Xncf4tEQHE/+t25sY8IH3CowcmWi+1U5B1Gw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.1.1.tgz", + "integrity": "sha512-1WdBfM9DwA59pnpIizxnUvBf/de18p4GP+6zP2AqrlFzoW3ERpZaT4QueBR0nS9deDMaQRkBlngpVlnkuuTisQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.4", - "@smithy/property-provider": "^4.0.5", - "@smithy/types": "^4.3.2", - "@smithy/url-parser": "^4.0.5", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/property-provider": "^4.1.1", + "@smithy/types": "^4.5.0", + "@smithy/url-parser": "^4.1.1", "tslib": "^2.6.2" }, "engines": { @@ -13754,15 +14184,15 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.1.tgz", - "integrity": "sha512-61WjM0PWmZJR+SnmzaKI7t7G0UkkNFboDpzIdzSoy7TByUzlxo18Qlh9s71qug4AY4hlH/CwXdubMtkcNEb/sQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.2.1.tgz", + "integrity": "sha512-5/3wxKNtV3wO/hk1is+CZUhL8a1yy/U+9u9LKQ9kZTkMsHaQjJhc3stFfiujtMnkITjzWfndGA2f7g9Uh9vKng==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.3", - "@smithy/querystring-builder": "^4.0.5", - "@smithy/types": "^4.3.2", - "@smithy/util-base64": "^4.0.0", + "@smithy/protocol-http": "^5.2.1", + "@smithy/querystring-builder": "^4.1.1", + "@smithy/types": "^4.5.0", + "@smithy/util-base64": "^4.1.0", "tslib": "^2.6.2" }, "engines": { @@ -13785,14 +14215,14 @@ } }, "node_modules/@smithy/hash-node": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.5.tgz", - "integrity": "sha512-cv1HHkKhpyRb6ahD8Vcfb2Hgz67vNIXEp2vnhzfxLFGRukLCNEA5QdsorbUEzXma1Rco0u3rx5VTqbM06GcZqQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.1.1.tgz", + "integrity": "sha512-H9DIU9WBLhYrvPs9v4sYvnZ1PiAI0oc8CgNQUJ1rpN3pP7QADbTOUjchI2FB764Ub0DstH5xbTqcMJu1pnVqxA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.2", - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", + "@smithy/types": "^4.5.0", + "@smithy/util-buffer-from": "^4.1.0", + "@smithy/util-utf8": "^4.1.0", "tslib": "^2.6.2" }, "engines": { @@ -13800,12 +14230,12 @@ } }, "node_modules/@smithy/hash-node/node_modules/@smithy/util-utf8": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", - "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.1.0.tgz", + "integrity": "sha512-mEu1/UIXAdNYuBcyEPbjScKi/+MQVXNIuY/7Cm5XLIWe319kDrT5SizBE95jqtmEXoDbGoZxKLCMttdZdqTZKQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-buffer-from": "^4.1.0", "tslib": "^2.6.2" }, "engines": { @@ -13840,12 +14270,12 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.5.tgz", - "integrity": "sha512-IVnb78Qtf7EJpoEVo7qJ8BEXQwgC4n3igeJNNKEj/MLYtapnx8A67Zt/J3RXAj2xSO1910zk0LdFiygSemuLow==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.1.1.tgz", + "integrity": "sha512-1AqLyFlfrrDkyES8uhINRlJXmHA2FkG+3DY8X+rmLSqmFwk3DJnvhyGzyByPyewh2jbmV+TYQBEfngQax8IFGg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.2", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -13853,9 +14283,9 @@ } }, "node_modules/@smithy/is-array-buffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz", - "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.1.0.tgz", + "integrity": "sha512-ePTYUOV54wMogio+he4pBybe8fwg4sDvEVDBU8ZlHOZXbXK3/C0XfJgUCu6qAZcawv05ZhZzODGUerFBPsPUDQ==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -13892,13 +14322,13 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.5.tgz", - "integrity": "sha512-l1jlNZoYzoCC7p0zCtBDE5OBXZ95yMKlRlftooE5jPWQn4YBPLgsp+oeHp7iMHaTGoUdFqmHOPa8c9G3gBsRpQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.1.1.tgz", + "integrity": "sha512-9wlfBBgTsRvC2JxLJxv4xDGNBrZuio3AgSl0lSFX7fneW2cGskXTYpFxCdRYD2+5yzmsiTuaAJD1Wp7gWt9y9w==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.3", - "@smithy/types": "^4.3.2", + "@smithy/protocol-http": "^5.2.1", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -13906,18 +14336,18 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.18.tgz", - "integrity": "sha512-ZhvqcVRPZxnZlokcPaTwb+r+h4yOIOCJmx0v2d1bpVlmP465g3qpVSf7wxcq5zZdu4jb0H4yIMxuPwDJSQc3MQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.2.1.tgz", + "integrity": "sha512-fUTMmQvQQZakXOuKizfu7fBLDpwvWZjfH6zUK2OLsoNZRZGbNUdNSdLJHpwk1vS208jtDjpUIskh+JoA8zMzZg==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.8.0", - "@smithy/middleware-serde": "^4.0.9", - "@smithy/node-config-provider": "^4.1.4", - "@smithy/shared-ini-file-loader": "^4.0.5", - "@smithy/types": "^4.3.2", - "@smithy/url-parser": "^4.0.5", - "@smithy/util-middleware": "^4.0.5", + "@smithy/core": "^3.11.0", + "@smithy/middleware-serde": "^4.1.1", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/shared-ini-file-loader": "^4.1.1", + "@smithy/types": "^4.5.0", + "@smithy/url-parser": "^4.1.1", + "@smithy/util-middleware": "^4.1.1", "tslib": "^2.6.2" }, "engines": { @@ -13925,18 +14355,18 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.1.19", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.19.tgz", - "integrity": "sha512-X58zx/NVECjeuUB6A8HBu4bhx72EoUz+T5jTMIyeNKx2lf+Gs9TmWPNNkH+5QF0COjpInP/xSpJGJ7xEnAklQQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.2.1.tgz", + "integrity": "sha512-JzfvjwSJXWRl7LkLgIRTUTd2Wj639yr3sQGpViGNEOjtb0AkAuYqRAHs+jSOI/LPC0ZTjmFVVtfrCICMuebexw==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.4", - "@smithy/protocol-http": "^5.1.3", - "@smithy/service-error-classification": "^4.0.7", - "@smithy/smithy-client": "^4.4.10", - "@smithy/types": "^4.3.2", - "@smithy/util-middleware": "^4.0.5", - "@smithy/util-retry": "^4.0.7", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/protocol-http": "^5.2.1", + "@smithy/service-error-classification": "^4.1.1", + "@smithy/smithy-client": "^4.6.1", + "@smithy/types": "^4.5.0", + "@smithy/util-middleware": "^4.1.1", + "@smithy/util-retry": "^4.1.1", "@types/uuid": "^9.0.1", "tslib": "^2.6.2", "uuid": "^9.0.1" @@ -13946,13 +14376,13 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.9.tgz", - "integrity": "sha512-uAFFR4dpeoJPGz8x9mhxp+RPjo5wW0QEEIPPPbLXiRRWeCATf/Km3gKIVR5vaP8bN1kgsPhcEeh+IZvUlBv6Xg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.1.1.tgz", + "integrity": "sha512-lh48uQdbCoj619kRouev5XbWhCwRKLmphAif16c4J6JgJ4uXjub1PI6RL38d3BLliUvSso6klyB/LTNpWSNIyg==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.3", - "@smithy/types": "^4.3.2", + "@smithy/protocol-http": "^5.2.1", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -13960,12 +14390,12 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.5.tgz", - "integrity": "sha512-/yoHDXZPh3ocRVyeWQFvC44u8seu3eYzZRveCMfgMOBcNKnAmOvjbL9+Cp5XKSIi9iYA9PECUuW2teDAk8T+OQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.1.1.tgz", + "integrity": "sha512-ygRnniqNcDhHzs6QAPIdia26M7e7z9gpkIMUe/pK0RsrQ7i5MblwxY8078/QCnGq6AmlUUWgljK2HlelsKIb/A==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.2", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -13973,14 +14403,14 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.4.tgz", - "integrity": "sha512-+UDQV/k42jLEPPHSn39l0Bmc4sB1xtdI9Gd47fzo/0PbXzJ7ylgaOByVjF5EeQIumkepnrJyfx86dPa9p47Y+w==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.2.1.tgz", + "integrity": "sha512-AIA0BJZq2h295J5NeCTKhg1WwtdTA/GqBCaVjk30bDgMHwniUETyh5cP9IiE9VrId7Kt8hS7zvREVMTv1VfA6g==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.0.5", - "@smithy/shared-ini-file-loader": "^4.0.5", - "@smithy/types": "^4.3.2", + "@smithy/property-provider": "^4.1.1", + "@smithy/shared-ini-file-loader": "^4.1.1", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -13988,15 +14418,15 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.1.1.tgz", - "integrity": "sha512-RHnlHqFpoVdjSPPiYy/t40Zovf3BBHc2oemgD7VsVTFFZrU5erFFe0n52OANZZ/5sbshgD93sOh5r6I35Xmpaw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.2.1.tgz", + "integrity": "sha512-REyybygHlxo3TJICPF89N2pMQSf+p+tBJqpVe1+77Cfi9HBPReNjTgtZ1Vg73exq24vkqJskKDpfF74reXjxfw==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.0.5", - "@smithy/protocol-http": "^5.1.3", - "@smithy/querystring-builder": "^4.0.5", - "@smithy/types": "^4.3.2", + "@smithy/abort-controller": "^4.1.1", + "@smithy/protocol-http": "^5.2.1", + "@smithy/querystring-builder": "^4.1.1", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -14004,12 +14434,12 @@ } }, "node_modules/@smithy/property-provider": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.5.tgz", - "integrity": "sha512-R/bswf59T/n9ZgfgUICAZoWYKBHcsVDurAGX88zsiUtOTA/xUAPyiT+qkNCPwFn43pZqN84M4MiUsbSGQmgFIQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.1.1.tgz", + "integrity": "sha512-gm3ZS7DHxUbzC2wr8MUCsAabyiXY0gaj3ROWnhSx/9sPMc6eYLMM4rX81w1zsMaObj2Lq3PZtNCC1J6lpEY7zg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.2", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -14017,12 +14447,12 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.3.tgz", - "integrity": "sha512-fCJd2ZR7D22XhDY0l+92pUag/7je2BztPRQ01gU5bMChcyI0rlly7QFibnYHzcxDvccMjlpM/Q1ev8ceRIb48w==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.2.1.tgz", + "integrity": "sha512-T8SlkLYCwfT/6m33SIU/JOVGNwoelkrvGjFKDSDtVvAXj/9gOT78JVJEas5a+ETjOu4SVvpCstKgd0PxSu/aHw==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.2", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -14030,13 +14460,13 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.5.tgz", - "integrity": "sha512-NJeSCU57piZ56c+/wY+AbAw6rxCCAOZLCIniRE7wqvndqxcKKDOXzwWjrY7wGKEISfhL9gBbAaWWgHsUGedk+A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.1.1.tgz", + "integrity": "sha512-J9b55bfimP4z/Jg1gNo+AT84hr90p716/nvxDkPGCD4W70MPms0h8KF50RDRgBGZeL83/u59DWNqJv6tEP/DHA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.2", - "@smithy/util-uri-escape": "^4.0.0", + "@smithy/types": "^4.5.0", + "@smithy/util-uri-escape": "^4.1.0", "tslib": "^2.6.2" }, "engines": { @@ -14044,12 +14474,12 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.5.tgz", - "integrity": "sha512-6SV7md2CzNG/WUeTjVe6Dj8noH32r4MnUeFKZrnVYsQxpGSIcphAanQMayi8jJLZAWm6pdM9ZXvKCpWOsIGg0w==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.1.1.tgz", + "integrity": "sha512-63TEp92YFz0oQ7Pj9IuI3IgnprP92LrZtRAkE3c6wLWJxfy/yOPRt39IOKerVr0JS770olzl0kGafXlAXZ1vng==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.2", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -14057,24 +14487,24 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.7.tgz", - "integrity": "sha512-XvRHOipqpwNhEjDf2L5gJowZEm5nsxC16pAZOeEcsygdjv9A2jdOh3YoDQvOXBGTsaJk6mNWtzWalOB9976Wlg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.1.1.tgz", + "integrity": "sha512-Iam75b/JNXyDE41UvrlM6n8DNOa/r1ylFyvgruTUx7h2Uk7vDNV9AAwP1vfL1fOL8ls0xArwEGVcGZVd7IO/Cw==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.2" + "@smithy/types": "^4.5.0" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.5.tgz", - "integrity": "sha512-YVVwehRDuehgoXdEL4r1tAAzdaDgaC9EQvhK0lEbfnbrd0bd5+CTQumbdPryX3J2shT7ZqQE+jPW4lmNBAB8JQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.1.1.tgz", + "integrity": "sha512-YkpikhIqGc4sfXeIbzSj10t2bJI/sSoP5qxLue6zG+tEE3ngOBSm8sO3+djacYvS/R5DfpxN/L9CyZsvwjWOAQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.2", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -14126,17 +14556,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.10.tgz", - "integrity": "sha512-iW6HjXqN0oPtRS0NK/zzZ4zZeGESIFcxj2FkWed3mcK8jdSdHzvnCKXSjvewESKAgGKAbJRA+OsaqKhkdYRbQQ==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.6.1.tgz", + "integrity": "sha512-WolVLDb9UTPMEPPOncrCt6JmAMCSC/V2y5gst2STWJ5r7+8iNac+EFYQnmvDCYMfOLcilOSEpm5yXZXwbLak1Q==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.8.0", - "@smithy/middleware-endpoint": "^4.1.18", - "@smithy/middleware-stack": "^4.0.5", - "@smithy/protocol-http": "^5.1.3", - "@smithy/types": "^4.3.2", - "@smithy/util-stream": "^4.2.4", + "@smithy/core": "^3.11.0", + "@smithy/middleware-endpoint": "^4.2.1", + "@smithy/middleware-stack": "^4.1.1", + "@smithy/protocol-http": "^5.2.1", + "@smithy/types": "^4.5.0", + "@smithy/util-stream": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -14144,9 +14574,9 @@ } }, "node_modules/@smithy/types": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.2.tgz", - "integrity": "sha512-QO4zghLxiQ5W9UZmX2Lo0nta2PuE1sSrXUYDoaB6HMR762C0P7v/HEPHf6ZdglTVssJG1bsrSBxdc3quvDSihw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.5.0.tgz", + "integrity": "sha512-RkUpIOsVlAwUIZXO1dsz8Zm+N72LClFfsNqf173catVlvRZiwPy0x2u0JLEA4byreOPKDZPGjmPDylMoP8ZJRg==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -14156,13 +14586,13 @@ } }, "node_modules/@smithy/url-parser": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.5.tgz", - "integrity": "sha512-j+733Um7f1/DXjYhCbvNXABV53NyCRRA54C7bNEIxNPs0YjfRxeMKjjgm2jvTYrciZyCjsicHwQ6Q0ylo+NAUw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.1.1.tgz", + "integrity": "sha512-bx32FUpkhcaKlEoOMbScvc93isaSiRM75pQ5IgIBaMkT7qMlIibpPRONyx/0CvrXHzJLpOn/u6YiDX2hcvs7Dg==", "license": "Apache-2.0", "dependencies": { - "@smithy/querystring-parser": "^4.0.5", - "@smithy/types": "^4.3.2", + "@smithy/querystring-parser": "^4.1.1", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -14170,13 +14600,13 @@ } }, "node_modules/@smithy/util-base64": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz", - "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.1.0.tgz", + "integrity": "sha512-RUGd4wNb8GeW7xk+AY5ghGnIwM96V0l2uzvs/uVHf+tIuVX2WSvynk5CxNoBCsM2rQRSZElAo9rt3G5mJ/gktQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", + "@smithy/util-buffer-from": "^4.1.0", + "@smithy/util-utf8": "^4.1.0", "tslib": "^2.6.2" }, "engines": { @@ -14184,12 +14614,12 @@ } }, "node_modules/@smithy/util-base64/node_modules/@smithy/util-utf8": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", - "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.1.0.tgz", + "integrity": "sha512-mEu1/UIXAdNYuBcyEPbjScKi/+MQVXNIuY/7Cm5XLIWe319kDrT5SizBE95jqtmEXoDbGoZxKLCMttdZdqTZKQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-buffer-from": "^4.1.0", "tslib": "^2.6.2" }, "engines": { @@ -14197,9 +14627,9 @@ } }, "node_modules/@smithy/util-body-length-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz", - "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.1.0.tgz", + "integrity": "sha512-V2E2Iez+bo6bUMOTENPr6eEmepdY8Hbs+Uc1vkDKgKNA/brTJqOW/ai3JO1BGj9GbCeLqw90pbbH7HFQyFotGQ==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -14209,9 +14639,9 @@ } }, "node_modules/@smithy/util-body-length-node": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz", - "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.1.0.tgz", + "integrity": "sha512-BOI5dYjheZdgR9XiEM3HJcEMCXSoqbzu7CzIgYrx0UtmvtC3tC2iDGpJLsSRFffUpy8ymsg2ARMP5fR8mtuUQQ==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -14221,12 +14651,12 @@ } }, "node_modules/@smithy/util-buffer-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", - "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.1.0.tgz", + "integrity": "sha512-N6yXcjfe/E+xKEccWEKzK6M+crMrlwaCepKja0pNnlSkm6SjAeLKKA++er5Ba0I17gvKfN/ThV+ZOx/CntKTVw==", "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": "^4.0.0", + "@smithy/is-array-buffer": "^4.1.0", "tslib": "^2.6.2" }, "engines": { @@ -14234,9 +14664,9 @@ } }, "node_modules/@smithy/util-config-provider": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz", - "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.1.0.tgz", + "integrity": "sha512-swXz2vMjrP1ZusZWVTB/ai5gK+J8U0BWvP10v9fpcFvg+Xi/87LHvHfst2IgCs1i0v4qFZfGwCmeD/KNCdJZbQ==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -14246,14 +14676,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.26", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.26.tgz", - "integrity": "sha512-xgl75aHIS/3rrGp7iTxQAOELYeyiwBu+eEgAk4xfKwJJ0L8VUjhO2shsDpeil54BOFsqmk5xfdesiewbUY5tKQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.1.1.tgz", + "integrity": "sha512-hA1AKIHFUMa9Tl6q6y8p0pJ9aWHCCG8s57flmIyLE0W7HcJeYrYtnqXDcGnftvXEhdQnSexyegXnzzTGk8bKLA==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.0.5", - "@smithy/smithy-client": "^4.4.10", - "@smithy/types": "^4.3.2", + "@smithy/property-provider": "^4.1.1", + "@smithy/smithy-client": "^4.6.1", + "@smithy/types": "^4.5.0", "bowser": "^2.11.0", "tslib": "^2.6.2" }, @@ -14262,17 +14692,17 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.26", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.26.tgz", - "integrity": "sha512-z81yyIkGiLLYVDetKTUeCZQ8x20EEzvQjrqJtb/mXnevLq2+w3XCEWTJ2pMp401b6BkEkHVfXb/cROBpVauLMQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.1.1.tgz", + "integrity": "sha512-RGSpmoBrA+5D2WjwtK7tto6Pc2wO9KSXKLpLONhFZ8VyuCbqlLdiDAfuDTNY9AJe4JoE+Cx806cpTQQoQ71zPQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/config-resolver": "^4.1.5", - "@smithy/credential-provider-imds": "^4.0.7", - "@smithy/node-config-provider": "^4.1.4", - "@smithy/property-provider": "^4.0.5", - "@smithy/smithy-client": "^4.4.10", - "@smithy/types": "^4.3.2", + "@smithy/config-resolver": "^4.2.1", + "@smithy/credential-provider-imds": "^4.1.1", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/property-provider": "^4.1.1", + "@smithy/smithy-client": "^4.6.1", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -14280,13 +14710,13 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.7.tgz", - "integrity": "sha512-klGBP+RpBp6V5JbrY2C/VKnHXn3d5V2YrifZbmMY8os7M6m8wdYFoO6w/fe5VkP+YVwrEktW3IWYaSQVNZJ8oQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.1.1.tgz", + "integrity": "sha512-qB4R9kO0SetA11Rzu6MVGFIaGYX3p6SGGGfWwsKnC6nXIf0n/0AKVwRTsYsz9ToN8CeNNtNgQRwKFBndGJZdyw==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.4", - "@smithy/types": "^4.3.2", + "@smithy/node-config-provider": "^4.2.1", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -14306,12 +14736,12 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.5.tgz", - "integrity": "sha512-N40PfqsZHRSsByGB81HhSo+uvMxEHT+9e255S53pfBw/wI6WKDI7Jw9oyu5tJTLwZzV5DsMha3ji8jk9dsHmQQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.1.1.tgz", + "integrity": "sha512-CGmZ72mL29VMfESz7S6dekqzCh8ZISj3B+w0g1hZFXaOjGTVaSqfAEFAq8EGp8fUL+Q2l8aqNmt8U1tglTikeg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.2", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -14319,13 +14749,13 @@ } }, "node_modules/@smithy/util-retry": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.7.tgz", - "integrity": "sha512-TTO6rt0ppK70alZpkjwy+3nQlTiqNfoXja+qwuAchIEAIoSZW8Qyd76dvBv3I5bCpE38APafG23Y/u270NspiQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.1.1.tgz", + "integrity": "sha512-jGeybqEZ/LIordPLMh5bnmnoIgsqnp4IEimmUp5c5voZ8yx+5kAlN5+juyr7p+f7AtZTgvhmInQk4Q0UVbrZ0Q==", "license": "Apache-2.0", "dependencies": { - "@smithy/service-error-classification": "^4.0.7", - "@smithy/types": "^4.3.2", + "@smithy/service-error-classification": "^4.1.1", + "@smithy/types": "^4.5.0", "tslib": "^2.6.2" }, "engines": { @@ -14333,18 +14763,18 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.4.tgz", - "integrity": "sha512-vSKnvNZX2BXzl0U2RgCLOwWaAP9x/ddd/XobPK02pCbzRm5s55M53uwb1rl/Ts7RXZvdJZerPkA+en2FDghLuQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.3.1.tgz", + "integrity": "sha512-khKkW/Jqkgh6caxMWbMuox9+YfGlsk9OnHOYCGVEdYQb/XVzcORXHLYUubHmmda0pubEDncofUrPNniS9d+uAA==", "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^5.1.1", - "@smithy/node-http-handler": "^4.1.1", - "@smithy/types": "^4.3.2", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", + "@smithy/fetch-http-handler": "^5.2.1", + "@smithy/node-http-handler": "^4.2.1", + "@smithy/types": "^4.5.0", + "@smithy/util-base64": "^4.1.0", + "@smithy/util-buffer-from": "^4.1.0", + "@smithy/util-hex-encoding": "^4.1.0", + "@smithy/util-utf8": "^4.1.0", "tslib": "^2.6.2" }, "engines": { @@ -14352,9 +14782,9 @@ } }, "node_modules/@smithy/util-stream/node_modules/@smithy/util-hex-encoding": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz", - "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.1.0.tgz", + "integrity": "sha512-1LcueNN5GYC4tr8mo14yVYbh/Ur8jHhWOxniZXii+1+ePiIbsLZ5fEI0QQGtbRRP5mOhmooos+rLmVASGGoq5w==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -14364,12 +14794,12 @@ } }, "node_modules/@smithy/util-stream/node_modules/@smithy/util-utf8": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", - "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.1.0.tgz", + "integrity": "sha512-mEu1/UIXAdNYuBcyEPbjScKi/+MQVXNIuY/7Cm5XLIWe319kDrT5SizBE95jqtmEXoDbGoZxKLCMttdZdqTZKQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-buffer-from": "^4.1.0", "tslib": "^2.6.2" }, "engines": { @@ -14377,9 +14807,9 @@ } }, "node_modules/@smithy/util-uri-escape": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", - "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.1.0.tgz", + "integrity": "sha512-b0EFQkq35K5NHUYxU72JuoheM6+pytEVUGlTwiFxWFpmddA+Bpz3LgsPRIpBk8lnPE47yT7AF2Egc3jVnKLuPg==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -17137,9 +17567,9 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.210.0", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.210.0.tgz", - "integrity": "sha512-TSXaZLHKak1bk144PblhqBHZwyh9lvlN2yM4g52aR/HCuxlw2nkn+eupjuOtiNe0JJFwSudvO/qke65dN2WlEg==", + "version": "2.217.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.217.0.tgz", + "integrity": "sha512-vPxTMF3IDW0Bf5m07yxebWjzZhd5/DcEPKusu4F9krnTORhx2UMqcTyvAmb7SLbi2+FrKYhP5w4nPBNxf8LhHA==", "bundleDependencies": [ "@balena/dockerignore", "case", @@ -17157,10 +17587,10 @@ "dependencies": { "@aws-cdk/asset-awscli-v1": "2.2.242", "@aws-cdk/asset-node-proxy-agent-v6": "^2.1.0", - "@aws-cdk/cloud-assembly-schema": "^48.2.0", + "@aws-cdk/cloud-assembly-schema": "^48.6.0", "@balena/dockerignore": "^1.0.2", "case": "1.6.3", - "fs-extra": "^11.3.0", + "fs-extra": "^11.3.1", "ignore": "^5.3.2", "jsonschema": "^1.5.0", "mime-types": "^2.1.35", @@ -17281,7 +17711,7 @@ "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/fast-uri": { - "version": "3.0.6", + "version": "3.1.0", "funding": [ { "type": "github", @@ -17296,7 +17726,7 @@ "license": "BSD-3-Clause" }, "node_modules/aws-cdk-lib/node_modules/fs-extra": { - "version": "11.3.0", + "version": "11.3.1", "inBundle": true, "license": "MIT", "dependencies": { @@ -17335,7 +17765,7 @@ "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/jsonfile": { - "version": "6.1.0", + "version": "6.2.0", "inBundle": true, "license": "MIT", "dependencies": { @@ -31324,7 +31754,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver" @@ -35427,12 +35856,12 @@ "packages/cdk": { "hasInstallScript": true, "dependencies": { - "@aws-cdk/aws-lambda-python-alpha": "^2.154.1-alpha.0", + "@aws-cdk/aws-lambda-python-alpha": "^2.217.0-alpha.0", "@aws-sdk/client-bedrock-agent": "^3.755.0", "@aws-sdk/client-bedrock-agent-runtime": "^3.755.0", "@aws-sdk/client-bedrock-agentcore": "^3.755.0", - "@aws-sdk/client-bedrock-agentcore-control": "^3.755.0", "@aws-sdk/client-bedrock-runtime": "^3.755.0", + "@aws-sdk/client-cognito-identity-provider": "^3.755.0", "@aws-sdk/client-dynamodb": "^3.755.0", "@aws-sdk/client-kendra": "^3.755.0", "@aws-sdk/client-lambda": "^3.755.0", @@ -35446,7 +35875,7 @@ "@aws-solutions-constructs/aws-cloudfront-s3": "^2.68.0", "@smithy/node-http-handler": "^4.0.4", "aws-amplify": "^6.14.2", - "aws-cdk-lib": "^2.154.1", + "aws-cdk-lib": "^2.217.0", "aws-jwt-verify": "^4.0.0", "constructs": "^10.3.0", "deploy-time-build": "^0.3.17", @@ -35454,6 +35883,7 @@ "sanitize-html": "^2.13.0", "source-map-support": "^0.5.21", "upsert-slr": "^1.0.4", + "uuid": "13.0.0", "ws": "^8.18.0", "zod": "^3.24.1" }, @@ -35464,7 +35894,7 @@ "@types/sanitize-html": "^2.13.0", "@typescript-eslint/eslint-plugin": "^7.6.0", "@typescript-eslint/parser": "^7.6.0", - "aws-cdk": "^2.154.1", + "aws-cdk": "^2.217.0", "eslint": "^8.56.0", "jest": "^29.7.0", "ts-jest": "^29.2.5", @@ -35472,6 +35902,19 @@ "typescript": "~5.4.5" } }, + "packages/cdk/node_modules/uuid": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, "packages/common": { "name": "@generative-ai-use-cases/common", "dependencies": { diff --git a/packages/cdk/custom-resources/agent-core-runtime/.gitignore b/packages/cdk/custom-resources/agent-core-runtime/.gitignore deleted file mode 100644 index 9cf4150d3..000000000 --- a/packages/cdk/custom-resources/agent-core-runtime/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# TypeScript compilation outputs -*.js -*.d.ts -*.js.map - -# Dependencies -node_modules/ - -# Logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Coverage directory used by tools like istanbul -coverage/ - -# Editor directories and files -.vscode/ -.idea/ -*.swp -*.swo \ No newline at end of file diff --git a/packages/cdk/custom-resources/agent-core-runtime/index.ts b/packages/cdk/custom-resources/agent-core-runtime/index.ts deleted file mode 100644 index d896f9039..000000000 --- a/packages/cdk/custom-resources/agent-core-runtime/index.ts +++ /dev/null @@ -1,301 +0,0 @@ -import { - BedrockAgentCoreControlClient, - CreateAgentRuntimeCommand, - UpdateAgentRuntimeCommand, - DeleteAgentRuntimeCommand, - CreateAgentRuntimeRequest, - UpdateAgentRuntimeRequest, -} from '@aws-sdk/client-bedrock-agentcore-control'; - -// Types for Custom Resource -interface CloudFormationCustomResourceEvent { - RequestType: 'Create' | 'Update' | 'Delete'; - ResponseURL: string; - StackId: string; - RequestId: string; - ResourceType: string; - LogicalResourceId: string; - ResourceProperties: { - AgentCoreRuntimeName: string; - RoleArn: string; - NetworkMode: string; - ServerProtocol: string; - CustomConfig: Record; - }; - PhysicalResourceId?: string; -} - -interface AgentCoreRuntimeConfig { - name: string; - roleArn: string; - networkMode: string; - serverProtocol: string; - containerImageUri: string; - environmentVariables?: Record; -} - -interface CustomResourceResponse { - PhysicalResourceId: string; - Data?: { - AgentCoreRuntimeId: string; - AgentCoreRuntimeArn: string; - }; -} - -/** - * Create AgentCore Runtime using AWS SDK - */ -async function createAgentRuntime( - client: BedrockAgentCoreControlClient, - config: AgentCoreRuntimeConfig -): Promise<{ agentRuntimeId: string; agentRuntimeArn: string }> { - console.log(`Creating AgentCore Runtime: ${config.name}`); - - if (!config.containerImageUri) { - throw new Error('containerImageUri is required for AgentCore Runtime'); - } - if (!config.serverProtocol) { - throw new Error('serverProtocol is required for AgentCore Runtime'); - } - - const createParams: CreateAgentRuntimeRequest = { - agentRuntimeName: config.name, - agentRuntimeArtifact: { - containerConfiguration: { - containerUri: config.containerImageUri, - }, - }, - roleArn: config.roleArn, - networkConfiguration: { - networkMode: (config.networkMode === 'DEFAULT' - ? 'PUBLIC' - : config.networkMode) as any, - }, - protocolConfiguration: { - serverProtocol: config.serverProtocol as any, - }, - ...(config.environmentVariables && { - environmentVariables: config.environmentVariables, - }), - }; - - console.log('Create parameters:', JSON.stringify(createParams, null, 2)); - - const command = new CreateAgentRuntimeCommand(createParams); - const response = await client.send(command); - - if (!response.agentRuntimeId || !response.agentRuntimeArn) { - throw new Error( - 'Failed to create AgentCore Runtime - missing ID or ARN in response' - ); - } - - console.log( - `Successfully created AgentCore Runtime: ${response.agentRuntimeId}` - ); - - return { - agentRuntimeId: response.agentRuntimeId, - agentRuntimeArn: response.agentRuntimeArn, - }; -} - -/** - * Update AgentCore Runtime using AWS SDK - */ -async function updateAgentRuntime( - client: BedrockAgentCoreControlClient, - agentRuntimeId: string, - config: AgentCoreRuntimeConfig -): Promise<{ agentRuntimeId: string; agentRuntimeArn: string }> { - console.log(`Updating AgentCore Runtime: ${agentRuntimeId}`); - - if (!config.containerImageUri) { - throw new Error( - 'containerImageUri is required for AgentCore Runtime update' - ); - } - if (!config.serverProtocol) { - throw new Error('serverProtocol is required for AgentCore Runtime update'); - } - - const updateParams: UpdateAgentRuntimeRequest = { - agentRuntimeId, - agentRuntimeArtifact: { - containerConfiguration: { - containerUri: config.containerImageUri, - }, - }, - roleArn: config.roleArn, - networkConfiguration: { - networkMode: (config.networkMode === 'DEFAULT' - ? 'PUBLIC' - : config.networkMode) as any, - }, - protocolConfiguration: { - serverProtocol: config.serverProtocol as any, - }, - ...(config.environmentVariables && { - environmentVariables: config.environmentVariables, - }), - }; - - console.log('Update parameters:', JSON.stringify(updateParams, null, 2)); - - const command = new UpdateAgentRuntimeCommand(updateParams); - const response = await client.send(command); - - console.log(`Successfully updated AgentCore Runtime: ${agentRuntimeId}`); - - return { - agentRuntimeId, - agentRuntimeArn: - response.agentRuntimeArn || - `arn:aws:bedrock-agentcore:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:runtime/${agentRuntimeId}`, - }; -} - -/** - * Delete AgentCore Runtime using AWS SDK - */ -async function deleteAgentRuntime( - client: BedrockAgentCoreControlClient, - agentRuntimeId: string -): Promise { - console.log(`Deleting AgentCore Runtime: ${agentRuntimeId}`); - - try { - const deleteParams = { agentRuntimeId }; - const command = new DeleteAgentRuntimeCommand(deleteParams); - await client.send(command); - console.log(`Successfully deleted AgentCore Runtime: ${agentRuntimeId}`); - } catch (error: any) { - console.log(`Delete error for AgentCore Runtime ${agentRuntimeId}:`, error); - - // Simplified error handling: Only handle resource not found - if ( - error.name === 'ResourceNotFoundException' || - error.message?.includes('not found') || - error.message?.includes('does not exist') - ) { - console.log( - `AgentCore Runtime ${agentRuntimeId} already deleted or not found` - ); - return; // Success case - } - - // For all other errors, let them bubble up - // CloudFormation will handle resource abandonment as designed - throw error; - } -} - -/** - * Main Lambda handler for CustomResource using Provider Framework - */ -export async function handler( - event: CloudFormationCustomResourceEvent -): Promise { - console.log('Received event:', JSON.stringify(event, null, 2)); - - const { RequestType, ResourceProperties, PhysicalResourceId } = event; - const { - AgentCoreRuntimeName: agentRuntimeName, - CustomConfig: customConfig = {}, - RoleArn: roleArn, - NetworkMode: networkMode, - ServerProtocol: serverProtocol, - } = ResourceProperties; - - // Extract configuration - const config: AgentCoreRuntimeConfig = { - name: agentRuntimeName, - roleArn, - networkMode, - serverProtocol, - containerImageUri: (customConfig as any).containerImageUri, - environmentVariables: (customConfig as any).environmentVariables, - }; - - const client = new BedrockAgentCoreControlClient({ - region: process.env.AWS_REGION, - }); - - try { - switch (RequestType) { - case 'Create': { - const { agentRuntimeId, agentRuntimeArn } = await createAgentRuntime( - client, - config - ); - - return { - PhysicalResourceId: agentRuntimeId, - Data: { - AgentCoreRuntimeId: agentRuntimeId, - AgentCoreRuntimeArn: agentRuntimeArn, - }, - }; - } - - case 'Update': { - if (!PhysicalResourceId) { - throw new Error('PhysicalResourceId is required for Update'); - } - - const { agentRuntimeId, agentRuntimeArn } = await updateAgentRuntime( - client, - PhysicalResourceId, - config - ); - - return { - PhysicalResourceId: agentRuntimeId, - Data: { - AgentCoreRuntimeId: agentRuntimeId, - AgentCoreRuntimeArn: agentRuntimeArn, - }, - }; - } - - case 'Delete': { - console.log( - `Processing Delete request for PhysicalResourceId: ${PhysicalResourceId}` - ); - - // Simple validation: Only process if we have a valid resource ID - if ( - !PhysicalResourceId || - PhysicalResourceId === 'deleted' || - PhysicalResourceId === 'failed' - ) { - console.log(`No valid resource to delete: ${PhysicalResourceId}`); - return { - PhysicalResourceId: PhysicalResourceId || 'deleted', - }; - } - - // Simple delete operation - let errors bubble up naturally - await deleteAgentRuntime(client, PhysicalResourceId); - - return { - PhysicalResourceId: PhysicalResourceId, - }; - } - - default: - throw new Error(`Unknown request type: ${RequestType}`); - } - } catch (error) { - console.error('Error processing request:', error); - console.log('Request details:', { - RequestType, - PhysicalResourceId, - LogicalResourceId: event.LogicalResourceId, - }); - - // Simple error handling: Re-throw the error - // Provider Framework will handle CloudFormation response - throw error; - } -} diff --git a/packages/cdk/custom-resources/agent-core-runtime/package-lock.json b/packages/cdk/custom-resources/agent-core-runtime/package-lock.json deleted file mode 100644 index 014820610..000000000 --- a/packages/cdk/custom-resources/agent-core-runtime/package-lock.json +++ /dev/null @@ -1,1318 +0,0 @@ -{ - "name": "agent-core-runtime-custom-resource", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "agent-core-runtime-custom-resource", - "version": "1.0.0", - "dependencies": { - "@aws-sdk/client-bedrock-agentcore-control": "^3.755.0" - }, - "devDependencies": { - "@types/node": "^20.0.0", - "typescript": "^5.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", - "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", - "license": "Apache-2.0", - "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-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==", - "license": "Apache-2.0", - "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==", - "license": "Apache-2.0", - "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==", - "license": "Apache-2.0", - "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", - "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", - "license": "Apache-2.0", - "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/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==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - } - }, - "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==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.222.0", - "@smithy/util-utf8": "^2.0.0", - "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==", - "license": "Apache-2.0", - "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==", - "license": "Apache-2.0", - "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==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-bedrock-agentcore-control": { - "version": "3.848.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-agentcore-control/-/client-bedrock-agentcore-control-3.848.0.tgz", - "integrity": "sha512-mePD3XiAHt1Jc2d0A6wJa00IXGiHEIJKobYpSwmR18w5O47reOVf2PANkTC2t9nQ7LwfZQ5VI5eYLfpI2Gn3DA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.846.0", - "@aws-sdk/credential-provider-node": "3.848.0", - "@aws-sdk/middleware-host-header": "3.840.0", - "@aws-sdk/middleware-logger": "3.840.0", - "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.848.0", - "@aws-sdk/region-config-resolver": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.848.0", - "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.848.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.7.0", - "@smithy/fetch-http-handler": "^5.1.0", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.15", - "@smithy/middleware-retry": "^4.1.16", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.1.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.23", - "@smithy/util-defaults-mode-node": "^4.0.23", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", - "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.6", - "@types/uuid": "^9.0.1", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.848.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.848.0.tgz", - "integrity": "sha512-mD+gOwoeZQvbecVLGoCmY6pS7kg02BHesbtIxUj+PeBqYoZV5uLvjUOmuGfw1SfoSobKvS11urxC9S7zxU/Maw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.846.0", - "@aws-sdk/middleware-host-header": "3.840.0", - "@aws-sdk/middleware-logger": "3.840.0", - "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.848.0", - "@aws-sdk/region-config-resolver": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.848.0", - "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.848.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.7.0", - "@smithy/fetch-http-handler": "^5.1.0", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.15", - "@smithy/middleware-retry": "^4.1.16", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.1.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.23", - "@smithy/util-defaults-mode-node": "^4.0.23", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/core": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.846.0.tgz", - "integrity": "sha512-7CX0pM906r4WSS68fCTNMTtBCSkTtf3Wggssmx13gD40gcWEZXsU00KzPp1bYheNRyPlAq3rE22xt4wLPXbuxA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.840.0", - "@aws-sdk/xml-builder": "3.821.0", - "@smithy/core": "^3.7.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-utf8": "^4.0.0", - "fast-xml-parser": "5.2.5", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.846.0.tgz", - "integrity": "sha512-QuCQZET9enja7AWVISY+mpFrEIeHzvkx/JEEbHYzHhUkxcnC2Kq2c0bB7hDihGD0AZd3Xsm653hk1O97qu69zg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.846.0.tgz", - "integrity": "sha512-Jh1iKUuepdmtreMYozV2ePsPcOF5W9p3U4tWhi3v6nDvz0GsBjzjAROW+BW8XMz9vAD3I9R+8VC3/aq63p5nlw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/fetch-http-handler": "^5.1.0", - "@smithy/node-http-handler": "^4.1.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.848.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.848.0.tgz", - "integrity": "sha512-r6KWOG+En2xujuMhgZu7dzOZV3/M5U/5+PXrG8dLQ3rdPRB3vgp5tc56KMqLwm/EXKRzAOSuw/UE4HfNOAB8Hw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/credential-provider-env": "3.846.0", - "@aws-sdk/credential-provider-http": "3.846.0", - "@aws-sdk/credential-provider-process": "3.846.0", - "@aws-sdk/credential-provider-sso": "3.848.0", - "@aws-sdk/credential-provider-web-identity": "3.848.0", - "@aws-sdk/nested-clients": "3.848.0", - "@aws-sdk/types": "3.840.0", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.848.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.848.0.tgz", - "integrity": "sha512-AblNesOqdzrfyASBCo1xW3uweiSro4Kft9/htdxLeCVU1KVOnFWA5P937MNahViRmIQm2sPBCqL8ZG0u9lnh5g==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.846.0", - "@aws-sdk/credential-provider-http": "3.846.0", - "@aws-sdk/credential-provider-ini": "3.848.0", - "@aws-sdk/credential-provider-process": "3.846.0", - "@aws-sdk/credential-provider-sso": "3.848.0", - "@aws-sdk/credential-provider-web-identity": "3.848.0", - "@aws-sdk/types": "3.840.0", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.846.0.tgz", - "integrity": "sha512-mEpwDYarJSH+CIXnnHN0QOe0MXI+HuPStD6gsv3z/7Q6ESl8KRWon3weFZCDnqpiJMUVavlDR0PPlAFg2MQoPg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.848.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.848.0.tgz", - "integrity": "sha512-pozlDXOwJZL0e7w+dqXLgzVDB7oCx4WvtY0sk6l4i07uFliWF/exupb6pIehFWvTUcOvn5aFTTqcQaEzAD5Wsg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/client-sso": "3.848.0", - "@aws-sdk/core": "3.846.0", - "@aws-sdk/token-providers": "3.848.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.848.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.848.0.tgz", - "integrity": "sha512-D1fRpwPxtVDhcSc/D71exa2gYweV+ocp4D3brF0PgFd//JR3XahZ9W24rVnTQwYEcK9auiBZB89Ltv+WbWN8qw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/nested-clients": "3.848.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.840.0.tgz", - "integrity": "sha512-ub+hXJAbAje94+Ya6c6eL7sYujoE8D4Bumu1NUI8TXjUhVVn0HzVWQjpRLshdLsUp1AW7XyeJaxyajRaJQ8+Xg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.840.0.tgz", - "integrity": "sha512-lSV8FvjpdllpGaRspywss4CtXV8M7NNNH+2/j86vMH+YCOZ6fu2T/TyFd/tHwZ92vDfHctWkRbQxg0bagqwovA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.840.0.tgz", - "integrity": "sha512-Gu7lGDyfddyhIkj1Z1JtrY5NHb5+x/CRiB87GjaSrKxkDaydtX2CU977JIABtt69l9wLbcGDIQ+W0uJ5xPof7g==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.848.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.848.0.tgz", - "integrity": "sha512-rjMuqSWJEf169/ByxvBqfdei1iaduAnfolTshsZxwcmLIUtbYrFUmts0HrLQqsAG8feGPpDLHA272oPl+NTCCA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.848.0", - "@smithy/core": "^3.7.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients": { - "version": "3.848.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.848.0.tgz", - "integrity": "sha512-joLsyyo9u61jnZuyYzo1z7kmS7VgWRAkzSGESVzQHfOA1H2PYeUFek6vLT4+c9xMGrX/Z6B0tkRdzfdOPiatLg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.846.0", - "@aws-sdk/middleware-host-header": "3.840.0", - "@aws-sdk/middleware-logger": "3.840.0", - "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.848.0", - "@aws-sdk/region-config-resolver": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.848.0", - "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.848.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.7.0", - "@smithy/fetch-http-handler": "^5.1.0", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.15", - "@smithy/middleware-retry": "^4.1.16", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.1.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.23", - "@smithy/util-defaults-mode-node": "^4.0.23", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.840.0.tgz", - "integrity": "sha512-Qjnxd/yDv9KpIMWr90ZDPtRj0v75AqGC92Lm9+oHXZ8p1MjG5JE2CW0HL8JRgK9iKzgKBL7pPQRXI8FkvEVfrA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.848.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.848.0.tgz", - "integrity": "sha512-oNPyM4+Di2Umu0JJRFSxDcKQ35+Chl/rAwD47/bS0cDPI8yrao83mLXLeDqpRPHyQW4sXlP763FZcuAibC0+mg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/nested-clients": "3.848.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/types": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.840.0.tgz", - "integrity": "sha512-xliuHaUFZxEx1NSXeLLZ9Dyu6+EJVQKEoD+yM+zqUo3YDZ7medKJWY6fIOKiPX/N7XbLdBYwajb15Q7IL8KkeA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.848.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.848.0.tgz", - "integrity": "sha512-fY/NuFFCq/78liHvRyFKr+aqq1aA/uuVSANjzr5Ym8c+9Z3HRPE9OrExAHoMrZ6zC8tHerQwlsXYYH5XZ7H+ww==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-endpoints": "^3.0.6", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.804.0.tgz", - "integrity": "sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.840.0.tgz", - "integrity": "sha512-JdyZM3EhhL4PqwFpttZu1afDpPJCCc3eyZOLi+srpX11LsGj6sThf47TYQN75HT1CarZ7cCdQHGzP2uy3/xHfQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.848.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.848.0.tgz", - "integrity": "sha512-Zz1ft9NiLqbzNj/M0jVNxaoxI2F4tGXN0ZbZIj+KJ+PbJo+w5+Jo6d0UDAtbj3AEd79pjcCaP4OA9NTVzItUdw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/middleware-user-agent": "3.848.0", - "@aws-sdk/types": "3.840.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } - } - }, - "node_modules/@aws-sdk/xml-builder": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.821.0.tgz", - "integrity": "sha512-DIIotRnefVL6DiaHtO6/21DhJ4JZnnIwdNbpwiAhdt/AVbttcE4yw925gsjur0OGv5BTYXQXU3YnANBYnZjuQA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/abort-controller": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.4.tgz", - "integrity": "sha512-gJnEjZMvigPDQWHrW3oPrFhQtkrgqBkyjj3pCIdF3A5M6vsZODG93KNlfJprv6bp4245bdT32fsHK4kkH3KYDA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.4.tgz", - "integrity": "sha512-prmU+rDddxHOH0oNcwemL+SwnzcG65sBF2yXRO7aeXIn/xTlq2pX7JLVbkBnVLowHLg4/OL4+jBmv9hVrVGS+w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/core": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.7.1.tgz", - "integrity": "sha512-ExRCsHnXFtBPnM7MkfKBPcBBdHw1h/QS/cbNw4ho95qnyNHvnpmGbR39MIAv9KggTr5qSPxRSEL+hRXlyGyGQw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/middleware-serde": "^4.0.8", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.3", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.6.tgz", - "integrity": "sha512-hKMWcANhUiNbCJouYkZ9V3+/Qf9pteR1dnwgdyzR09R4ODEYx8BbUysHwRSyex4rZ9zapddZhLFTnT4ZijR4pw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.0.tgz", - "integrity": "sha512-mADw7MS0bYe2OGKkHYMaqarOXuDwRbO6ArD91XhHcl2ynjGCFF+hvqf0LyQcYxkA1zaWjefSkU7Ne9mqgApSgQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/querystring-builder": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/hash-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.4.tgz", - "integrity": "sha512-qnbTPUhCVnCgBp4z4BUJUhOEkVwxiEi1cyFM+Zj6o+aY8OFGxUQleKWq8ltgp3dujuhXojIvJWdoqpm6dVO3lQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.4.tgz", - "integrity": "sha512-bNYMi7WKTJHu0gn26wg8OscncTt1t2b8KcsZxvOv56XA6cyXtOAAAaNP7+m45xfppXfOatXF3Sb1MNsLUgVLTw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/is-array-buffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz", - "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.4.tgz", - "integrity": "sha512-F7gDyfI2BB1Kc+4M6rpuOLne5LOcEknH1n6UQB69qv+HucXBR1rkzXBnQTB2q46sFy1PM/zuSJOB532yc8bg3w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.16.tgz", - "integrity": "sha512-plpa50PIGLqzMR2ANKAw2yOW5YKS626KYKqae3atwucbz4Ve4uQ9K9BEZxDLIFmCu7hKLcrq2zmj4a+PfmUV5w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.7.1", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-middleware": "^4.0.4", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-retry": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.17.tgz", - "integrity": "sha512-gsCimeG6BApj0SBecwa1Be+Z+JOJe46iy3B3m3A8jKJHf7eIihP76Is4LwLrbJ1ygoS7Vg73lfqzejmLOrazUA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/protocol-http": "^5.1.2", - "@smithy/service-error-classification": "^4.0.6", - "@smithy/smithy-client": "^4.4.8", - "@smithy/types": "^4.3.1", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-serde": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.8.tgz", - "integrity": "sha512-iSSl7HJoJaGyMIoNn2B7czghOVwJ9nD7TMvLhMWeSB5vt0TnEYyRRqPJu/TqW76WScaNvYYB8nRoiBHR9S1Ddw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.4.tgz", - "integrity": "sha512-kagK5ggDrBUCCzI93ft6DjteNSfY8Ulr83UtySog/h09lTIOAJ/xUSObutanlPT0nhoHAkpmW9V5K8oPyLh+QA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-config-provider": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.3.tgz", - "integrity": "sha512-HGHQr2s59qaU1lrVH6MbLlmOBxadtzTsoO4c+bF5asdgVik3I8o7JIOzoeqWc5MjVa+vD36/LWE0iXKpNqooRw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.1.0.tgz", - "integrity": "sha512-vqfSiHz2v8b3TTTrdXi03vNz1KLYYS3bhHCDv36FYDqxT7jvTll1mMnCrkD+gOvgwybuunh/2VmvOMqwBegxEg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/abort-controller": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/querystring-builder": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/property-provider": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.4.tgz", - "integrity": "sha512-qHJ2sSgu4FqF4U/5UUp4DhXNmdTrgmoAai6oQiM+c5RZ/sbDwJ12qxB1M6FnP+Tn/ggkPZf9ccn4jqKSINaquw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.2.tgz", - "integrity": "sha512-rOG5cNLBXovxIrICSBm95dLqzfvxjEmuZx4KK3hWwPFHGdW3lxY0fZNXfv2zebfRO7sJZ5pKJYHScsqopeIWtQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/querystring-builder": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.4.tgz", - "integrity": "sha512-SwREZcDnEYoh9tLNgMbpop+UTGq44Hl9tdj3rf+yeLcfH7+J8OXEBaMc2kDxtyRHu8BhSg9ADEx0gFHvpJgU8w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "@smithy/util-uri-escape": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/querystring-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.4.tgz", - "integrity": "sha512-6yZf53i/qB8gRHH/l2ZwUG5xgkPgQF15/KxH0DdXMDHjesA9MeZje/853ifkSY0x4m5S+dfDZ+c4x439PF0M2w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/service-error-classification": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.6.tgz", - "integrity": "sha512-RRoTDL//7xi4tn5FrN2NzH17jbgmnKidUqd4KvquT0954/i6CXXkh1884jBiunq24g9cGtPBEXlU40W6EpNOOg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.4.tgz", - "integrity": "sha512-63X0260LoFBjrHifPDs+nM9tV0VMkOTl4JRMYNuKh/f5PauSjowTfvF3LogfkWdcPoxsA9UjqEOgjeYIbhb7Nw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.2.tgz", - "integrity": "sha512-d3+U/VpX7a60seHziWnVZOHuEgJlclufjkS6zhXvxcJgkJq4UWdH5eOBLzHRMx6gXjsdT9h6lfpmLzbrdupHgQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^4.0.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-uri-escape": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/smithy-client": { - "version": "4.4.8", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.8.tgz", - "integrity": "sha512-pcW691/lx7V54gE+dDGC26nxz8nrvnvRSCJaIYD6XLPpOInEZeKdV/SpSux+wqeQ4Ine7LJQu8uxMvobTIBK0w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.7.1", - "@smithy/middleware-endpoint": "^4.1.16", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.1.tgz", - "integrity": "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/url-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.4.tgz", - "integrity": "sha512-eMkc144MuN7B0TDA4U2fKs+BqczVbk3W+qIvcoCY6D1JY3hnAdCuhCZODC+GAeaxj0p6Jroz4+XMUn3PCxQQeQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/querystring-parser": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-base64": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz", - "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-body-length-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz", - "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-body-length-node": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz", - "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-buffer-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", - "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-config-provider": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz", - "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.24", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.24.tgz", - "integrity": "sha512-UkQNgaQ+bidw1MgdgPO1z1k95W/v8Ej/5o/T/Is8PiVUYPspl/ZxV6WO/8DrzZQu5ULnmpB9CDdMSRwgRc21AA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.8", - "@smithy/types": "^4.3.1", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.24", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.24.tgz", - "integrity": "sha512-phvGi/15Z4MpuQibTLOYIumvLdXb+XIJu8TA55voGgboln85jytA3wiD7CkUE8SNcWqkkb+uptZKPiuFouX/7g==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/config-resolver": "^4.1.4", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.8", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-endpoints": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.6.tgz", - "integrity": "sha512-YARl3tFL3WgPuLzljRUnrS2ngLiUtkwhQtj8PAL13XZSyUiNLQxwG3fBBq3QXFqGFUXepIN73pINp3y8c2nBmA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-hex-encoding": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz", - "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-middleware": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.4.tgz", - "integrity": "sha512-9MLKmkBmf4PRb0ONJikCbCwORACcil6gUWojwARCClT7RmLzF04hUR4WdRprIXal7XVyrddadYNfp2eF3nrvtQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-retry": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.6.tgz", - "integrity": "sha512-+YekoF2CaSMv6zKrA6iI/N9yva3Gzn4L6n35Luydweu5MMPYpiGZlWqehPHDHyNbnyaYlz/WJyYAZnC+loBDZg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/service-error-classification": "^4.0.6", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-stream": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.3.tgz", - "integrity": "sha512-cQn412DWHHFNKrQfbHY8vSFI3nTROY1aIKji9N0tpp8gUABRilr7wdf8fqBbSlXresobM+tQFNk6I+0LXK/YZg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/fetch-http-handler": "^5.1.0", - "@smithy/node-http-handler": "^4.1.0", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-uri-escape": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", - "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-utf8": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", - "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-waiter": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.6.tgz", - "integrity": "sha512-slcr1wdRbX7NFphXZOxtxRNA7hXAAtJAXJDE/wdoMAos27SIquVCKiSqfB6/28YzQ8FCsB5NKkhdM5gMADbqxg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/abort-controller": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@types/node": { - "version": "20.19.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz", - "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "license": "MIT" - }, - "node_modules/bowser": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", - "license": "MIT" - }, - "node_modules/fast-xml-parser": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", - "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "dependencies": { - "strnum": "^2.1.0" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, - "node_modules/strnum": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", - "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/uuid": { - "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" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - } - } -} diff --git a/packages/cdk/custom-resources/agent-core-runtime/package.json b/packages/cdk/custom-resources/agent-core-runtime/package.json deleted file mode 100644 index 543d08278..000000000 --- a/packages/cdk/custom-resources/agent-core-runtime/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "agent-core-runtime-custom-resource", - "private": true, - "version": "1.0.0", - "description": "CustomResource for managing AWS Bedrock AgentCore Runtimes", - "main": "index.js", - "scripts": { - "build": "tsc", - "clean": "rm -rf dist *.js *.d.ts", - "prebuild": "npm run clean" - }, - "dependencies": { - "@aws-sdk/client-bedrock-agentcore-control": "^3.755.0" - }, - "devDependencies": { - "@types/node": "^20.0.0", - "typescript": "^5.0.0" - } -} diff --git a/packages/cdk/custom-resources/agent-core-runtime/tsconfig.json b/packages/cdk/custom-resources/agent-core-runtime/tsconfig.json deleted file mode 100644 index deaa5c919..000000000 --- a/packages/cdk/custom-resources/agent-core-runtime/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "commonjs", - "lib": ["ES2020"], - "outDir": "./", - "rootDir": "./", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "declaration": true, - "declarationMap": false, - "sourceMap": false, - "moduleResolution": "node", - "allowSyntheticDefaultImports": true - }, - "include": ["*.ts"], - "exclude": ["node_modules", "**/*.test.ts", "**/*.spec.ts"] -} diff --git a/packages/cdk/lambda-python/generic-agent-core-runtime/app.py b/packages/cdk/lambda-python/generic-agent-core-runtime/app.py index 8006c4190..04f9d7551 100644 --- a/packages/cdk/lambda-python/generic-agent-core-runtime/app.py +++ b/packages/cdk/lambda-python/generic-agent-core-runtime/app.py @@ -41,38 +41,56 @@ async def invocations(request: Request): Expects request with messages, system_prompt, prompt, and model """ - # Get session info from headers + # Setup session and workspace headers = dict(request.headers) session_id = headers.get("x-amzn-bedrock-agentcore-runtime-session-id") trace_id = headers.get("x-amzn-trace-id") - logger.info(f"New invocation: {session_id} {trace_id}") - - # Set session info in agent manager agent_manager.set_session_info(session_id, trace_id) - - # Ensure workspace directory exists create_ws_directory() try: - # Read and parse request body + # Parse request body body = await request.body() - body_str = body.decode() - request_data = json.loads(body_str) - - # Handle input field if present (AWS Lambda integration format) - if "input" in request_data and isinstance(request_data["input"], dict): - request_data = request_data["input"] - - # Extract required fields + try: + request_data = json.loads(body.decode()) + # Handle AWS Lambda integration format + if "input" in request_data and isinstance(request_data["input"], dict): + request_data = request_data["input"] + except json.JSONDecodeError as e: + logger.error(f"Invalid JSON: {e}") + return create_error_response("Invalid JSON in request body") + + # Extract fields messages = request_data.get("messages", []) system_prompt = request_data.get("system_prompt") prompt = request_data.get("prompt", []) model_info = request_data.get("model", {}) - - # Return streaming response + user_id = request_data.get("user_id") + mcp_servers = request_data.get("mcp_servers") + agent_session_id = request_data.get("session_id") + agent_id = request_data.get("agent_id") + code_execution_enabled = request_data.get("code_execution_enabled", False) + + # Validate required fields + if not model_info: + return create_error_response("Model information is required") + if not prompt and not messages: + return create_error_response("Either prompt or messages is required") + + # Stream response async def generate(): try: - async for chunk in agent_manager.process_request_streaming(messages=messages, system_prompt=system_prompt, prompt=prompt, model_info=model_info): + async for chunk in agent_manager.process_request_streaming( + messages=messages, + system_prompt=system_prompt, + prompt=prompt, + model_info=model_info, + user_id=user_id, + mcp_servers=mcp_servers, + session_id=agent_session_id or session_id, + agent_id=agent_id, + code_execution_enabled=code_execution_enabled, + ): yield chunk finally: clean_ws_directory() diff --git a/packages/cdk/lambda-python/generic-agent-core-runtime/mcp.json b/packages/cdk/lambda-python/generic-agent-core-runtime/mcp.json index 6eadc70af..fb1c02c8d 100644 --- a/packages/cdk/lambda-python/generic-agent-core-runtime/mcp.json +++ b/packages/cdk/lambda-python/generic-agent-core-runtime/mcp.json @@ -1,36 +1,78 @@ { - "_comment": "Generic AgentCore Runtime Configuration", - "_agentcore_requirements": { - "platform": "linux/arm64", - "port": 8080, - "endpoints": { - "/ping": "GET - Health check endpoint", - "/invocations": "POST - Main inference endpoint" - }, - "aws_credentials": "Required for Bedrock model access and S3 operations" + "_comment": "MCP Server Configuration", + "_metadata_info": { + "description": "Each server can include a 'metadata' object with 'category' and 'description' fields", + "category_examples": [ + "AWS", + "AI/ML", + "Utility", + "Search", + "Development", + "Other" + ] }, "mcpServers": { "time": { "command": "uvx", - "args": ["mcp-server-time"] + "args": ["mcp-server-time"], + "metadata": { + "category": "Utility", + "description": "Provides current time and date functionality" + } + }, + "aws-knowledge-mcp-server": { + "command": "npx", + "args": ["mcp-remote", "https://knowledge-mcp.global.api.aws"], + "metadata": { + "category": "AWS", + "description": "AWS Knowledge Base MCP server for enterprise knowledge access" + } }, "awslabs.aws-documentation-mcp-server": { "command": "uvx", - "args": ["awslabs.aws-documentation-mcp-server@latest"] + "args": ["awslabs.aws-documentation-mcp-server@latest"], + "metadata": { + "category": "AWS", + "description": "Access AWS documentation and guides" + } }, "awslabs.cdk-mcp-server": { "command": "uvx", - "args": ["awslabs.cdk-mcp-server@latest"] + "args": ["awslabs.cdk-mcp-server@latest"], + "metadata": { + "category": "AWS", + "description": "AWS CDK code generation and assistance" + } }, "awslabs.aws-diagram-mcp-server": { "command": "uvx", - "args": ["awslabs.aws-diagram-mcp-server@latest"] + "args": ["awslabs.aws-diagram-mcp-server@latest"], + "metadata": { + "category": "AWS", + "description": "Generate AWS architecture diagrams" + } }, "awslabs.nova-canvas-mcp-server": { "command": "uvx", "args": ["awslabs.nova-canvas-mcp-server@latest"], "env": { "AWS_REGION": "us-east-1" + }, + "metadata": { + "category": "AI/ML", + "description": "Amazon Nova Canvas image generation" + } + }, + "tavily-search": { + "command": "npx", + "args": [ + "-y", + "mcp-remote", + "https://mcp.tavily.com/mcp/?tavilyApiKey=" + ], + "metadata": { + "category": "Search", + "description": "Web search and research capabilities powered by Tavily" } } } diff --git a/packages/cdk/lambda-python/generic-agent-core-runtime/src/agent.py b/packages/cdk/lambda-python/generic-agent-core-runtime/src/agent.py index 6775ffc69..4871a1e13 100644 --- a/packages/cdk/lambda-python/generic-agent-core-runtime/src/agent.py +++ b/packages/cdk/lambda-python/generic-agent-core-runtime/src/agent.py @@ -12,9 +12,13 @@ from .config import extract_model_info, get_system_prompt from .tools import ToolManager from .types import Message, ModelInfo -from .utils import process_messages, process_prompt +from .utils import ( + process_messages, + process_prompt, +) logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) class AgentManager: @@ -33,17 +37,31 @@ async def process_request_streaming( system_prompt: str | None, prompt: str | list[dict[str, Any]], model_info: ModelInfo, + user_id: str | None = None, + mcp_servers: list[str] | None = None, + session_id: str | None = None, + agent_id: str | None = None, + code_execution_enabled: bool | None = False, ) -> AsyncGenerator[str]: """Process a request and yield streaming responses as raw events""" try: - # Get model info + # Set session info if provided + if session_id: + self.set_session_info(session_id, session_id) + + # Extract model info model_id, region = extract_model_info(model_info) # Combine system prompts combined_system_prompt = get_system_prompt(system_prompt) - # Get all tools - tools = self.tool_manager.get_all_tools() + # Get tools (MCP handling is done in ToolManager) + tools = self.tool_manager.get_tools_with_options(code_execution_enabled=code_execution_enabled, mcp_servers=mcp_servers) + logger.info(f"Loaded {len(tools)} tools (code execution: {code_execution_enabled})") + + # Log agent info + if agent_id: + logger.debug(f"Processing agent: {agent_id}") # Create boto3 session and Bedrock model session = boto3.Session(region_name=region) @@ -71,7 +89,7 @@ async def process_request_streaming( yield json.dumps(event, ensure_ascii=False) + "\n" except Exception as e: - logger.error(f"Error processing agent request: {e}") + logger.error(f"Error processing agent request: {e}", exc_info=True) error_event = { "event": { "internalServerException": { @@ -80,3 +98,7 @@ async def process_request_streaming( } } yield json.dumps(error_event, ensure_ascii=False) + "\n" + finally: + # Cleanup is handled automatically by the dynamic MCP client + if user_id: + logger.debug(f"Session cleanup for user {user_id} handled automatically") diff --git a/packages/cdk/lambda-python/generic-agent-core-runtime/src/tools.py b/packages/cdk/lambda-python/generic-agent-core-runtime/src/tools.py index 66f2422e5..5c71a01a3 100644 --- a/packages/cdk/lambda-python/generic-agent-core-runtime/src/tools.py +++ b/packages/cdk/lambda-python/generic-agent-core-runtime/src/tools.py @@ -45,43 +45,96 @@ def load_mcp_tools(self) -> list[Any]: return self.mcp_tools try: - with open("mcp.json") as f: - mcp_json = json.loads(f.read()) - - if "mcpServers" not in mcp_json: - logger.warning("mcpServers not defined in mcp.json") - self.mcp_tools = [] - return self.mcp_tools - - mcp_servers = mcp_json["mcpServers"] - mcp_clients = [] - uv_env = get_uv_environment() - - for server_name, server in mcp_servers.items(): - try: - client = MCPClient( - lambda server=server: stdio_client( - StdioServerParameters( - command=server["command"], - args=server.get("args", []), - env={**uv_env, **server.get("env", {})}, - ) + # Load MCP configuration from mcp.json file + mcp_config_path = "mcp.json" + if not os.path.exists(mcp_config_path): + logger.warning(f"MCP configuration file not found at {mcp_config_path}") + self.mcp_tools = [] + return self.mcp_tools + + with open(mcp_config_path) as f: + mcp_config = json.load(f) + + mcp_servers = mcp_config.get("mcpServers", {}) + mcp_clients = [] + uv_env = get_uv_environment() + + for server_name, server in mcp_servers.items(): + try: + client = MCPClient( + lambda server=server: stdio_client( + StdioServerParameters( + command=server["command"], + args=server.get("args", []), + env={**uv_env, **server.get("env", {})}, ) ) - client.start() - mcp_clients.append(client) - except Exception as e: - logger.error(f"Error creating MCP client for {server_name}: {e}") - - # Flatten the tools - self.mcp_tools = sum([c.list_tools_sync() for c in mcp_clients], []) - logger.info(f"Loaded {len(self.mcp_tools)} MCP tools") - return self.mcp_tools + ) + client.start() + mcp_clients.append(client) + except Exception as e: + logger.error(f"Error creating MCP client for {server_name}: {e}") + + # Flatten the tools + self.mcp_tools = sum([c.list_tools_sync() for c in mcp_clients], []) + logger.info(f"Loaded {len(self.mcp_tools)} MCP tools") + return self.mcp_tools + except Exception as e: logger.error(f"Error loading MCP tools: {e}") self.mcp_tools = [] return self.mcp_tools + def load_mcp_tools_by_names(self, server_names: list[str]) -> list[Any]: + """Load MCP tools from environment variable by server names""" + if not server_names: + return [] + + try: + # Load MCP configuration from mcp.json file + # Try multiple possible paths + mcp_config_path = "mcp.json" + + logger.info(f"Loading MCP configuration from: {mcp_config_path}") + with open(mcp_config_path) as f: + mcp_config = json.load(f) + + available_servers = mcp_config.get("mcpServers", {}) + logger.info(f"Found {len(available_servers)} available MCP servers") + mcp_clients = [] + uv_env = get_uv_environment() + + for server_name in server_names: + if server_name not in available_servers: + logger.warning(f"MCP server '{server_name}' not found in mcp.json") + continue + + server_config = available_servers[server_name] + try: + client = MCPClient( + lambda server=server_config: stdio_client( + StdioServerParameters( + command=server["command"], + args=server.get("args", []), + env={**uv_env, **server.get("env", {})}, + ) + ) + ) + client.start() + mcp_clients.append(client) + logger.info(f"Successfully loaded MCP server: {server_name}") + except Exception as e: + logger.error(f"Error creating MCP client for {server_name}: {e}") + + # Flatten the tools + dynamic_tools = sum([c.list_tools_sync() for c in mcp_clients], []) + logger.info(f"Loaded {len(dynamic_tools)} MCP tools from {len(mcp_clients)} servers") + return dynamic_tools + + except Exception as e: + logger.error(f"Error loading MCP tools by names: {e}") + return [] + def get_upload_tool(self): """Get the S3 upload tool with session context""" trace_id = self.trace_id @@ -136,13 +189,56 @@ def get_code_interpreter_tool(self) -> list[Any]: return code_interpreter_tools - def get_all_tools(self) -> list[Any]: - """Get all available tools (MCP + built-in + code interpreter)""" - mcp_tools = self.load_mcp_tools() + def get_tools_with_options(self, code_execution_enabled: bool = False, mcp_servers=None) -> list[Any]: + """ + Get tools with optional code execution and MCP servers. + + Args: + code_execution_enabled: Whether to include code interpreter tools + mcp_servers: MCP server configurations + - None: Load default MCP servers from mcp.json + - []: Empty list, no MCP servers (File Upload only) + - [...]: Load specified MCP servers + + Returns: + List of all available tools + """ + logger.info(f"get_tools_with_options called with code_execution_enabled={code_execution_enabled}") + logger.info(f"mcp_servers parameter: {mcp_servers} (type: {type(mcp_servers)})") + + all_tools = [] + + # Handle MCP servers based on parameter + if mcp_servers is None: + # Load default MCP servers from mcp.json + logger.info("Loading default MCP servers from mcp.json") + mcp_tools = self.load_mcp_tools() + elif isinstance(mcp_servers, list) and len(mcp_servers) == 0: + # Empty list: no MCP servers + logger.info("Empty MCP servers list provided, skipping MCP tools") + mcp_tools = [] + elif isinstance(mcp_servers, list): + # Load specified MCP servers by name + logger.info(f"Loading {len(mcp_servers)} user-specified MCP servers by name") + mcp_tools = self.load_mcp_tools_by_names(mcp_servers) + else: + # Fallback to default + logger.warning(f"Unexpected mcp_servers type: {type(mcp_servers)}, using default") + mcp_tools = self.load_mcp_tools() + + all_tools.extend(mcp_tools) + + # Add built-in tools (always included) upload_tool = self.get_upload_tool() - code_interpreter_tools = self.get_code_interpreter_tool() + all_tools.append(upload_tool) + + # Add code interpreter tools if enabled + code_interpreter_tools = [] + if code_execution_enabled: + code_interpreter_tools = self.get_code_interpreter_tool() + all_tools.extend(code_interpreter_tools) - all_tools = mcp_tools + [upload_tool] + code_interpreter_tools - logger.info(f"Total tools loaded: {len(all_tools)} (MCP: {len(mcp_tools)}, Built-in: 1, Code Interpreter: {len(code_interpreter_tools)})") + # Log final tool count + logger.info(f"Total tools loaded: {len(all_tools)} (MCP: {len(mcp_tools)}, Built-in: 1, Code Interpreter: {len(code_interpreter_tools)} - {'enabled' if code_execution_enabled else 'disabled'})") return all_tools diff --git a/packages/cdk/lambda-python/generic-agent-core-runtime/src/types.py b/packages/cdk/lambda-python/generic-agent-core-runtime/src/types.py index 905843d40..a1078fbcf 100644 --- a/packages/cdk/lambda-python/generic-agent-core-runtime/src/types.py +++ b/packages/cdk/lambda-python/generic-agent-core-runtime/src/types.py @@ -16,3 +16,7 @@ class AgentCoreRequest(BaseModel): system_prompt: str | None = None prompt: str | list[dict[str, Any]] = "" model: ModelInfo = {} + user_id: str | None = None # User identification for MCP isolation + mcp_servers: list[str] | None = None # MCP server names from mcp.json + session_id: str | None = None # Session identifier + agent_id: str | None = None # Agent identifier for logging and tracking diff --git a/packages/cdk/lambda/agentBuilder.ts b/packages/cdk/lambda/agentBuilder.ts new file mode 100644 index 000000000..7ecb244f2 --- /dev/null +++ b/packages/cdk/lambda/agentBuilder.ts @@ -0,0 +1,34 @@ +import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda'; +import { getUserIdFromEvent } from './agentBuilder/utils/auth-utils'; +import { createSuccessResponse } from './agentBuilder/utils/response-utils'; +import { handleError } from './agentBuilder/utils/error-handling'; +import { routeRequest } from './agentBuilder/router'; + +/** + * Main Lambda handler for Agent Builder API + * + * This handler has been refactored to use a modular architecture: + * - Utilities: Common functions for auth, responses, and security + * - Validation: Request and data validation logic + * - Services: Business logic layer + * - Handlers: Individual endpoint handlers + * - Router: Centralized routing logic + */ +export const handler = async ( + event: APIGatewayProxyEvent +): Promise => { + // Handle CORS preflight + if (event.httpMethod === 'OPTIONS') { + return createSuccessResponse({}); + } + + try { + const userId = getUserIdFromEvent(event); + + // Route to appropriate handler based on resource and method + return await routeRequest(event, userId); + } catch (error) { + console.error('Handler error:', error); + return handleError(error as Error); + } +}; diff --git a/packages/cdk/lambda/agentBuilder/handlers/agent-handlers.ts b/packages/cdk/lambda/agentBuilder/handlers/agent-handlers.ts new file mode 100644 index 000000000..d00b10691 --- /dev/null +++ b/packages/cdk/lambda/agentBuilder/handlers/agent-handlers.ts @@ -0,0 +1,276 @@ +import { APIGatewayProxyResult } from 'aws-lambda'; +import { + CreateAgentRequest, + UpdateAgentRequest, + CloneAgentRequest, +} from 'generative-ai-use-cases'; +import * as agentService from '../services/agent-service'; +import { + validateUserId, + validateAgentId, + validateCloneAgentRequest, +} from '../validation/request-validation'; +import { + validateCreateAgentRequest, + validateUpdateAgentRequest, +} from '../validation/agent-validation'; +import { createSuccessResponse } from '../utils/response-utils'; +import { handleError, ValidationError } from '../utils/error-handling'; + +/** + * Handle create agent request + */ +export async function handleCreateAgent( + userId: string, + request: CreateAgentRequest +): Promise { + try { + // Input validation (data format, types, required fields) + const userValidation = validateUserId(userId); + if (!userValidation.isValid) { + throw new ValidationError(userValidation.error!); + } + + const validation = validateCreateAgentRequest(request); + if (!validation.isValid) { + throw new ValidationError(validation.error!); + } + + // Service layer handles business logic with validated data + const agent = await agentService.createAgent(userId, validation.data!); + return createSuccessResponse(agent, 201); + } catch (error) { + return handleError(error as Error); + } +} + +/** + * Handle get agent request + */ +export async function handleGetAgent( + userId: string, + agentId: string +): Promise { + try { + // Validate user ID + const userValidation = validateUserId(userId); + if (!userValidation.isValid) { + throw new ValidationError(userValidation.error!); + } + + // Validate agent ID + const agentValidation = validateAgentId(agentId); + if (!agentValidation.isValid) { + throw new ValidationError(agentValidation.error!); + } + + // Get agent + const agent = await agentService.getAgent(userId, agentId); + + return createSuccessResponse(agent); + } catch (error) { + return handleError(error as Error); + } +} + +/** + * Handle update agent request + */ +export async function handleUpdateAgent( + userId: string, + agentId: string, + request: UpdateAgentRequest +): Promise { + try { + // Input validation (data format, types, required fields) + const userValidation = validateUserId(userId); + if (!userValidation.isValid) { + throw new ValidationError(userValidation.error!); + } + + const agentValidation = validateAgentId(agentId); + if (!agentValidation.isValid) { + throw new ValidationError(agentValidation.error!); + } + + const validation = validateUpdateAgentRequest(request); + if (!validation.isValid) { + throw new ValidationError(validation.error!); + } + + // Service layer handles business logic with validated data + const agent = await agentService.updateAgent( + userId, + agentId, + validation.data! + ); + return createSuccessResponse(agent); + } catch (error) { + return handleError(error as Error); + } +} + +/** + * Handle delete agent request + */ +export async function handleDeleteAgent( + userId: string, + agentId: string +): Promise { + try { + // Validate user ID + const userValidation = validateUserId(userId); + if (!userValidation.isValid) { + throw new ValidationError(userValidation.error!); + } + + // Validate agent ID + const agentValidation = validateAgentId(agentId); + if (!agentValidation.isValid) { + throw new ValidationError(agentValidation.error!); + } + + // Delete agent + await agentService.deleteAgent(userId, agentId); + + return createSuccessResponse({ message: 'Agent deleted successfully' }); + } catch (error) { + return handleError(error as Error); + } +} + +/** + * Handle list user agents request + */ +export async function handleListUserAgents( + userId: string, + exclusiveStartKey?: string, + limit?: number +): Promise { + try { + // Validate user ID + const userValidation = validateUserId(userId); + if (!userValidation.isValid) { + throw new ValidationError(userValidation.error!); + } + + // List agents + const result = await agentService.listUserAgents( + userId, + limit, + exclusiveStartKey + ); + + return createSuccessResponse(result); + } catch (error) { + return handleError(error as Error); + } +} + +/** + * Handle list public agents request + */ +export async function handleListPublicAgents( + userId: string, + exclusiveStartKey?: string, + limit?: number +): Promise { + try { + // Input validation + const userValidation = validateUserId(userId); + if (!userValidation.isValid) { + throw new ValidationError(userValidation.error!); + } + + // Service layer handles business logic + const result = await agentService.listPublicAgents( + userId, + limit, + exclusiveStartKey + ); + return createSuccessResponse(result); + } catch (error) { + return handleError(error as Error); + } +} + +/** + * Handle clone agent request + */ +export async function handleCloneAgent( + userId: string, + request: CloneAgentRequest +): Promise { + try { + // Input validation + const userValidation = validateUserId(userId); + if (!userValidation.isValid) { + throw new ValidationError(userValidation.error!); + } + + const validation = validateCloneAgentRequest(request); + if (!validation.isValid) { + throw new ValidationError(validation.error!); + } + + // Service layer handles business logic with validated data + const agent = await agentService.cloneAgent(userId, validation.data!); + return createSuccessResponse(agent); + } catch (error) { + return handleError(error as Error); + } +} + +/** + * Handle list favorite agents request + */ +export async function handleListFavoriteAgents( + userId: string, + exclusiveStartKey?: string, + limit?: number +): Promise { + try { + // Input validation + const userValidation = validateUserId(userId); + if (!userValidation.isValid) { + throw new ValidationError(userValidation.error!); + } + + // Service layer handles business logic + const result = await agentService.listFavoriteAgents( + userId, + limit, + exclusiveStartKey + ); + return createSuccessResponse(result); + } catch (error) { + return handleError(error as Error); + } +} + +/** + * Handle toggle agent favorite request + */ +export async function handleToggleAgentFavorite( + userId: string, + agentId: string +): Promise { + try { + // Input validation + const userValidation = validateUserId(userId); + if (!userValidation.isValid) { + throw new ValidationError(userValidation.error!); + } + + const agentValidation = validateAgentId(agentId); + if (!agentValidation.isValid) { + throw new ValidationError(agentValidation.error!); + } + + // Service layer handles business logic + const result = await agentService.toggleAgentFavorite(userId, agentId); + return createSuccessResponse(result); + } catch (error) { + return handleError(error as Error); + } +} diff --git a/packages/cdk/lambda/agentBuilder/repositories/agent-repository.ts b/packages/cdk/lambda/agentBuilder/repositories/agent-repository.ts new file mode 100644 index 000000000..350537440 --- /dev/null +++ b/packages/cdk/lambda/agentBuilder/repositories/agent-repository.ts @@ -0,0 +1,818 @@ +/** + * Agent Repository + * + * DynamoDB Key Design: + * + * 1. User Agent Records: + * - PK: agent#{userId} + * - SK: agent#{agentId} + * - Purpose: Store user's own agents + * - Access: Direct access by userId + agentId + * + * 2. Public Agent Records (Denormalized): + * - PK: public-agents + * - SK: public#{agentId} + * - Purpose: Store public agents for discovery/marketplace + * - Access: Query all public agents or get specific public agent + * - Note: Contains full agent data with public-specific keys + * + * 3. Favorite Records: + * - PK: agent#{userId} + * - SK: favorite#{agentId} + * - Purpose: Track user's favorite agents + * - Access: Query user's favorites or check specific favorite + * - Additional Fields: createdBy (for optimization), createdAt + * + * Key Benefits: + * - Single table design with efficient access patterns + * - BatchGetItem optimization for multiple record retrieval + * - Denormalized public records for fast marketplace queries + * - Favorite records with createdBy for direct agent access + * + * Access Patterns: + * 1. Get user's agents: Query PK=agent#{userId}, SK begins_with agent# + * 2. Get public agents: Query PK=public-agents, SK begins_with public# + * 3. Get user's favorites: Query PK=agent#{userId}, SK begins_with favorite# + * 4. Get specific agent: BatchGet user + public locations + * 5. Check favorite status: BatchGet favorite records for specific agents + */ + +import { + BatchGetCommand, + DeleteCommand, + DynamoDBDocumentClient, + GetCommand, + PutCommand, + QueryCommand, + UpdateCommand, +} from '@aws-sdk/lib-dynamodb'; +import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; +import { v7 as uuidv7 } from 'uuid'; +import { + AgentInTable, + AgentAsOutput, + AgentContent, + RepositoryListAgentsResponse, +} from 'generative-ai-use-cases'; + +const TABLE_NAME: string = process.env.USECASE_TABLE_NAME!; +const dynamoDb = new DynamoDBClient({}); +const dynamoDbDocument = DynamoDBDocumentClient.from(dynamoDb); + +// Get agent by agentId with userId context (optimized with BatchGetItem) +const findAgentByAgentId = async ( + agentId: string, + userId: string +): Promise => { + // Use BatchGetItem to check both locations simultaneously + const result = await dynamoDbDocument.send( + new BatchGetCommand({ + RequestItems: { + [TABLE_NAME]: { + Keys: [ + { id: `agent#${userId}`, dataType: `agent#${agentId}` }, + { id: 'public-agents', dataType: `public#${agentId}` }, + ], + }, + }, + }) + ); + + if (!result.Responses?.[TABLE_NAME]) { + return null; + } + + // Prioritize user's own agent over public agent + for (const item of result.Responses[TABLE_NAME]) { + if (item.id === `agent#${userId}`) { + return item as AgentInTable; + } + } + + // If no user agent found, return public agent with key mapping + for (const item of result.Responses[TABLE_NAME]) { + if (item.id === 'public-agents') { + return { + ...item, + id: `agent#${item.createdBy}`, + dataType: `agent#${item.agentId}`, + } as AgentInTable; + } + } + + return null; +}; + +// Get agent list by userId +const findAgentsByUserId = async ( + userId: string, + exclusiveStartKey?: string, + limit: number = 12 +): Promise<{ agents: AgentInTable[]; lastEvaluatedKey?: string }> => { + const startKey = exclusiveStartKey + ? JSON.parse(Buffer.from(exclusiveStartKey, 'base64').toString()) + : undefined; + + const result = await dynamoDbDocument.send( + new QueryCommand({ + TableName: TABLE_NAME, + KeyConditionExpression: + '#id = :id and begins_with(#dataType, :dataTypePrefix)', + ExpressionAttributeNames: { + '#id': 'id', + '#dataType': 'dataType', + }, + ExpressionAttributeValues: { + ':id': `agent#${userId}`, + ':dataTypePrefix': 'agent#', + }, + ScanIndexForward: true, + Limit: Math.min(limit, 100), + ExclusiveStartKey: startKey, + }) + ); + + const agents = (result.Items || []) as AgentInTable[]; + + return { + agents, + lastEvaluatedKey: result.LastEvaluatedKey + ? Buffer.from(JSON.stringify(result.LastEvaluatedKey)).toString('base64') + : undefined, + }; +}; + +// Get favorites by userId +const findFavoritesByUserId = async ( + userId: string, + exclusiveStartKey?: string, + limit: number = 12 +): Promise<{ + favorites: Array<{ dataType: string; agentId: string; createdBy: string }>; + lastEvaluatedKey?: string; +}> => { + const startKey = exclusiveStartKey + ? JSON.parse(Buffer.from(exclusiveStartKey, 'base64').toString()) + : undefined; + + const result = await dynamoDbDocument.send( + new QueryCommand({ + TableName: TABLE_NAME, + KeyConditionExpression: + '#id = :id and begins_with(#dataType, :dataTypePrefix)', + ExpressionAttributeNames: { + '#id': 'id', + '#dataType': 'dataType', + }, + ExpressionAttributeValues: { + ':id': `agent#${userId}`, + ':dataTypePrefix': 'favorite#', + }, + ScanIndexForward: true, + Limit: Math.min(limit, 100), + ExclusiveStartKey: startKey, + }) + ); + + const favorites = (result.Items || []).map((item) => ({ + dataType: item.dataType, + agentId: item.dataType.replace('favorite#', ''), + createdBy: item.createdBy || '', + })); + + return { + favorites, + lastEvaluatedKey: result.LastEvaluatedKey + ? Buffer.from(JSON.stringify(result.LastEvaluatedKey)).toString('base64') + : undefined, + }; +}; + +// Get agents by favorites (optimized with single BatchGetItem) +const findAgentsByFavorites = async ( + favorites: Array<{ agentId: string; createdBy: string }>, + userId: string +): Promise => { + if (favorites.length === 0) return []; + + // Build all keys for single BatchGetItem call + const allKeys = favorites.map(({ agentId, createdBy }) => { + if (createdBy === userId) { + return { id: `agent#${userId}`, dataType: `agent#${agentId}` }; + } else { + return { id: 'public-agents', dataType: `public#${agentId}` }; + } + }); + + // Single BatchGetItem call for all agents + const result = await dynamoDbDocument.send( + new BatchGetCommand({ + RequestItems: { + [TABLE_NAME]: { + Keys: allKeys, + }, + }, + }) + ); + + if (!result.Responses?.[TABLE_NAME]) { + return []; + } + + // Map results to AgentInTable format + const agents = result.Responses[TABLE_NAME].map((item) => { + // Check if it's a public agent record (needs key mapping) + if (item.id === 'public-agents') { + return { + ...item, + id: `agent#${item.createdBy}`, + dataType: `agent#${item.agentId}`, + } as AgentInTable; + } else { + // User agent record (already in correct format) + return item as AgentInTable; + } + }); + + return agents; +}; + +// Manage public agent record +const managePublicAgentRecord = async ( + agentId: string, + isPublic: boolean, + agentData?: AgentInTable +): Promise => { + const key = { id: 'public-agents', dataType: `public#${agentId}` }; + + console.log( + `managePublicAgentRecord: agentId=${agentId}, isPublic=${isPublic}, hasAgentData=${!!agentData}` + ); + + if (isPublic && agentData) { + // Add/update public record with full data, but preserve the public record keys + console.log(`Creating/updating public record for agent ${agentId}`); + await dynamoDbDocument.send( + new PutCommand({ + TableName: TABLE_NAME, + Item: { + ...agentData, + ...key, + }, + }) + ); + console.log(`Public record created/updated for agent ${agentId}`); + } else { + // Remove public record + console.log(`Removing public record for agent ${agentId}`); + await dynamoDbDocument.send( + new DeleteCommand({ TableName: TABLE_NAME, Key: key }) + ); + console.log(`Public record removed for agent ${agentId}`); + } +}; + +// Get all public agents +export const listPublicAgents = async (): Promise => { + const result = await dynamoDbDocument.send( + new QueryCommand({ + TableName: TABLE_NAME, + KeyConditionExpression: + '#id = :id AND begins_with(#dataType, :dataTypePrefix)', + ExpressionAttributeNames: { + '#id': 'id', + '#dataType': 'dataType', + }, + ExpressionAttributeValues: { + ':id': 'public-agents', + ':dataTypePrefix': 'public#', + }, + }) + ); + + return (result.Items || []).map( + (item) => + ({ + ...item, + id: `agent#${item.createdBy}`, + dataType: `agent#${item.agentId}`, + }) as AgentInTable + ); +}; + +export const createAgent = async ( + userId: string, + content: AgentContent +): Promise => { + const agentId = uuidv7(); + const now = new Date().toISOString(); + + const item: AgentInTable = { + id: `agent#${userId}`, + dataType: `agent#${agentId}`, + agentId, + name: content.name, + description: content.description || '', + systemPrompt: content.systemPrompt, + modelId: content.modelId, + mcpServers: content.mcpServers, + codeExecutionEnabled: content.codeExecutionEnabled ?? false, + tags: content.tags || [], + isPublic: content.isPublic ?? false, + starCount: 0, + createdAt: now, + updatedAt: now, + createdByEmail: content.createdByEmail, + createdBy: userId, + }; + + await dynamoDbDocument.send( + new PutCommand({ TableName: TABLE_NAME, Item: item }) + ); + + if (item.isPublic) { + await managePublicAgentRecord(agentId, true, item); + } + + return { ...item, isMyAgent: true }; +}; + +export const getAgent = async ( + userId: string, + agentId: string +): Promise => { + const agent = await findAgentByAgentId(agentId, userId); + if (!agent) return null; + + const isMyAgent = agent.createdBy === userId; + + // Access control: must be my agent or public + if (!isMyAgent && !agent.isPublic) { + return null; + } + + return { ...agent, isMyAgent }; +}; + +export const listAgents = async ( + userId: string, + exclusiveStartKey?: string, + limit?: number +): Promise => { + const { agents, lastEvaluatedKey } = await findAgentsByUserId( + userId, + exclusiveStartKey, + limit + ); + + return { + data: agents.map((agent) => ({ ...agent, isMyAgent: true })), + lastEvaluatedKey, + }; +}; + +export const updateAgent = async ( + userId: string, + agentId: string, + content: AgentContent +): Promise => { + const agent = await findAgentByAgentId(agentId, userId); + if (!agent || agent.createdBy !== userId) { + throw new Error(`Agent not found or access denied: ${agentId}`); + } + + const now = new Date().toISOString(); + const wasPublic = agent.isPublic; + const isNowPublic = content.isPublic ?? false; + + // Update main agent record + await dynamoDbDocument.send( + new UpdateCommand({ + TableName: TABLE_NAME, + Key: { id: agent.id, dataType: agent.dataType }, + UpdateExpression: + 'set #name = :name, description = :description, systemPrompt = :systemPrompt, modelId = :modelId, mcpServers = :mcpServers, codeExecutionEnabled = :codeExecutionEnabled, tags = :tags, isPublic = :isPublic, updatedAt = :updatedAt, createdByEmail = :createdByEmail', + ExpressionAttributeNames: { '#name': 'name' }, + ExpressionAttributeValues: { + ':name': content.name, + ':description': content.description || '', + ':systemPrompt': content.systemPrompt, + ':modelId': content.modelId, + ':mcpServers': content.mcpServers, + ':codeExecutionEnabled': content.codeExecutionEnabled ?? false, + ':tags': content.tags || [], + ':isPublic': isNowPublic, + ':updatedAt': now, + ':createdByEmail': content.createdByEmail, + }, + }) + ); + + // Update public record if needed + const updatedAgent: AgentInTable = { + ...agent, + ...content, + description: content.description || '', + codeExecutionEnabled: content.codeExecutionEnabled ?? false, + tags: content.tags || [], + isPublic: isNowPublic, + updatedAt: now, + }; + + if (wasPublic !== isNowPublic || isNowPublic) { + await managePublicAgentRecord(agentId, isNowPublic, updatedAgent); + } +}; + +export const deleteAgent = async ( + userId: string, + agentId: string +): Promise => { + const agent = await findAgentByAgentId(agentId, userId); + if (!agent || agent.createdBy !== userId) { + throw new Error(`Agent not found or access denied: ${agentId}`); + } + + await dynamoDbDocument.send( + new DeleteCommand({ + TableName: TABLE_NAME, + Key: { id: agent.id, dataType: agent.dataType }, + }) + ); + + if (agent.isPublic) { + await managePublicAgentRecord(agentId, false); + } +}; + +export const listAgentsWithFavorites = async ( + userId: string, + exclusiveStartKey?: string, + limit: number = 12 +): Promise<{ + data: (AgentAsOutput & { isFavorite: boolean })[]; + lastEvaluatedKey?: string; +}> => { + // First get the agents + const agentsResult = await findAgentsByUserId( + userId, + exclusiveStartKey, + limit + ); + + if (agentsResult.agents.length === 0) { + return { + data: [], + lastEvaluatedKey: agentsResult.lastEvaluatedKey, + }; + } + + // Build favorite keys for the specific agents we retrieved + const favoriteKeys = agentsResult.agents.map((agent) => ({ + id: `agent#${userId}`, + dataType: `favorite#${agent.agentId}`, + })); + + // BatchGetItem to check favorite status for these specific agents + const favoriteResult = await dynamoDbDocument.send( + new BatchGetCommand({ + RequestItems: { + [TABLE_NAME]: { + Keys: favoriteKeys, + }, + }, + }) + ); + + // Create a set of favorited agent IDs for quick lookup + const favoritedAgentIds = new Set( + (favoriteResult.Responses?.[TABLE_NAME] || []).map((item) => + item.dataType.replace('favorite#', '') + ) + ); + + return { + data: agentsResult.agents.map((agent) => ({ + ...agent, + isMyAgent: true, + isFavorite: favoritedAgentIds.has(agent.agentId), + })), + lastEvaluatedKey: agentsResult.lastEvaluatedKey, + }; +}; + +export const listPublicAgentsWithFavorites = async ( + userId: string, + limit: number = 50 +): Promise<(AgentInTable & { isFavorite: boolean; isMyAgent: boolean })[]> => { + // Use the paginated version with a reasonable default limit + const result = await listPublicAgentsWithFavoritesPaginated( + userId, + undefined, + limit + ); + return result.data; +}; + +export const listPublicAgentsWithFavoritesPaginated = async ( + userId: string, + exclusiveStartKey?: string, + limit: number = 12 +): Promise<{ + data: (AgentAsOutput & { isFavorite: boolean; isMyAgent: boolean })[]; + lastEvaluatedKey?: string; +}> => { + const startKey = exclusiveStartKey + ? JSON.parse(Buffer.from(exclusiveStartKey, 'base64').toString()) + : undefined; + + // First get the public agents + const publicResult = await dynamoDbDocument.send( + new QueryCommand({ + TableName: TABLE_NAME, + KeyConditionExpression: + '#id = :id AND begins_with(#dataType, :dataTypePrefix)', + ExpressionAttributeNames: { + '#id': 'id', + '#dataType': 'dataType', + }, + ExpressionAttributeValues: { + ':id': 'public-agents', + ':dataTypePrefix': 'public#', + }, + ScanIndexForward: true, + Limit: Math.min(limit, 100), + ExclusiveStartKey: startKey, + }) + ); + + const agents = (publicResult.Items || []).map( + (item) => + ({ + ...item, + id: `agent#${item.createdBy}`, + dataType: `agent#${item.agentId}`, + }) as AgentInTable + ); + + if (agents.length === 0) { + return { + data: [], + lastEvaluatedKey: publicResult.LastEvaluatedKey + ? Buffer.from(JSON.stringify(publicResult.LastEvaluatedKey)).toString( + 'base64' + ) + : undefined, + }; + } + + // Build favorite keys for the specific public agents we retrieved + const favoriteKeys = agents.map((agent) => ({ + id: `agent#${userId}`, + dataType: `favorite#${agent.agentId}`, + })); + + // BatchGetItem to check favorite status for these specific agents + const favoriteResult = await dynamoDbDocument.send( + new BatchGetCommand({ + RequestItems: { + [TABLE_NAME]: { + Keys: favoriteKeys, + }, + }, + }) + ); + + // Create a set of favorited agent IDs for quick lookup + const favoritedAgentIds = new Set( + (favoriteResult.Responses?.[TABLE_NAME] || []).map((item) => + item.dataType.replace('favorite#', '') + ) + ); + + return { + data: agents.map((agent) => ({ + ...agent, + isFavorite: favoritedAgentIds.has(agent.agentId), + isMyAgent: agent.createdBy === userId, + })), + lastEvaluatedKey: publicResult.LastEvaluatedKey + ? Buffer.from(JSON.stringify(publicResult.LastEvaluatedKey)).toString( + 'base64' + ) + : undefined, + }; +}; + +export const listFavoriteAgents = async ( + userId: string, + exclusiveStartKey?: string, + limit?: number +): Promise<{ data: AgentAsOutput[]; lastEvaluatedKey?: string }> => { + const favoritesResult = await findFavoritesByUserId( + userId, + exclusiveStartKey, + limit + ); + + const agents = await findAgentsByFavorites(favoritesResult.favorites, userId); + + // Create a map for quick agent lookup + const agentMap = new Map(agents.map((agent) => [agent.agentId, agent])); + + // Maintain the order from favorites and include status information + const orderedAgents = favoritesResult.favorites.map((favorite) => { + const agent = agentMap.get(favorite.agentId); + + if (!agent) { + // Agent was deleted - create a placeholder with minimal info + return { + id: `agent#unknown`, + dataType: `agent#${favorite.agentId}`, + agentId: favorite.agentId, + name: 'Deleted Agent', + description: 'This agent has been deleted', + systemPrompt: '', + modelId: '', + mcpServers: [], + codeExecutionEnabled: false, + tags: [], + isPublic: false, + starCount: 0, + createdAt: '', + updatedAt: '', + createdBy: favorite.createdBy || '', + createdByEmail: '', + isMyAgent: false, + status: 'deleted' as const, + }; + } + + // Agent exists but check accessibility + const isMyAgent = agent.createdBy === userId; + let status: 'available' | 'private' = 'available'; + + if (!isMyAgent && !agent.isPublic) { + status = 'private'; + } + + return { + ...agent, + isMyAgent, + status, + }; + }); + + return { + data: orderedAgents, + lastEvaluatedKey: favoritesResult.lastEvaluatedKey, + }; +}; + +export const isFavoriteAgent = async ( + userId: string, + agentId: string +): Promise => { + const result = await dynamoDbDocument.send( + new GetCommand({ + TableName: TABLE_NAME, + Key: { id: `agent#${userId}`, dataType: `favorite#${agentId}` }, + ProjectionExpression: '#id', // Only need to check existence + ExpressionAttributeNames: { '#id': 'id' }, + }) + ); + return !!result.Item; +}; + +export const toggleFavorite = async ( + userId: string, + agentId: string +): Promise<{ isFavorite: boolean }> => { + const key = { id: `agent#${userId}`, dataType: `favorite#${agentId}` }; + + // Use BatchGetItem to get both favorite status and agent info simultaneously + const result = await dynamoDbDocument.send( + new BatchGetCommand({ + RequestItems: { + [TABLE_NAME]: { + Keys: [ + key, + { id: `agent#${userId}`, dataType: `agent#${agentId}` }, + { id: 'public-agents', dataType: `public#${agentId}` }, + ], + }, + }, + }) + ); + + const items = result.Responses?.[TABLE_NAME] || []; + const existingFavorite = items.find( + (item) => item.id === key.id && item.dataType === key.dataType + ); + + // Find agent (prioritize user's own agent) + let agent = items.find( + (item) => + item.id === `agent#${userId}` && item.dataType === `agent#${agentId}` + ); + if (!agent) { + agent = items.find((item) => item.id === 'public-agents'); + if (agent) { + // Map public agent to standard format + agent = { + ...agent, + id: `agent#${agent.createdBy}`, + dataType: `agent#${agent.agentId}`, + }; + } + } + + const updateOperations = []; + + if (existingFavorite) { + // Remove from favorites - always allow this operation (even for deleted agents) + updateOperations.push( + dynamoDbDocument.send( + new DeleteCommand({ TableName: TABLE_NAME, Key: key }) + ) + ); + + // Only update star count if agent still exists + if (agent) { + updateOperations.push( + dynamoDbDocument.send( + new UpdateCommand({ + TableName: TABLE_NAME, + Key: { id: agent.id, dataType: agent.dataType }, + UpdateExpression: 'ADD starCount :dec', + ExpressionAttributeValues: { ':dec': -1 }, + }) + ) + ); + + // Update public record if agent is public + if (agent.isPublic) { + updateOperations.push( + dynamoDbDocument.send( + new UpdateCommand({ + TableName: TABLE_NAME, + Key: { id: 'public-agents', dataType: `public#${agentId}` }, + UpdateExpression: 'ADD starCount :dec', + ExpressionAttributeValues: { ':dec': -1 }, + }) + ) + ); + } + } + + await Promise.all(updateOperations); + return { isFavorite: false }; + } else { + // Cannot add deleted/non-existent agents to favorites + if (!agent) { + throw new Error( + `Cannot add deleted or non-existent agent to favorites: ${agentId}` + ); + } + + // Add to favorites and increment star count + updateOperations.push( + dynamoDbDocument.send( + new PutCommand({ + TableName: TABLE_NAME, + Item: { + ...key, + agentId, + createdBy: agent.createdBy, + createdAt: new Date().toISOString(), + }, + }) + ), + dynamoDbDocument.send( + new UpdateCommand({ + TableName: TABLE_NAME, + Key: { id: agent.id, dataType: agent.dataType }, + UpdateExpression: 'ADD starCount :inc', + ExpressionAttributeValues: { ':inc': 1 }, + }) + ) + ); + + // Update public record if agent is public + if (agent.isPublic) { + updateOperations.push( + dynamoDbDocument.send( + new UpdateCommand({ + TableName: TABLE_NAME, + Key: { id: 'public-agents', dataType: `public#${agentId}` }, + UpdateExpression: 'ADD starCount :inc', + ExpressionAttributeValues: { ':inc': 1 }, + }) + ) + ); + } + + await Promise.all(updateOperations); + return { isFavorite: true }; + } +}; diff --git a/packages/cdk/lambda/agentBuilder/router.ts b/packages/cdk/lambda/agentBuilder/router.ts new file mode 100644 index 000000000..8218c706d --- /dev/null +++ b/packages/cdk/lambda/agentBuilder/router.ts @@ -0,0 +1,157 @@ +import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda'; + +// Import handlers +import { + handleCreateAgent, + handleGetAgent, + handleUpdateAgent, + handleDeleteAgent, + handleListUserAgents, + handleListPublicAgents, + handleCloneAgent, + handleListFavoriteAgents, + handleToggleAgentFavorite, +} from './handlers/agent-handlers'; + +import { createNotFoundResponse } from './utils/response-utils'; +import { validateAndParseRequestBody } from './validation/request-validation'; +import { handleError } from './utils/error-handling'; +import { + CreateAgentRequest, + CloneAgentRequest, + UpdateAgentRequest, +} from 'generative-ai-use-cases'; + +/** + * Route requests to appropriate handlers with error handling + */ +export async function routeRequest( + event: APIGatewayProxyEvent, + userId: string +): Promise { + try { + const { + resource, + httpMethod, + pathParameters, + body, + queryStringParameters, + } = event; + const exclusiveStartKey = + queryStringParameters?.exclusiveStartKey || + queryStringParameters?.nextToken; + const limit = queryStringParameters?.limit + ? parseInt(queryStringParameters.limit, 10) + : undefined; + + // Agent routes + if (resource === '/agents') { + if (httpMethod === 'POST') { + const parseResult = validateAndParseRequestBody(body); + if (!parseResult.isValid) { + return handleError(new Error(parseResult.error!)); + } + return await handleCreateAgent( + userId, + parseResult.data as CreateAgentRequest + ); + } + if (httpMethod === 'GET') { + return await handleListUserAgents(userId, exclusiveStartKey, limit); + } + } + + // Public agents route + if (resource === '/agents/public' && httpMethod === 'GET') { + return await handleListPublicAgents(userId, exclusiveStartKey, limit); + } + + // Import agent route + if (resource === '/agents/clone' && httpMethod === 'POST') { + const parseResult = validateAndParseRequestBody(body); + if (!parseResult.isValid) { + return handleError(new Error(parseResult.error!)); + } + return await handleCloneAgent( + userId, + parseResult.data as CloneAgentRequest + ); + } + + // Favorite agents route + if (resource === '/agents/favorites' && httpMethod === 'GET') { + return await handleListFavoriteAgents(userId, exclusiveStartKey, limit); + } + + // Individual agent routes and sub-routes + if (resource === '/agents/{proxy+}') { + const pathParts = (pathParameters?.proxy || '').split('/'); + const agentId = pathParts[0]; + + if (!agentId) { + return createNotFoundResponse('Agent ID is required'); + } + + // Handle special routes with clear semantics + if (agentId === 'my' && httpMethod === 'GET') { + return await handleListUserAgents(userId, exclusiveStartKey, limit); + } + + if (agentId === 'public' && httpMethod === 'GET') { + return await handleListPublicAgents(userId, exclusiveStartKey, limit); + } + + if (agentId === 'favorites' && httpMethod === 'GET') { + return await handleListFavoriteAgents(userId, exclusiveStartKey, limit); + } + + if (agentId === 'import' && httpMethod === 'POST') { + const parseResult = validateAndParseRequestBody(body); + if (!parseResult.isValid) { + return handleError(new Error(parseResult.error!)); + } + return await handleCloneAgent( + userId, + parseResult.data as CloneAgentRequest + ); + } + + // Individual agent operations + if (pathParts.length === 1) { + if (httpMethod === 'GET') { + return await handleGetAgent(userId, agentId); + } + if (httpMethod === 'PUT') { + const parseResult = validateAndParseRequestBody(body); + if (!parseResult.isValid) { + return handleError(new Error(parseResult.error!)); + } + return await handleUpdateAgent( + userId, + agentId, + parseResult.data as UpdateAgentRequest + ); + } + if (httpMethod === 'DELETE') { + return await handleDeleteAgent(userId, agentId); + } + } + + // Sub-routes + if (pathParts.length > 1) { + const subRoute = pathParts[1]; + + // share endpoint removed - use PUT /agents/{agentId} with isPublic flag instead + + if (subRoute === 'favorite' && httpMethod === 'POST') { + return await handleToggleAgentFavorite(userId, agentId); + } + } + } + + // Default: not found + return createNotFoundResponse(); + } catch (error) { + return handleError(error as Error); + } +} diff --git a/packages/cdk/lambda/agentBuilder/services/agent-service.ts b/packages/cdk/lambda/agentBuilder/services/agent-service.ts new file mode 100644 index 000000000..c427f6ee1 --- /dev/null +++ b/packages/cdk/lambda/agentBuilder/services/agent-service.ts @@ -0,0 +1,323 @@ +import { + AgentConfiguration, + ListAgentsResponse, + CreateAgentRequest, + UpdateAgentRequest, + AgentAsOutput, + CloneAgentRequest, + ClonedAgentResponse, +} from 'generative-ai-use-cases'; +import * as agentRepository from '../repositories/agent-repository'; +import { getUserEmail } from '../utils/auth-utils'; +import { + NotFoundError, + ForbiddenError, + UnauthorizedError, +} from '../utils/error-handling'; + +/** + * Convert AgentAsOutput to AgentConfiguration + */ +function convertToAgentConfiguration( + agent: AgentAsOutput & { isFavorite?: boolean } +): AgentConfiguration { + return { + agentId: agent.agentId, + name: agent.name, + description: agent.description, + systemPrompt: agent.systemPrompt, + mcpServers: agent.mcpServers || [], + modelId: agent.modelId, + codeExecutionEnabled: agent.codeExecutionEnabled || false, + isPublic: agent.isPublic || false, + shareId: undefined, // Not available in AgentAsOutput + createdAt: agent.createdAt, + updatedAt: agent.updatedAt, + tags: agent.tags || [], + starCount: agent.starCount || 0, + createdBy: agent.id ? agent.id.split('#')[1] : 'Unknown', + createdByEmail: agent.createdByEmail, + isFavorite: agent.isFavorite ?? false, // Use the actual favorite status + isMyAgent: agent.isMyAgent, + }; +} + +/** + * Create a new agent + */ +export async function createAgent( + userId: string, + request: CreateAgentRequest +): Promise { + // MCP server names (no sanitization needed for string array) + const mcpServerNames = request.mcpServers || []; + + // Get user email from Cognito + const userEmail = await getUserEmail(userId); + + const agent = await agentRepository.createAgent(userId, { + name: request.name.trim(), + description: (request.description || '').trim(), + systemPrompt: request.systemPrompt.trim(), + mcpServers: mcpServerNames, + modelId: request.modelId, + codeExecutionEnabled: request.codeExecutionEnabled ?? false, + isPublic: request.isPublic ?? false, + tags: (request.tags || []) + .map((tag) => tag.trim()) + .filter((tag) => tag.length > 0), + createdByEmail: userEmail, + }); + + console.log(`Agent created: ${agent.agentId} by user: ${userId}`); + return convertToAgentConfiguration(agent); +} + +/** + * Get an agent by ID + */ +export async function getAgent( + userId: string, + agentId: string +): Promise { + const agent = await agentRepository.getAgent(userId, agentId); + + if (!agent) { + throw new NotFoundError('Agent not found'); + } + + return convertToAgentConfiguration(agent); +} + +/** + * Update an existing agent + */ +export async function updateAgent( + userId: string, + agentId: string, + request: UpdateAgentRequest +): Promise { + // Business validation: Check if agent exists and user owns it + const existingAgent = await agentRepository.getAgent(userId, agentId); + if (!existingAgent) { + throw new NotFoundError('Agent not found'); + } + + // Version check removed - using starCount instead + + // MCP server names + const mcpServerNames = request.mcpServers || existingAgent.mcpServers; + + // Get user email from Cognito if not provided in request + const userEmail = request.createdByEmail || (await getUserEmail(userId)); + + try { + await agentRepository.updateAgent(userId, agentId, { + name: request.name?.trim() || existingAgent.name, + description: request.description?.trim() || existingAgent.description, + systemPrompt: request.systemPrompt?.trim() || existingAgent.systemPrompt, + mcpServers: mcpServerNames, + modelId: request.modelId || existingAgent.modelId, + codeExecutionEnabled: + request.codeExecutionEnabled ?? + existingAgent.codeExecutionEnabled ?? + false, + tags: + request.tags + ?.map((tag) => tag.trim()) + .filter((tag) => tag.length > 0) || existingAgent.tags, + isPublic: request.isPublic ?? existingAgent.isPublic ?? false, + createdByEmail: userEmail, + }); + } catch (error) { + if (error instanceof Error && error.message.includes('Access denied')) { + throw new ForbiddenError( + 'You do not have permission to update this agent' + ); + } + if (error instanceof Error && error.message.includes('Agent not found')) { + throw new NotFoundError('Agent not found'); + } + throw error; + } + + // Get updated agent + const agent = await agentRepository.getAgent(userId, agentId); + if (!agent) { + throw new NotFoundError('Agent not found after update'); + } + + console.log(`Agent updated: ${agentId} by user: ${userId}`); + return convertToAgentConfiguration(agent); +} + +/** + * Delete an agent + */ +export async function deleteAgent( + userId: string, + agentId: string +): Promise { + // Check if agent exists first + const existingAgent = await agentRepository.getAgent(userId, agentId); + if (!existingAgent) { + throw new NotFoundError('Agent not found'); + } + + try { + await agentRepository.deleteAgent(userId, agentId); + console.log(`Agent deleted: ${agentId} by user: ${userId}`); + } catch (error) { + if (error instanceof Error && error.message.includes('Access denied')) { + throw new ForbiddenError( + 'You do not have permission to delete this agent' + ); + } + if (error instanceof Error && error.message.includes('Agent not found')) { + throw new NotFoundError('Agent not found'); + } + throw error; + } +} + +/** + * List user's agents + */ +export async function listUserAgents( + userId: string, + limit?: number, + nextToken?: string +): Promise { + console.log( + `listUserAgents service: userId=${userId}, limit=${limit}, nextToken=${nextToken}` + ); + + const result = await agentRepository.listAgentsWithFavorites( + userId, + nextToken, + limit + ); + + console.log( + `listUserAgents service result: agents=${result.data.length}, nextToken=${result.lastEvaluatedKey}` + ); + + return { + agents: result.data.map((agent) => convertToAgentConfiguration(agent)), + nextToken: result.lastEvaluatedKey, + totalCount: undefined, // Remove totalCount to avoid full table scan + type: 'my', + }; +} + +/** + * List public agents (always returns latest data) + */ +export async function listPublicAgents( + userId: string, + limit?: number, + nextToken?: string +): Promise { + const result = await agentRepository.listPublicAgentsWithFavoritesPaginated( + userId, + nextToken, + limit + ); + + return { + agents: result.data.map((agent) => convertToAgentConfiguration(agent)), + nextToken: result.lastEvaluatedKey, + totalCount: undefined, // Remove totalCount to avoid full table scan + type: 'public', + }; +} + +/** + * List favorite agents (always returns latest data) + */ +export async function listFavoriteAgents( + userId: string, + limit?: number, + nextToken?: string +): Promise { + const result = await agentRepository.listFavoriteAgents( + userId, + nextToken, + limit + ); + + return { + agents: result.data.map((agent) => ({ + ...convertToAgentConfiguration(agent), + isFavorite: true, // All agents in this list are favorites + isMyAgent: agent.isMyAgent || false, // Ensure boolean type + })), + nextToken: result.lastEvaluatedKey, + totalCount: undefined, // Remove totalCount to avoid full table scan + type: 'favorites', + }; +} + +/** + * Toggle agent favorite status + */ +export async function toggleAgentFavorite( + userId: string, + agentId: string +): Promise<{ isFavorite: boolean }> { + return await agentRepository.toggleFavorite(userId, agentId); +} + +/** + * Clone an agent + */ +export async function cloneAgent( + userId: string, + request: CloneAgentRequest +): Promise { + // Use agent repository for consistent access pattern + const sourceAgent = await agentRepository.getAgent( + userId, + request.sourceAgentId + ); + + if (!sourceAgent) { + throw new NotFoundError('Source agent not found'); + } + + // Check if the source agent is public or owned by the user + const isPublic = sourceAgent.isPublic ?? false; + if (!isPublic && !sourceAgent.isMyAgent) { + throw new UnauthorizedError('Agent is not public and you do not own it'); + } + + // Create a new agent using the repository + const newAgent = await agentRepository.createAgent(userId, { + name: request.name || `${sourceAgent.name} (Cloned)`, + description: sourceAgent.description, + systemPrompt: sourceAgent.systemPrompt, + modelId: sourceAgent.modelId, + mcpServers: sourceAgent.mcpServers || [], + codeExecutionEnabled: sourceAgent.codeExecutionEnabled || false, + tags: sourceAgent.tags || [], + isPublic: false, // Cloned agents are private by default + }); + + console.log( + `Agent cloned: ${newAgent.agentId} from ${request.sourceAgentId} by user: ${userId}` + ); + + return { + agentId: newAgent.agentId, + name: newAgent.name, + description: newAgent.description, + systemPrompt: newAgent.systemPrompt, + modelId: newAgent.modelId, + mcpServers: newAgent.mcpServers, + codeExecutionEnabled: newAgent.codeExecutionEnabled, + tags: newAgent.tags, + isPublic: newAgent.isPublic, + createdAt: newAgent.createdAt, + updatedAt: newAgent.updatedAt, + }; +} diff --git a/packages/cdk/lambda/agentBuilder/utils/auth-utils.ts b/packages/cdk/lambda/agentBuilder/utils/auth-utils.ts new file mode 100644 index 000000000..403d4293b --- /dev/null +++ b/packages/cdk/lambda/agentBuilder/utils/auth-utils.ts @@ -0,0 +1,44 @@ +import { APIGatewayProxyEvent } from 'aws-lambda'; +import { + CognitoIdentityProviderClient, + AdminGetUserCommand, + AttributeType, +} from '@aws-sdk/client-cognito-identity-provider'; + +// Initialize Cognito client +const cognitoClient = new CognitoIdentityProviderClient({}); + +/** + * Extract user ID from API Gateway event + */ +export function getUserIdFromEvent(event: APIGatewayProxyEvent): string { + const userId = event.requestContext.authorizer!.claims['cognito:username']; + if (!userId) { + throw new Error('User not authenticated'); + } + return userId; +} + +/** + * Get user email from Cognito + */ +export async function getUserEmail( + userId: string +): Promise { + try { + const command = new AdminGetUserCommand({ + UserPoolId: process.env.USER_POOL_ID!, + Username: userId, + }); + + const response = await cognitoClient.send(command); + const emailAttribute = response.UserAttributes?.find( + (attr: AttributeType) => attr.Name === 'email' + ); + + return emailAttribute?.Value; + } catch (error) { + console.error('Error getting user email:', error); + return undefined; + } +} diff --git a/packages/cdk/lambda/agentBuilder/utils/error-handling.ts b/packages/cdk/lambda/agentBuilder/utils/error-handling.ts new file mode 100644 index 000000000..03bb9c0d6 --- /dev/null +++ b/packages/cdk/lambda/agentBuilder/utils/error-handling.ts @@ -0,0 +1,89 @@ +import { APIGatewayProxyResult } from 'aws-lambda'; +import { + createErrorResponse, + createNotFoundResponse, + createUnauthorizedResponse, + createInternalServerErrorResponse, +} from './response-utils'; + +/** + * Custom error classes for better error handling + */ +export class ValidationError extends Error { + constructor(message: string) { + super(message); + this.name = 'ValidationError'; + } +} + +export class NotFoundError extends Error { + constructor(message: string) { + super(message); + this.name = 'NotFoundError'; + } +} + +export class UnauthorizedError extends Error { + constructor(message: string) { + super(message); + this.name = 'UnauthorizedError'; + } +} + +export class ConflictError extends Error { + public currentVersion?: number; + + constructor(message: string, currentVersion?: number) { + super(message); + this.name = 'ConflictError'; + this.currentVersion = currentVersion; + } +} + +export class ForbiddenError extends Error { + constructor(message: string) { + super(message); + this.name = 'ForbiddenError'; + } +} + +/** + * Handle errors and return appropriate API Gateway response + */ +export function handleError(error: Error): APIGatewayProxyResult { + console.error('Error occurred:', error); + + if (error instanceof ValidationError) { + return createErrorResponse(error.message, 400); + } + + if (error instanceof NotFoundError) { + return createNotFoundResponse(error.message); + } + + if (error instanceof UnauthorizedError) { + return createUnauthorizedResponse(error.message); + } + + if (error instanceof ForbiddenError) { + return createErrorResponse(error.message, 403); + } + + if (error instanceof ConflictError) { + const body = error.currentVersion + ? { error: error.message, currentVersion: error.currentVersion } + : { error: error.message }; + + return { + statusCode: 409, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify(body), + }; + } + + // Default to internal server error for unexpected errors + return createInternalServerErrorResponse('Internal server error'); +} diff --git a/packages/cdk/lambda/agentBuilder/utils/response-utils.ts b/packages/cdk/lambda/agentBuilder/utils/response-utils.ts new file mode 100644 index 000000000..998022849 --- /dev/null +++ b/packages/cdk/lambda/agentBuilder/utils/response-utils.ts @@ -0,0 +1,62 @@ +import { APIGatewayProxyResult } from 'aws-lambda'; + +/** + * Create a standardized success response + */ +export function createSuccessResponse( + data: unknown, + statusCode: number = 200 +): APIGatewayProxyResult { + return { + statusCode, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify(data), + }; +} + +/** + * Create a standardized error response + */ +export function createErrorResponse( + error: string, + statusCode: number = 400 +): APIGatewayProxyResult { + return { + statusCode, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify({ error }), + }; +} + +/** + * Create a not found response + */ +export function createNotFoundResponse( + message: string = 'Not found' +): APIGatewayProxyResult { + return createErrorResponse(message, 404); +} + +/** + * Create an unauthorized response + */ +export function createUnauthorizedResponse( + message: string = 'Unauthorized' +): APIGatewayProxyResult { + return createErrorResponse(message, 403); +} + +/** + * Create an internal server error response + */ +export function createInternalServerErrorResponse( + message: string = 'Internal server error' +): APIGatewayProxyResult { + return createErrorResponse(message, 500); +} diff --git a/packages/cdk/lambda/agentBuilder/validation/agent-validation.ts b/packages/cdk/lambda/agentBuilder/validation/agent-validation.ts new file mode 100644 index 000000000..527c241e0 --- /dev/null +++ b/packages/cdk/lambda/agentBuilder/validation/agent-validation.ts @@ -0,0 +1,50 @@ +import { z } from 'zod'; +import { + CreateAgentRequestSchema, + UpdateAgentRequestSchema, + CreateAgentRequestValidation, + UpdateAgentRequestValidation, +} from './schemas'; +import { ValidationResult } from 'generative-ai-use-cases'; + +// ValidationResult interface is now imported from generative-ai-use-cases types + +/** + * Validate create agent request using Zod + * @param request Create agent request to validate + * @returns Validation result with validated data + */ +export function validateCreateAgentRequest( + request: unknown +): ValidationResult { + try { + const validatedData = CreateAgentRequestSchema.parse(request); + return { isValid: true, data: validatedData }; + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessage = error.errors.map((err) => err.message).join(', '); + return { isValid: false, error: errorMessage }; + } + return { isValid: false, error: 'Invalid request format' }; + } +} + +/** + * Validate update agent request using Zod + * @param request Update agent request to validate + * @returns Validation result with validated data + */ +export function validateUpdateAgentRequest( + request: unknown +): ValidationResult { + try { + const validatedData = UpdateAgentRequestSchema.parse(request); + return { isValid: true, data: validatedData }; + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessage = error.errors.map((err) => err.message).join(', '); + return { isValid: false, error: errorMessage }; + } + return { isValid: false, error: 'Invalid request format' }; + } +} diff --git a/packages/cdk/lambda/agentBuilder/validation/request-validation.ts b/packages/cdk/lambda/agentBuilder/validation/request-validation.ts new file mode 100644 index 000000000..a1486b7bb --- /dev/null +++ b/packages/cdk/lambda/agentBuilder/validation/request-validation.ts @@ -0,0 +1,127 @@ +import { z } from 'zod'; +import { + ShareAgentRequestSchema, + CloneAgentRequestSchema, + AgentIdSchema, + UserIdSchema, + PaginationKeySchema, + RequestBodySchema, + ShareAgentRequestValidation, + CloneAgentRequestValidation, +} from './schemas'; +import { ValidationResult } from 'generative-ai-use-cases'; + +/** + * Validate share agent request using Zod + * @param request Share agent request to validate + * @returns Validation result with validated data + */ +export function validateShareAgentRequest( + request: unknown +): ValidationResult { + try { + const validatedData = ShareAgentRequestSchema.parse(request); + return { isValid: true, data: validatedData }; + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessage = error.errors.map((err) => err.message).join(', '); + return { isValid: false, error: errorMessage }; + } + return { isValid: false, error: 'Invalid request format' }; + } +} + +/** + * Validate import agent request using Zod + * @param request Import agent request to validate + * @returns Validation result with validated data + */ +export function validateCloneAgentRequest( + request: unknown +): ValidationResult { + try { + const validatedData = CloneAgentRequestSchema.parse(request); + return { isValid: true, data: validatedData }; + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessage = error.errors.map((err) => err.message).join(', '); + return { isValid: false, error: errorMessage }; + } + return { isValid: false, error: 'Invalid request format' }; + } +} + +/** + * Validate agent ID parameter using Zod + * @param agentId Agent ID to validate + * @returns Validation result + */ +export function validateAgentId(agentId: unknown): ValidationResult { + try { + AgentIdSchema.parse(agentId); + return { isValid: true }; + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessage = error.errors.map((err) => err.message).join(', '); + return { isValid: false, error: errorMessage }; + } + return { isValid: false, error: 'Invalid agent ID format' }; + } +} + +/** + * Validate user ID parameter using Zod + * @param userId User ID to validate + * @returns Validation result + */ +export function validateUserId(userId: unknown): ValidationResult { + try { + UserIdSchema.parse(userId); + return { isValid: true }; + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessage = error.errors.map((err) => err.message).join(', '); + return { isValid: false, error: errorMessage }; + } + return { isValid: false, error: 'Invalid user ID format' }; + } +} + +/** + * Validate pagination parameters using Zod + * @param exclusiveStartKey Exclusive start key for pagination + * @returns Validation result + */ +export function validatePaginationParams( + exclusiveStartKey: unknown +): ValidationResult { + try { + PaginationKeySchema.parse(exclusiveStartKey); + return { isValid: true }; + } catch (error) { + return { isValid: false, error: 'Invalid pagination key format' }; + } +} + +/** + * Validate and parse request body using Zod + * @param body Request body string + * @returns Parsed object or validation error + */ +export function validateAndParseRequestBody( + body: string | null +): { isValid: true; data: T } | ValidationResult { + try { + // First validate that we have a body + const validBody = RequestBodySchema.parse(body); + + // Then parse JSON + const data = JSON.parse(validBody) as T; + return { isValid: true, data }; + } catch (error) { + if (error instanceof z.ZodError) { + return { isValid: false, error: 'Request body is required' }; + } + return { isValid: false, error: 'Invalid JSON in request body' }; + } +} diff --git a/packages/cdk/lambda/agentBuilder/validation/schemas.ts b/packages/cdk/lambda/agentBuilder/validation/schemas.ts new file mode 100644 index 000000000..7a7d0af37 --- /dev/null +++ b/packages/cdk/lambda/agentBuilder/validation/schemas.ts @@ -0,0 +1,178 @@ +import { z } from 'zod'; + +// MCP Server Reference Schema (what users specify) +export const MCPServerReferenceSchema = z + .string() + .min(1, 'MCP server name is required') + .max(100, 'MCP server name must be 100 characters or less') + .regex(/^[a-zA-Z0-9._-]+$/, 'MCP server name contains invalid characters'); + +// MCP Server Configuration Schema (for internal use) +export const MCPServerConfigSchema = z + .object({ + name: z + .string() + .min(1, 'MCP server name is required') + .max(100, 'MCP server name must be 100 characters or less'), + command: z.enum(['uvx', 'npx', 'node', 'python', 'python3'], { + errorMap: () => ({ + message: + 'Only uvx, npx, node, python, and python3 commands are allowed for MCP servers', + }), + }), + args: z.array(z.string()).optional().default([]), + env: z.record(z.string()).optional().default({}), + enabled: z.boolean().optional().default(true), + description: z + .string() + .max(500, 'MCP server description must be 500 characters or less') + .optional(), + version: z.string().optional(), + }) + .refine( + (data) => { + // Validate args don't contain dangerous patterns + const dangerousPatterns = [ + '--', + '&&', + '||', + ';', + '|', + '>', + '<', + '`', + '$', + 'rm', + 'sudo', + 'chmod', + ]; + for (const arg of data.args || []) { + if ( + dangerousPatterns.some((pattern) => String(arg).includes(pattern)) + ) { + return false; + } + } + return true; + }, + { + message: 'Dangerous pattern detected in MCP server arguments', + } + ) + .refine( + (data) => { + // Validate environment variables + const allowedEnvVars = [ + 'AWS_REGION', + 'FASTMCP_LOG_LEVEL', + 'MCP_SERVER_NAME', + 'LOG_LEVEL', + 'DEBUG', + 'VERBOSE', + ]; + + for (const key of Object.keys(data.env || {})) { + if (!allowedEnvVars.includes(key) && !key.startsWith('MCP_')) { + return false; + } + } + return true; + }, + { + message: 'Environment variable not allowed', + } + ); + +// Agent Schemas +export const CreateAgentRequestSchema = z.object({ + name: z + .string() + .min(1, 'Agent name is required') + .max(100, 'Agent name must be 100 characters or less'), + description: z + .string() + .max(500, 'Description must be 500 characters or less') + .optional(), + systemPrompt: z + .string() + .min(1, 'System prompt is required') + .max(10000, 'System prompt must be 10,000 characters or less'), + modelId: z.string().min(1, 'Model ID is required'), + mcpServers: z + .array(MCPServerReferenceSchema) + .max(10, 'Maximum 10 MCP servers allowed') + .optional() + .default([]), + codeExecutionEnabled: z.boolean().optional().default(false), + isPublic: z.boolean().optional().default(false), + tags: z + .array(z.string().max(50, 'Each tag must be 50 characters or less')) + .max(10, 'Maximum 10 tags allowed') + .optional() + .default([]), + createdByEmail: z.string().email().optional(), +}); + +export const UpdateAgentRequestSchema = z.object({ + agentId: z.string().uuid('Invalid agent ID format'), + name: z + .string() + .min(1, 'Agent name is required') + .max(100, 'Agent name must be 100 characters or less'), + description: z + .string() + .max(500, 'Description must be 500 characters or less'), + systemPrompt: z + .string() + .min(1, 'System prompt is required') + .max(10000, 'System prompt must be 10,000 characters or less'), + modelId: z.string().min(1, 'Model ID is required'), + mcpServers: z + .array(MCPServerReferenceSchema) + .max(10, 'Maximum 10 MCP servers allowed'), + codeExecutionEnabled: z.boolean().optional().default(false), + isPublic: z.boolean().optional().default(false), + tags: z + .array(z.string().max(50, 'Each tag must be 50 characters or less')) + .max(10, 'Maximum 10 tags allowed') + .optional() + .default([]), + // version removed - using starCount instead + createdByEmail: z.string().email().optional(), +}); + +export const ShareAgentRequestSchema = z.object({ + isPublic: z.boolean({ required_error: 'isPublic must be a boolean value' }), +}); + +export const CloneAgentRequestSchema = z.object({ + sourceAgentId: z.string().uuid('Invalid source agent ID format'), + name: z + .string() + .max(100, 'Agent name must be 100 characters or less') + .optional(), +}); + +// Common validation schemas +export const AgentIdSchema = z.string().uuid('Invalid agent ID format'); +export const UserIdSchema = z.string().min(1, 'User ID is required'); +export const PaginationKeySchema = z.string().optional(); + +// Request body validation helper +export const RequestBodySchema = z.string().min(1, 'Request body is required'); + +// Export types for TypeScript - use common types from generative-ai-use-cases +// These are kept for validation purposes only +export type CreateAgentRequestValidation = z.infer< + typeof CreateAgentRequestSchema +>; +export type UpdateAgentRequestValidation = z.infer< + typeof UpdateAgentRequestSchema +>; +export type ShareAgentRequestValidation = z.infer< + typeof ShareAgentRequestSchema +>; +export type CloneAgentRequestValidation = z.infer< + typeof CloneAgentRequestSchema +>; +export type MCPServerConfigValidation = z.infer; diff --git a/packages/cdk/lambda/utils/bedrockAgentApi.ts b/packages/cdk/lambda/utils/bedrockAgentApi.ts index 7a385aa39..050b4d217 100644 --- a/packages/cdk/lambda/utils/bedrockAgentApi.ts +++ b/packages/cdk/lambda/utils/bedrockAgentApi.ts @@ -31,10 +31,10 @@ const s3Client = new S3Client({}); // Agent information const agentMap: AgentMap = JSON.parse(process.env.AGENT_MAP || '{}'); -type AgentInfo = { +type AgentConfig = { codeInterpreterEnabled: boolean; }; -const agentInfoMap: { [aliasId: string]: AgentInfo } = {}; +const agentConfigMap: { [aliasId: string]: AgentConfig } = {}; // Convert s3:/// to https://s3..amazonaws.com// const convertS3UriToUrl = (s3Uri: string, region: string): string => { @@ -59,9 +59,9 @@ const encodeUrlString = (str: string): string => { } }; -const getAgentInfo = async (agentId: string, agentAliasId: string) => { +const getagentConfig = async (agentId: string, agentAliasId: string) => { // Get Agent Info if not cached - if (!agentInfoMap[agentAliasId]) { + if (!agentConfigMap[agentAliasId]) { const bedrockAgentClient = await initBedrockAgentClient({ region: MODEL_REGION, }); @@ -83,13 +83,13 @@ const getAgentInfo = async (agentId: string, agentAliasId: string) => { }) ); // Cache Agent Info - agentInfoMap[agentAliasId] = { + agentConfigMap[agentAliasId] = { codeInterpreterEnabled: !!actionGroups.actionGroupSummaries?.find( (actionGroup) => actionGroup.actionGroupName === 'CodeInterpreterAction' ), }; } - return agentInfoMap[agentAliasId]; + return agentConfigMap[agentAliasId]; }; const bedrockAgentApi: ApiInterface = { @@ -104,7 +104,7 @@ const bedrockAgentApi: ApiInterface = { } const agentId = agentMap[model.modelId].agentId; const agentAliasId = agentMap[model.modelId].aliasId; - const agentInfo = await getAgentInfo(agentId, agentAliasId); + const agentConfig = await getagentConfig(agentId, agentAliasId); // Invoke Agent const command = new InvokeAgentCommand({ @@ -135,7 +135,7 @@ const bedrockAgentApi: ApiInterface = { data: Buffer.from(file.source.data, 'base64'), }, }, - useCase: agentInfo.codeInterpreterEnabled + useCase: agentConfig.codeInterpreterEnabled ? 'CODE_INTERPRETER' : 'CHAT', })) as InputFile[] | undefined; diff --git a/packages/cdk/lib/construct/agent.ts b/packages/cdk/lib/construct/agent.ts index 86e0024b7..7af1a0c59 100644 --- a/packages/cdk/lib/construct/agent.ts +++ b/packages/cdk/lib/construct/agent.ts @@ -99,6 +99,8 @@ export class Agent extends Construct { new ServicePrincipal('bedrock.amazonaws.com') ); + const searchAgentName = 'SearchEngine'; + const searchAgentDescription = 'Agent with Web Search Functionality'; const searchAgent = new CfnAgent(this, 'SearchAgent', { agentName: `SearchEngineAgent-${suffix}`, actionGroups: [ @@ -123,7 +125,7 @@ export class Agent extends Construct { agentResourceRoleArn: bedrockAgentRole.roleArn, idleSessionTtlInSeconds: 3600, autoPrepare: true, - description: 'Search Agent', + description: searchAgentDescription, foundationModel: 'us.anthropic.claude-3-5-sonnet-20241022-v2:0', instruction: `You are an advanced assistant with the ability to search and retrieve information from the web to perform complex research tasks. Your main function is to solve problems and meet user requests by utilizing these capabilities. @@ -146,13 +148,17 @@ Automatically detect the language of the user's request and think and answer in }); this.agents.push({ - displayName: 'SearchEngine', + displayName: searchAgentName, agentId: searchAgent.attrAgentId, aliasId: searchAgentAlias.attrAgentAliasId, + description: searchAgentDescription, }); } // Code Interpreter Agent + const codeInterpreterAgentName = 'CodeInterpreter'; + const codeInterpreterAgentDescription = + 'Agent with Code Interpreter Functionality'; const codeInterpreterAgent = new CfnAgent(this, 'CodeInterpreterAgent', { agentName: `CodeInterpreterAgent-${suffix}`, actionGroups: [ @@ -214,9 +220,10 @@ Automatically detect the language of the user's request and think and answer in ); this.agents.push({ - displayName: 'CodeInterpreter', + displayName: codeInterpreterAgentName, agentId: codeInterpreterAgent.attrAgentId, aliasId: codeInterpreterAgentAlias.attrAgentAliasId, + description: codeInterpreterAgentDescription, }); } } diff --git a/packages/cdk/lib/construct/api.ts b/packages/cdk/lib/construct/api.ts index 9c88b3645..6aaac95a8 100644 --- a/packages/cdk/lib/construct/api.ts +++ b/packages/cdk/lib/construct/api.ts @@ -26,7 +26,12 @@ import { BucketEncryption, HttpMethods, } from 'aws-cdk-lib/aws-s3'; -import { Agent, AgentMap, ModelConfiguration } from 'generative-ai-use-cases'; +import { + Agent, + AgentInfo, + AgentMap, + ModelConfiguration, +} from 'generative-ai-use-cases'; import { BEDROCK_IMAGE_GEN_MODELS, BEDROCK_VIDEO_GEN_MODELS, @@ -85,7 +90,7 @@ export class Api extends Construct { readonly imageGenerationModelIds: ModelConfiguration[]; readonly videoGenerationModelIds: ModelConfiguration[]; readonly endpointNames: ModelConfiguration[]; - readonly agentNames: string[]; + readonly agents: AgentInfo[]; readonly fileBucket: Bucket; readonly getFileDownloadSignedUrlFunction: IFunction; @@ -1111,7 +1116,10 @@ export class Api extends Construct { this.imageGenerationModelIds = imageGenerationModelIds; this.videoGenerationModelIds = videoGenerationModelIds; this.endpointNames = endpointNames; - this.agentNames = Object.keys(agentMap); + this.agents = agents.map((agent) => ({ + displayName: agent.displayName, + description: agent.description, + })); this.fileBucket = fileBucket; this.getFileDownloadSignedUrlFunction = getFileDownloadSignedUrlFunction; } diff --git a/packages/cdk/lib/construct/generic-agent-core.ts b/packages/cdk/lib/construct/generic-agent-core.ts index c32f798ee..74a109ccc 100644 --- a/packages/cdk/lib/construct/generic-agent-core.ts +++ b/packages/cdk/lib/construct/generic-agent-core.ts @@ -4,11 +4,8 @@ import { PolicyStatement, Role, ServicePrincipal, - ManagedPolicy, } from 'aws-cdk-lib/aws-iam'; -import { CustomResource, Duration, Stack, RemovalPolicy } from 'aws-cdk-lib'; -import { Provider } from 'aws-cdk-lib/custom-resources'; -import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs'; +import { Stack, RemovalPolicy } from 'aws-cdk-lib'; import { Repository } from 'aws-cdk-lib/aws-ecr'; import { DockerImageAsset, Platform } from 'aws-cdk-lib/aws-ecr-assets'; import { @@ -16,9 +13,9 @@ import { BlockPublicAccess, BucketEncryption, } from 'aws-cdk-lib/aws-s3'; +import { CfnRuntime } from 'aws-cdk-lib/aws-bedrockagentcore'; import { BucketInfo } from 'generative-ai-use-cases'; import * as path from 'path'; -import { LAMBDA_RUNTIME_NODEJS } from '../../consts'; export interface AgentCoreRuntimeConfig { name: string; @@ -36,15 +33,13 @@ export interface GenericAgentCoreProps { env: string; } -// UUID for Agent Core Runtime -const AGENT_CORE_RUNTIME_UUID = 'B8F5E892-3A1C-4D2F-9B7E-6C8A5F9D2E1B'; - export class GenericAgentCore extends Construct { private _deployedGenericRuntimeArn?: string; private _ecrRepository?: Repository; private _imageUri?: string; private readonly genericRuntimeConfig: AgentCoreRuntimeConfig; private readonly _fileBucket: Bucket; + private _agentCoreRuntime?: CfnRuntime; constructor(scope: Construct, id: string, props: GenericAgentCoreProps) { super(scope, id); @@ -61,7 +56,7 @@ export class GenericAgentCore extends Construct { // Default configuration for Generic AgentCore Runtime this.genericRuntimeConfig = { - name: `GenericAgentCoreRuntime${env}`, + name: `GenUAgentCoreRuntime${env}`, instructions: 'You are a helpful assistant powered by AWS Bedrock.', memorySize: 2048, dockerPath: 'lambda-python/generic-agent-core-runtime', @@ -79,26 +74,31 @@ export class GenericAgentCore extends Construct { } /** - * Deploy the generic AgentCore Runtime + * Deploy the generic AgentCore Runtime using L1 CDK Construct */ private deployGenericRuntime(): { repository: Repository; imageUri: string } { const dockerImageAsset = this.createDockerImageAsset(); - const { customResourceRole, agentCoreRuntimeRole } = this.createIamRoles(); - const customResourceProvider = - this.createCustomResourceProvider(customResourceRole); - - const customResource = this.createAgentCoreRuntime( - 'GenericAgentCoreRuntime', - this.genericRuntimeConfig, - agentCoreRuntimeRole, - customResourceProvider, - dockerImageAsset.imageUri - ); + const agentCoreRuntimeRole = this.createAgentCoreRuntimeRole(); - // Get the actual runtime ARN and ID from CustomResource response - this._deployedGenericRuntimeArn = customResource.getAttString( - 'AgentCoreRuntimeArn' - ); + // Create AgentCore Runtime using L1 CDK Construct + this._agentCoreRuntime = new CfnRuntime(this, 'GenericAgentCoreRuntimeL1', { + agentRuntimeName: this.genericRuntimeConfig.name, + agentRuntimeArtifact: { + containerConfiguration: { + containerUri: dockerImageAsset.imageUri, + }, + }, + roleArn: agentCoreRuntimeRole.roleArn, + networkConfiguration: { + networkMode: this.genericRuntimeConfig.networkMode || 'PUBLIC', + }, + protocolConfiguration: this.genericRuntimeConfig.serverProtocol || 'HTTP', + environmentVariables: this.genericRuntimeConfig.environmentVariables, + }); + + // Set the deployed runtime ARN + this._deployedGenericRuntimeArn = + this._agentCoreRuntime.attrAgentRuntimeArn; return dockerImageAsset; } @@ -136,62 +136,13 @@ export class GenericAgentCore extends Construct { }; } - /** - * Create IAM roles for AgentCore operations - */ - private createIamRoles(): { - customResourceRole: Role; - agentCoreRuntimeRole: Role; - } { - const customResourceRole = this.createCustomResourceRole(); - const agentCoreRuntimeRole = this.createAgentCoreRuntimeRole(); - - return { customResourceRole, agentCoreRuntimeRole }; - } - - /** - * Create IAM role for Custom Resource operations - */ - private createCustomResourceRole(): Role { - const role = new Role(this, 'AgentCoreCustomResourceRole', { - assumedBy: new ServicePrincipal('lambda.amazonaws.com'), - managedPolicies: [ - ManagedPolicy.fromAwsManagedPolicyName( - 'service-role/AWSLambdaBasicExecutionRole' - ), - ], - }); - - role.addToPolicy( - new PolicyStatement({ - sid: 'BedrockAgentCorePermissions', - effect: Effect.ALLOW, - actions: ['bedrock-agentcore:*'], - resources: ['*'], - }) - ); - - role.addToPolicy( - new PolicyStatement({ - sid: 'IAMPassRolePermissions', - effect: Effect.ALLOW, - actions: ['iam:PassRole'], - resources: ['*'], - conditions: { - StringEquals: { - 'iam:PassedToService': 'bedrock-agentcore.amazonaws.com', - }, - }, - }) - ); - - return role; - } - /** * Create IAM role for AgentCore Runtime execution with comprehensive permissions */ private createAgentCoreRuntimeRole(): Role { + const region = Stack.of(this).region; + const accountId = Stack.of(this).account; + const role = new Role(this, 'AgentCoreRuntimeRole', { assumedBy: new ServicePrincipal('bedrock-agentcore.amazonaws.com', { conditions: { @@ -199,41 +150,35 @@ export class GenericAgentCore extends Construct { 'aws:SourceAccount': Stack.of(this).account, }, ArnLike: { - 'aws:SourceArn': `arn:aws:bedrock-agentcore:${Stack.of(this).region}:${Stack.of(this).account}:*`, + 'aws:SourceArn': `arn:aws:bedrock-agentcore:${region}:${accountId}:*`, }, }, }), - managedPolicies: [ - ManagedPolicy.fromAwsManagedPolicyName( - 'service-role/AWSLambdaBasicExecutionRole' - ), - ], }); - // Bedrock - + // Bedrock Model Invocation role.addToPolicy( new PolicyStatement({ - sid: 'BedrockPermissions', + sid: 'BedrockModelInvocation', effect: Effect.ALLOW, actions: [ 'bedrock:InvokeModel', 'bedrock:InvokeModelWithResponseStream', ], - resources: ['*'], + resources: [ + 'arn:aws:bedrock:*::foundation-model/*', + `arn:aws:bedrock:${region}:${accountId}:*`, + ], }) ); - // ECR - + // ECR Access role.addToPolicy( new PolicyStatement({ sid: 'ECRImageAccess', effect: Effect.ALLOW, actions: ['ecr:BatchGetImage', 'ecr:GetDownloadUrlForLayer'], - resources: [ - `arn:aws:ecr:${Stack.of(this).region}:${Stack.of(this).account}:repository/*`, - ], + resources: [`arn:aws:ecr:${region}:${accountId}:repository/*`], }) ); @@ -246,15 +191,14 @@ export class GenericAgentCore extends Construct { }) ); - // Logging - - const logGroupArn = `arn:aws:logs:${Stack.of(this).region}:${Stack.of(this).account}:log-group:/aws/bedrock-agentcore/runtimes/*`; - + // CloudWatch Logs role.addToPolicy( new PolicyStatement({ effect: Effect.ALLOW, actions: ['logs:DescribeLogStreams', 'logs:CreateLogGroup'], - resources: [logGroupArn], + resources: [ + `arn:aws:logs:${region}:${accountId}:log-group:/aws/bedrock-agentcore/runtimes/*`, + ], }) ); @@ -262,9 +206,7 @@ export class GenericAgentCore extends Construct { new PolicyStatement({ effect: Effect.ALLOW, actions: ['logs:DescribeLogGroups'], - resources: [ - `arn:aws:logs:${Stack.of(this).region}:${Stack.of(this).account}:log-group:*`, - ], + resources: [`arn:aws:logs:${region}:${accountId}:log-group:*`], }) ); @@ -272,11 +214,13 @@ export class GenericAgentCore extends Construct { new PolicyStatement({ effect: Effect.ALLOW, actions: ['logs:CreateLogStream', 'logs:PutLogEvents'], - resources: [`${logGroupArn}:log-stream:*`], + resources: [ + `arn:aws:logs:${region}:${accountId}:log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*`, + ], }) ); - // Monitoring + // X-Ray Tracing role.addToPolicy( new PolicyStatement({ effect: Effect.ALLOW, @@ -290,6 +234,7 @@ export class GenericAgentCore extends Construct { }) ); + // CloudWatch Metrics role.addToPolicy( new PolicyStatement({ effect: Effect.ALLOW, @@ -303,8 +248,7 @@ export class GenericAgentCore extends Construct { }) ); - // Workload - + // Workload Identity role.addToPolicy( new PolicyStatement({ sid: 'GetAgentAccessToken', @@ -315,33 +259,16 @@ export class GenericAgentCore extends Construct { 'bedrock-agentcore:GetWorkloadAccessTokenForUserId', ], resources: [ - `arn:aws:bedrock-agentcore:${Stack.of(this).region}:${Stack.of(this).account}:workload-identity-directory/default`, - `arn:aws:bedrock-agentcore:${Stack.of(this).region}:${Stack.of(this).account}:workload-identity-directory/default/workload-identity/*`, + `arn:aws:bedrock-agentcore:${region}:${accountId}:workload-identity-directory/default`, + `arn:aws:bedrock-agentcore:${region}:${accountId}:workload-identity-directory/default/workload-identity/*`, ], }) ); // S3 File Bucket Access - this._fileBucket.grantReadWrite(role); - - role.addToPolicy( - new PolicyStatement({ - sid: 'S3BucketAccess', - effect: Effect.ALLOW, - actions: [ - 's3:GetObject', - 's3:PutObject', - 's3:ListBucket', - 's3:DeleteObject', - ], - resources: [ - this._fileBucket.bucketArn, - `${this._fileBucket.bucketArn}/*`, - ], - }) - ); + this._fileBucket.grantWrite(role); - // Tools + // CodeInterpreter Tools role.addToPolicy( new PolicyStatement({ sid: 'Tools', @@ -364,100 +291,6 @@ export class GenericAgentCore extends Construct { return role; } - /** - * Get or create a singleton NodejsFunction using unique ID pattern - */ - private getOrCreateSingletonFunction( - uniqueId: string, - functionName: string, - entry: string, - role: Role - ): NodejsFunction { - const stack = Stack.of(this); - const singletonId = `Singleton-${uniqueId}`; - - // Try to find existing function in the stack scope - const existingConstruct = stack.node.tryFindChild(singletonId); - - if (existingConstruct && existingConstruct instanceof NodejsFunction) { - // Reuse existing function - return existingConstruct; - } - - // Create new NodejsFunction - return new NodejsFunction(stack, singletonId, { - functionName: `${functionName}-${Stack.of(this).stackName}-${uniqueId.slice(0, 8)}`, - description: `${functionName} CustomResource Lambda Function (Singleton)`, - runtime: LAMBDA_RUNTIME_NODEJS, - entry, - handler: 'handler', - timeout: Duration.minutes(10), - role, - environment: { - AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1', - }, - bundling: { - minify: false, - target: 'es2020', - nodeModules: ['@aws-sdk/client-bedrock-agentcore-control'], - }, - }); - } - - /** - * Create Custom Resource provider with custom singleton logic - */ - private createCustomResourceProvider(customResourceRole: Role): Provider { - const lambdaFunction = this.getOrCreateSingletonFunction( - AGENT_CORE_RUNTIME_UUID, - 'AgentCoreRuntime', - path.join( - __dirname, - '../../custom-resources/agent-core-runtime/index.ts' - ), - customResourceRole - ); - - return new Provider(this, 'AgentCoreRuntimeProvider', { - onEventHandler: lambdaFunction, - }); - } - - /** - * Create individual AgentCore Runtime using Custom Resource - */ - private createAgentCoreRuntime( - id: string, - config: AgentCoreRuntimeConfig, - agentCoreRuntimeRole: Role, - customResourceProvider: Provider, - imageUri: string - ): CustomResource { - if (!imageUri) { - throw new Error( - `AgentCore Runtime '${config.name}' requires imageUri to be provided` - ); - } - - const customConfig = { ...config.customRuntimeConfig }; - customConfig.containerImageUri = imageUri; - - if (config.environmentVariables) { - customConfig.environmentVariables = config.environmentVariables; - } - - return new CustomResource(this, id, { - serviceToken: customResourceProvider.serviceToken, - properties: { - AgentCoreRuntimeName: config.name, - RoleArn: agentCoreRuntimeRole.roleArn, - NetworkMode: config.networkMode || 'PUBLIC', - ServerProtocol: config.serverProtocol || 'HTTP', - CustomConfig: customConfig, - }, - }); - } - /** * Get ECR repository */ diff --git a/packages/cdk/lib/construct/use-case-builder.ts b/packages/cdk/lib/construct/use-case-builder.ts index 3011d1a95..cd767082f 100644 --- a/packages/cdk/lib/construct/use-case-builder.ts +++ b/packages/cdk/lib/construct/use-case-builder.ts @@ -14,18 +14,20 @@ import { UserPool } from 'aws-cdk-lib/aws-cognito'; import * as ddb from 'aws-cdk-lib/aws-dynamodb'; import { LAMBDA_RUNTIME_NODEJS } from '../../consts'; import { ISecurityGroup, IVpc } from 'aws-cdk-lib/aws-ec2'; +import { Effect, PolicyStatement } from 'aws-cdk-lib/aws-iam'; export interface UseCaseBuilderProps { readonly userPool: UserPool; readonly api: RestApi; readonly vpc?: IVpc; readonly securityGroups?: ISecurityGroup[]; + readonly createGenericAgentCoreRuntime?: boolean; } export class UseCaseBuilder extends Construct { constructor(scope: Construct, id: string, props: UseCaseBuilderProps) { super(scope, id); - const { userPool, api } = props; + const { userPool, api, createGenericAgentCoreRuntime } = props; const useCaseIdIndexName = 'UseCaseIdIndexName'; const useCaseBuilderTable = new ddb.Table(this, 'UseCaseBuilderTable', { @@ -240,5 +242,64 @@ export class UseCaseBuilder extends Construct { new LambdaIntegration(updateRecentlyUsedUseCaseFunction), commonAuthorizerProps ); + + if (createGenericAgentCoreRuntime) { + // Add Agent Builder related APIs + const agentBuilderFunction = new NodejsFunction(this, 'AgentBuilder', { + ...commonProperty, + memorySize: 1024, + entry: './lambda/agentBuilder.ts', + environment: { + ...commonProperty.environment, + MODEL_REGION: process.env.MODEL_REGION || 'us-east-1', + USER_POOL_ID: userPool.userPoolId, + }, + bundling: { + nodeModules: ['@aws-sdk/client-bedrock-runtime'], + }, + }); + useCaseBuilderTable.grantReadWriteData(agentBuilderFunction); + + // Grant Bedrock permissions for agent testing + const bedrockPolicyForAgent = new PolicyStatement({ + effect: Effect.ALLOW, + resources: ['*'], + actions: ['bedrock:*', 'logs:*'], + }); + agentBuilderFunction.role?.addToPrincipalPolicy(bedrockPolicyForAgent); + + // Grant Cognito permissions for getting user information + const cognitoPolicyForAgent = new PolicyStatement({ + effect: Effect.ALLOW, + resources: [userPool.userPoolArn], + actions: ['cognito-idp:AdminGetUser'], + }); + agentBuilderFunction.role?.addToPrincipalPolicy(cognitoPolicyForAgent); + + // Agent Builder API endpoints + const agentsResource = api.root.addResource('agents'); + + // GET: /agents + agentsResource.addMethod( + 'GET', + new LambdaIntegration(agentBuilderFunction), + commonAuthorizerProps + ); + + // POST: /agents + agentsResource.addMethod( + 'POST', + new LambdaIntegration(agentBuilderFunction), + commonAuthorizerProps + ); + + // All agent sub-routes handled by proxy+ integration + const agentResource = agentsResource.addResource('{proxy+}'); + agentResource.addMethod( + 'ANY', + new LambdaIntegration(agentBuilderFunction), + commonAuthorizerProps + ); + } } } diff --git a/packages/cdk/lib/construct/web.ts b/packages/cdk/lib/construct/web.ts index 3b47c60a8..ca1e0f808 100644 --- a/packages/cdk/lib/construct/web.ts +++ b/packages/cdk/lib/construct/web.ts @@ -21,6 +21,7 @@ import { Flow, HiddenUseCases, ModelConfiguration, + AgentInfo, } from 'generative-ai-use-cases'; import { ComputeType } from 'aws-cdk-lib/aws-codebuild'; @@ -46,7 +47,7 @@ export interface WebProps { readonly samlAuthEnabled: boolean; readonly samlCognitoDomainName?: string | null; readonly samlCognitoFederatedIdentityProviderName?: string | null; - readonly agentNames: string[]; + readonly agents: AgentInfo[]; readonly inlineAgents: boolean; readonly cert?: ICertificate; readonly hostName?: string | null; @@ -59,6 +60,7 @@ export interface WebProps { readonly speechToSpeechModelIds: ModelConfiguration[]; readonly mcpEnabled: boolean; readonly mcpEndpoint: string | null; + readonly mcpServersConfig?: string; readonly webBucket?: s3.Bucket; readonly cognitoUserPoolProxyEndpoint?: string; readonly cognitoIdentityPoolProxyEndpoint?: string; @@ -273,7 +275,7 @@ export class Web extends Construct { VITE_APP_SAML_COGNITO_DOMAIN_NAME: props.samlCognitoDomainName ?? '', VITE_APP_SAML_COGNITO_FEDERATED_IDENTITY_PROVIDER_NAME: props.samlCognitoFederatedIdentityProviderName ?? '', - VITE_APP_AGENT_NAMES: JSON.stringify(props.agentNames), + VITE_APP_AGENTS: JSON.stringify(props.agents), VITE_APP_INLINE_AGENTS: props.inlineAgents.toString(), VITE_APP_USE_CASE_BUILDER_ENABLED: props.useCaseBuilderEnabled.toString(), @@ -286,6 +288,7 @@ export class Web extends Construct { ), VITE_APP_MCP_ENABLED: props.mcpEnabled.toString(), VITE_APP_MCP_ENDPOINT: props.mcpEndpoint ?? '', + VITE_APP_MCP_SERVERS_CONFIG: props.mcpServersConfig ?? '', VITE_APP_COGNITO_USER_POOL_PROXY_ENDPOINT: props.cognitoUserPoolProxyEndpoint ?? '', VITE_APP_COGNITO_IDENTITY_POOL_PROXY_ENDPOINT: diff --git a/packages/cdk/lib/create-stacks.ts b/packages/cdk/lib/create-stacks.ts index 483573e13..3c0e01241 100644 --- a/packages/cdk/lib/create-stacks.ts +++ b/packages/cdk/lib/create-stacks.ts @@ -231,6 +231,7 @@ export const createStacks = (app: cdk.App, params: ProcessedStackInput) => { agents: agentStack?.agents, // Agent Core agentCoreStack: agentCoreStack || undefined, + createGenericAgentCoreRuntime: params.createGenericAgentCoreRuntime, // Video Generation videoBucketRegionMap, // Guardrail diff --git a/packages/cdk/lib/generative-ai-use-cases-stack.ts b/packages/cdk/lib/generative-ai-use-cases-stack.ts index 82556355e..b6b0734f8 100644 --- a/packages/cdk/lib/generative-ai-use-cases-stack.ts +++ b/packages/cdk/lib/generative-ai-use-cases-stack.ts @@ -13,6 +13,7 @@ import { McpApi, AgentCore, } from './construct'; +import { loadMCPConfig, extractSafeMCPConfig } from './utils/mcp-config-loader'; import { CfnWebACLAssociation } from 'aws-cdk-lib/aws-wafv2'; import * as cognito from 'aws-cdk-lib/aws-cognito'; import { ICertificate } from 'aws-cdk-lib/aws-certificatemanager'; @@ -37,6 +38,7 @@ export interface GenerativeAiUseCasesStackProps extends StackProps { // Agent readonly agents?: Agent[]; // Agent Core + readonly createGenericAgentCoreRuntime?: boolean; readonly agentCoreStack?: AgentCoreStack; // Video Generation readonly videoBucketRegionMap: Record; @@ -160,6 +162,10 @@ export class GenerativeAiUseCasesStack extends Stack { securityGroups, }); + // Load MCP configuration for Web frontend + const mcpServers = loadMCPConfig(); + const safeMCPConfig = extractSafeMCPConfig(mcpServers); + // MCP let mcpEndpoint: string | null = null; if (params.mcpEnabled) { @@ -219,7 +225,7 @@ export class GenerativeAiUseCasesStack extends Stack { imageGenerationModelIds: api.imageGenerationModelIds, videoGenerationModelIds: api.videoGenerationModelIds, endpointNames: api.endpointNames, - agentNames: api.agentNames, + agents: api.agents, inlineAgents: params.inlineAgents, useCaseBuilderEnabled: params.useCaseBuilderEnabled, speechToSpeechNamespace: speechToSpeech.namespace, @@ -227,6 +233,7 @@ export class GenerativeAiUseCasesStack extends Stack { speechToSpeechModelIds: params.speechToSpeechModelIds, mcpEnabled: params.mcpEnabled, mcpEndpoint, + mcpServersConfig: safeMCPConfig, agentCoreEnabled: params.createGenericAgentCoreRuntime || params.agentCoreExternalRuntimes.length > 0, @@ -234,6 +241,7 @@ export class GenerativeAiUseCasesStack extends Stack { ? { name: genericRuntimeName || 'GenericAgentCoreRuntime', arn: genericRuntimeArn, + description: 'Generic Agent Core Runtime for custom agents', } : undefined, agentCoreExternalRuntimes: params.agentCoreExternalRuntimes, @@ -325,6 +333,7 @@ export class GenerativeAiUseCasesStack extends Stack { api: api.api, vpc: props.vpc, securityGroups, + createGenericAgentCoreRuntime: props.createGenericAgentCoreRuntime, }); } @@ -424,8 +433,8 @@ export class GenerativeAiUseCasesStack extends Stack { value: params.samlCognitoFederatedIdentityProviderName ?? '', }); - new CfnOutput(this, 'AgentNames', { - value: Buffer.from(JSON.stringify(api.agentNames)).toString('base64'), + new CfnOutput(this, 'Agents', { + value: Buffer.from(JSON.stringify(api.agents)).toString('base64'), }); new CfnOutput(this, 'InlineAgents', { @@ -480,6 +489,10 @@ export class GenerativeAiUseCasesStack extends Stack { value: JSON.stringify(params.agentCoreExternalRuntimes), }); + new CfnOutput(this, 'McpServersConfig', { + value: safeMCPConfig, + }); + this.userPool = auth.userPool; this.userPoolClient = auth.client; diff --git a/packages/cdk/lib/stack-input.ts b/packages/cdk/lib/stack-input.ts index e47ccd7fd..cb9089eff 100644 --- a/packages/cdk/lib/stack-input.ts +++ b/packages/cdk/lib/stack-input.ts @@ -142,6 +142,7 @@ const baseStackInputSchema = z.object({ displayName: z.string(), agentId: z.string(), aliasId: z.string(), + description: z.string().default(''), }) ) .default([]), @@ -154,6 +155,7 @@ const baseStackInputSchema = z.object({ z.object({ name: z.string(), arn: z.string(), + description: z.string().default(''), }) ) .default([]), diff --git a/packages/cdk/lib/utils/mcp-config-loader.ts b/packages/cdk/lib/utils/mcp-config-loader.ts new file mode 100644 index 000000000..9ed0b614c --- /dev/null +++ b/packages/cdk/lib/utils/mcp-config-loader.ts @@ -0,0 +1,64 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +export interface MCPServerMetadata { + category?: string; + description?: string; +} + +export interface MCPServerConfig { + command?: string; + args?: string[]; + env?: Record; + url?: string; + metadata?: MCPServerMetadata; +} + +export interface MCPConfig { + mcpServers: Record; +} + +/** + * Load MCP configuration from mcp.json file + * Returns only the server names and metadata for frontend use + */ +export function loadMCPConfig(): Record { + try { + const mcpJsonPath = path.join( + __dirname, + '../../lambda-python/generic-agent-core-runtime/mcp.json' + ); + + if (!fs.existsSync(mcpJsonPath)) { + console.warn('mcp.json not found, using empty configuration'); + return {}; + } + + const mcpConfig: MCPConfig = JSON.parse( + fs.readFileSync(mcpJsonPath, 'utf8') + ); + return mcpConfig.mcpServers || {}; + } catch (error) { + console.error('Error loading MCP configuration:', error); + return {}; + } +} + +/** + * Extract safe MCP server information for frontend + * Excludes sensitive information like commands, args, and env variables + */ +export function extractSafeMCPConfig( + mcpServers: Record +): string { + const safeConfig: Record = {}; + + Object.keys(mcpServers).forEach((serverName) => { + const serverConfig = mcpServers[serverName]; + safeConfig[serverName] = { + metadata: serverConfig.metadata, + }; + }); + + return JSON.stringify(safeConfig); +} diff --git a/packages/cdk/package.json b/packages/cdk/package.json index 5dee1fb18..85619b50a 100644 --- a/packages/cdk/package.json +++ b/packages/cdk/package.json @@ -9,7 +9,7 @@ "cdk": "cdk", "lint": "eslint . --ext ts --report-unused-disable-directives --max-warnings 0", "lambda-build-dryrun": "tsc --noEmit --skipLibCheck", - "postinstall": "npm ci --prefix custom-resources/agent-core-runtime && npm ci --prefix custom-resources/opensearch-index && npm ci --prefix custom-resources/apply-tags && npm ci --prefix fargate-s3-server" + "postinstall": "npm ci --prefix custom-resources/opensearch-index && npm ci --prefix custom-resources/apply-tags && npm ci --prefix fargate-s3-server" }, "devDependencies": { "@types/aws-lambda": "^8.10.137", @@ -18,7 +18,7 @@ "@types/sanitize-html": "^2.13.0", "@typescript-eslint/eslint-plugin": "^7.6.0", "@typescript-eslint/parser": "^7.6.0", - "aws-cdk": "^2.154.1", + "aws-cdk": "^2.217.0", "eslint": "^8.56.0", "jest": "^29.7.0", "ts-jest": "^29.2.5", @@ -26,12 +26,12 @@ "typescript": "~5.4.5" }, "dependencies": { - "@aws-cdk/aws-lambda-python-alpha": "^2.154.1-alpha.0", + "@aws-cdk/aws-lambda-python-alpha": "^2.217.0-alpha.0", "@aws-sdk/client-bedrock-agent": "^3.755.0", "@aws-sdk/client-bedrock-agent-runtime": "^3.755.0", "@aws-sdk/client-bedrock-agentcore": "^3.755.0", - "@aws-sdk/client-bedrock-agentcore-control": "^3.755.0", "@aws-sdk/client-bedrock-runtime": "^3.755.0", + "@aws-sdk/client-cognito-identity-provider": "^3.755.0", "@aws-sdk/client-dynamodb": "^3.755.0", "@aws-sdk/client-kendra": "^3.755.0", "@aws-sdk/client-lambda": "^3.755.0", @@ -45,7 +45,7 @@ "@aws-solutions-constructs/aws-cloudfront-s3": "^2.68.0", "@smithy/node-http-handler": "^4.0.4", "aws-amplify": "^6.14.2", - "aws-cdk-lib": "^2.154.1", + "aws-cdk-lib": "^2.217.0", "aws-jwt-verify": "^4.0.0", "constructs": "^10.3.0", "deploy-time-build": "^0.3.17", @@ -53,6 +53,7 @@ "sanitize-html": "^2.13.0", "source-map-support": "^0.5.21", "upsert-slr": "^1.0.4", + "uuid": "13.0.0", "ws": "^8.18.0", "zod": "^3.24.1" } diff --git a/packages/cdk/test/__snapshots__/generative-ai-use-cases.test.ts.snap b/packages/cdk/test/__snapshots__/generative-ai-use-cases.test.ts.snap index 50a28d781..d202e088a 100644 --- a/packages/cdk/test/__snapshots__/generative-ai-use-cases.test.ts.snap +++ b/packages/cdk/test/__snapshots__/generative-ai-use-cases.test.ts.snap @@ -2753,7 +2753,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 2`] = ` "Arn", ], }, - "Runtime": "python3.11", + "Runtime": "python3.13", "Timeout": 900, }, "Type": "AWS::Lambda::Function", @@ -3286,6 +3286,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 2`] = ` "SourceObjectKeys": [ "HASH-REPLACED.zip", ], + "WaitForDistributionInvalidation": true, }, "Type": "Custom::CDKBucketDeployment", "UpdateReplacePolicy": "Delete", @@ -3649,6 +3650,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 3`] = ` "SourceObjectKeys": [ "HASH-REPLACED.zip", ], + "WaitForDistributionInvalidation": true, }, "Type": "Custom::CDKBucketDeployment", "UpdateReplacePolicy": "Delete", @@ -4102,7 +4104,7 @@ Automatically detect the language of the user's request and think and answer in ], }, "AutoPrepare": true, - "Description": "Search Agent", + "Description": "Agent with Web Search Functionality", "FoundationModel": "us.anthropic.claude-3-5-sonnet-20241022-v2:0", "IdleSessionTTLInSeconds": 3600, "Instruction": "You are an advanced assistant with the ability to search and retrieve information from the web to perform complex research tasks. @@ -4160,7 +4162,7 @@ Automatically detect the language of the user's request and think and answer in "Arn", ], }, - "Runtime": "python3.11", + "Runtime": "python3.13", "Timeout": 900, }, "Type": "AWS::Lambda::Function", @@ -4373,14 +4375,14 @@ Automatically detect the language of the user's request and think and answer in exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 4`] = ` { "Outputs": { - "ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7AgentCoreRuntimeArn010E372F": { + "ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803AgentRuntimeArn53FA08A2": { "Export": { - "Name": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7AgentCoreRuntimeArn010E372F", + "Name": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803AgentRuntimeArn53FA08A2", }, "Value": { "Fn::GetAtt": [ - "GenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7", - "AgentCoreRuntimeArn", + "GenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803", + "AgentRuntimeArn", ], }, }, @@ -4398,8 +4400,8 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 4`] = ` }, "Value": { "Fn::GetAtt": [ - "GenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7", - "AgentCoreRuntimeArn", + "GenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803", + "AgentRuntimeArn", ], }, }, @@ -4407,7 +4409,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 4`] = ` "Export": { "Name": "AgentCoreStack-GenericAgentCoreRuntimeName", }, - "Value": "GenericAgentCoreRuntime", + "Value": "GenUAgentCoreRuntime", }, }, "Parameters": { @@ -4474,70 +4476,6 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 4`] = ` }, "Type": "AWS::IAM::Role", }, - "GenericAgentCoreAgentCoreCustomResourceRoleBDED8F6B": { - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - ], - ], - }, - ], - }, - "Type": "AWS::IAM::Role", - }, - "GenericAgentCoreAgentCoreCustomResourceRoleDefaultPolicy673FD2FE": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "bedrock-agentcore:*", - "Effect": "Allow", - "Resource": "*", - "Sid": "BedrockAgentCorePermissions", - }, - { - "Action": "iam:PassRole", - "Condition": { - "StringEquals": { - "iam:PassedToService": "bedrock-agentcore.amazonaws.com", - }, - }, - "Effect": "Allow", - "Resource": "*", - "Sid": "IAMPassRolePermissions", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GenericAgentCoreAgentCoreCustomResourceRoleDefaultPolicy673FD2FE", - "Roles": [ - { - "Ref": "GenericAgentCoreAgentCoreCustomResourceRoleBDED8F6B", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, "GenericAgentCoreAgentCoreFileBucket0430DA42": { "DeletionPolicy": "Delete", "Properties": { @@ -4637,126 +4575,6 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 4`] = ` }, "Type": "AWS::S3::BucketPolicy", }, - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventC9CCB51A": { - "DependsOn": [ - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRoleDefaultPolicyBB9E52E2", - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRole032FFAFA", - ], - "Properties": { - "Code": { - "S3Bucket": "cdk-hnb659fds-assets-123456890123-us-east-1", - "S3Key": "HASH-REPLACED.zip", - }, - "Description": "AWS CDK resource provider framework - onEvent (AgentCoreStack/GenericAgentCore/AgentCoreRuntimeProvider)", - "Environment": { - "Variables": { - "USER_ON_EVENT_FUNCTION_ARN": { - "Fn::GetAtt": [ - "SingletonB8F5E8923A1C4D2F9B7E6C8A5F9D2E1B1B378805", - "Arn", - ], - }, - }, - }, - "Handler": "framework.onEvent", - "LoggingConfig": { - "ApplicationLogLevel": "FATAL", - "LogFormat": "JSON", - }, - "Role": { - "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRole032FFAFA", - "Arn", - ], - }, - "Runtime": "nodejs22.x", - "Timeout": 900, - }, - "Type": "AWS::Lambda::Function", - }, - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRole032FFAFA": { - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - ], - ], - }, - ], - }, - "Type": "AWS::IAM::Role", - }, - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRoleDefaultPolicyBB9E52E2": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "SingletonB8F5E8923A1C4D2F9B7E6C8A5F9D2E1B1B378805", - "Arn", - ], - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "SingletonB8F5E8923A1C4D2F9B7E6C8A5F9D2E1B1B378805", - "Arn", - ], - }, - ":*", - ], - ], - }, - ], - }, - { - "Action": "lambda:GetFunction", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "SingletonB8F5E8923A1C4D2F9B7E6C8A5F9D2E1B1B378805", - "Arn", - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRoleDefaultPolicyBB9E52E2", - "Roles": [ - { - "Ref": "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRole032FFAFA", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, "GenericAgentCoreAgentCoreRuntimeRepository6901D0DC": { "DeletionPolicy": "Delete", "Properties": { @@ -4778,8 +4596,11 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 4`] = ` "bedrock:InvokeModelWithResponseStream", ], "Effect": "Allow", - "Resource": "*", - "Sid": "BedrockPermissions", + "Resource": [ + "arn:aws:bedrock:*::foundation-model/*", + "arn:aws:bedrock:us-east-1:123456890123:*", + ], + "Sid": "BedrockModelInvocation", }, { "Action": [ @@ -4852,9 +4673,6 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 4`] = ` }, { "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*", "s3:DeleteObject*", "s3:PutObject", "s3:PutObjectLegalHold", @@ -4887,38 +4705,6 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 4`] = ` }, ], }, - { - "Action": [ - "s3:GetObject", - "s3:PutObject", - "s3:ListBucket", - "s3:DeleteObject", - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreFileBucket0430DA42", - "Arn", - ], - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreFileBucket0430DA42", - "Arn", - ], - }, - "/*", - ], - ], - }, - ], - "Sid": "S3BucketAccess", - }, { "Action": [ "bedrock-agentcore:CreateCodeInterpreter", @@ -4969,83 +4755,36 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 4`] = ` ], "Version": "2012-10-17", }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - ], - ], - }, - ], }, "Type": "AWS::IAM::Role", }, - "GenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7": { - "DeletionPolicy": "Delete", + "GenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803": { "Properties": { - "AgentCoreRuntimeName": "GenericAgentCoreRuntime", - "CustomConfig": { - "containerImageUri": { - "Fn::Sub": "123456890123.dkr.ecr.us-east-1.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-123456890123-us-east-1:736d91ac33c9bb64c93f49d1258dbf8aff8d6ec20441291f20f42076efb65f00", - }, - "environmentVariables": { - "FILE_BUCKET": { - "Ref": "GenericAgentCoreAgentCoreFileBucket0430DA42", + "AgentRuntimeArtifact": { + "ContainerConfiguration": { + "ContainerUri": { + "Fn::Sub": "123456890123.dkr.ecr.us-east-1.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-123456890123-us-east-1:eacaf716c76a59b8488fd6fb1f733b73392992af31a340e37d0bb3818021b832", }, }, }, - "NetworkMode": "PUBLIC", - "RoleArn": { - "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreRuntimeRoleF34B80EA", - "Arn", - ], - }, - "ServerProtocol": "HTTP", - "ServiceToken": { - "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventC9CCB51A", - "Arn", - ], - }, - }, - "Type": "AWS::CloudFormation::CustomResource", - "UpdateReplacePolicy": "Delete", - }, - "SingletonB8F5E8923A1C4D2F9B7E6C8A5F9D2E1B1B378805": { - "DependsOn": [ - "GenericAgentCoreAgentCoreCustomResourceRoleDefaultPolicy673FD2FE", - "GenericAgentCoreAgentCoreCustomResourceRoleBDED8F6B", - ], - "Properties": { - "Code": { - "S3Bucket": "cdk-hnb659fds-assets-123456890123-us-east-1", - "S3Key": "HASH-REPLACED.zip", - }, - "Description": "AgentCoreRuntime CustomResource Lambda Function (Singleton)", - "Environment": { - "Variables": { - "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "AgentRuntimeName": "GenUAgentCoreRuntime", + "EnvironmentVariables": { + "FILE_BUCKET": { + "Ref": "GenericAgentCoreAgentCoreFileBucket0430DA42", }, }, - "FunctionName": "AgentCoreRuntime-AgentCoreStack-B8F5E892", - "Handler": "index.handler", - "Role": { + "NetworkConfiguration": { + "NetworkMode": "PUBLIC", + }, + "ProtocolConfiguration": "HTTP", + "RoleArn": { "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreCustomResourceRoleBDED8F6B", + "GenericAgentCoreAgentCoreRuntimeRoleF34B80EA", "Arn", ], }, - "Runtime": "nodejs22.x", - "Timeout": 600, }, - "Type": "AWS::Lambda::Function", + "Type": "AWS::BedrockAgentCore::Runtime", }, }, "Rules": { @@ -5249,9 +4988,9 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Fn::Join": [ "", [ - "{"name":"GenericAgentCoreRuntime","arn":"", + "{"name":"GenUAgentCoreRuntime","arn":"", { - "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7AgentCoreRuntimeArn010E372F", + "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803AgentRuntimeArn53FA08A2", }, ""}", ], @@ -5261,8 +5000,8 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "AgentEnabled": { "Value": "true", }, - "AgentNames": { - "Value": "WyJTZWFyY2hFbmdpbmUiLCJDb2RlSW50ZXJwcmV0ZXIiXQ==", + "Agents": { + "Value": "W3siZGlzcGxheU5hbWUiOiJTZWFyY2hFbmdpbmUiLCJkZXNjcmlwdGlvbiI6IkFnZW50IHdpdGggV2ViIFNlYXJjaCBGdW5jdGlvbmFsaXR5In0seyJkaXNwbGF5TmFtZSI6IkNvZGVJbnRlcnByZXRlciIsImRlc2NyaXB0aW9uIjoiQWdlbnQgd2l0aCBDb2RlIEludGVycHJldGVyIEZ1bmN0aW9uYWxpdHkifV0=", }, "ApiEndpoint": { "Value": { @@ -5347,6 +5086,9 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "McpEndpoint": { "Value": "", }, + "McpServersConfig": { + "Value": "{"time":{"metadata":{"category":"Utility","description":"Provides current time and date functionality"}},"aws-knowledge-mcp-server":{"metadata":{"category":"AWS","description":"AWS Knowledge Base MCP server for enterprise knowledge access"}},"awslabs.aws-documentation-mcp-server":{"metadata":{"category":"AWS","description":"Access AWS documentation and guides"}},"awslabs.cdk-mcp-server":{"metadata":{"category":"AWS","description":"AWS CDK code generation and assistance"}},"awslabs.aws-diagram-mcp-server":{"metadata":{"category":"AWS","description":"Generate AWS architecture diagrams"}},"awslabs.nova-canvas-mcp-server":{"metadata":{"category":"AI/ML","description":"Amazon Nova Canvas image generation"}},"tavily-search":{"metadata":{"category":"Search","description":"Web search and research capabilities powered by Tavily"}}}", + }, "ModelIds": { "Value": { "Fn::Join": [ @@ -5551,11 +5293,18 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::IAM::Role", "UpdateReplacePolicy": "Delete", }, - "APIApiDeployment3A5021231e35051e75cb37230e3365d2f55dbe60": { + "APIApiDeployment3A502123b4c182070f01d378b2e5ccab86f6b1c4": { "DeletionPolicy": "Delete", "DependsOn": [ "APIApiApi4XXDCF913C8", "APIApiApi5XX11B67643", + "APIApiagentsproxyANY44A4A08E", + "APIApiagentsproxyOPTIONS65C845F9", + "APIApiagentsproxy440913A2", + "APIApiagentsGETFE9F47E4", + "APIApiagentsOPTIONS064D2F41", + "APIApiagentsPOST28B48D5F", + "APIApiagents70FB378D", "APIApichatschatIdDELETE4578D41B", "APIApichatschatIdfeedbacksOPTIONS7AB34AA5", "APIApichatschatIdfeedbacksPOST3E9ACBEC", @@ -5707,7 +5456,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ], "Properties": { "DeploymentId": { - "Ref": "APIApiDeployment3A5021231e35051e75cb37230e3365d2f55dbe60", + "Ref": "APIApiDeployment3A502123b4c182070f01d378b2e5ccab86f6b1c4", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -5800,7 +5549,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatsE061702A": { + "APIApiagents70FB378D": { "DeletionPolicy": "Delete", "Properties": { "ParentId": { @@ -5809,7 +5558,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "RootResourceId", ], }, - "PathPart": "chats", + "PathPart": "agents", "RestApiId": { "Ref": "APIApiFFA96F67", }, @@ -5817,54 +5566,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Resource", "UpdateReplacePolicy": "Delete", }, - "APIApichatsGET40767623": { - "DeletionPolicy": "Delete", - "Properties": { - "AuthorizationType": "COGNITO_USER_POOLS", - "AuthorizerId": { - "Ref": "APIAuthorizer9DCC037B", - }, - "HttpMethod": "GET", - "Integration": { - "IntegrationHttpMethod": "POST", - "Type": "AWS_PROXY", - "Uri": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", - { - "Fn::GetAtt": [ - "APIListChats12807275", - "Arn", - ], - }, - "/invocations", - ], - ], - }, - }, - "ResourceId": { - "Ref": "APIApichatsE061702A", - }, - "RestApiId": { - "Ref": "APIApiFFA96F67", - }, - }, - "Type": "AWS::ApiGateway::Method", - "UpdateReplacePolicy": "Delete", - }, - "APIApichatsGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETchats3464EF3A": { + "APIApiagentsGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETagents5FFFAEBF": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIListChats12807275", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -5885,7 +5593,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/GET/chats", + "/GET/agents", ], ], }, @@ -5893,13 +5601,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatsGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETchatsE1DE3C5A": { + "APIApiagentsGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETagents2809AEEE": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIListChats12807275", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -5916,7 +5624,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/GET/chats", + "/test-invoke-stage/GET/agents", ], ], }, @@ -5924,7 +5632,48 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatsOPTIONSDFF708CB": { + "APIApiagentsGETFE9F47E4": { + "DeletionPolicy": "Delete", + "Properties": { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": { + "Ref": "UseCaseBuilderAuthorizer8C07733E", + }, + "HttpMethod": "GET", + "Integration": { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", + { + "Fn::GetAtt": [ + "UseCaseBuilderAgentBuilderDAB96216", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": { + "Ref": "APIApiagents70FB378D", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApiagentsOPTIONS064D2F41": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -5957,7 +5706,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, ], "ResourceId": { - "Ref": "APIApichatsE061702A", + "Ref": "APIApiagents70FB378D", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -5966,13 +5715,54 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatsPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTchats6FB5CEC9": { + "APIApiagentsPOST28B48D5F": { + "DeletionPolicy": "Delete", + "Properties": { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": { + "Ref": "UseCaseBuilderAuthorizer8C07733E", + }, + "HttpMethod": "POST", + "Integration": { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", + { + "Fn::GetAtt": [ + "UseCaseBuilderAgentBuilderDAB96216", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": { + "Ref": "APIApiagents70FB378D", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApiagentsPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTagentsBB862BB1": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APICreateChatE07AFAF4", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -5993,7 +5783,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/POST/chats", + "/POST/agents", ], ], }, @@ -6001,13 +5791,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatsPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTchatsE0E202B2": { + "APIApiagentsPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTagents9F230B2C": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APICreateChatE07AFAF4", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -6024,7 +5814,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/POST/chats", + "/test-invoke-stage/POST/agents", ], ], }, @@ -6032,55 +5822,28 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatsPOSTF32299AA": { + "APIApiagentsproxy440913A2": { "DeletionPolicy": "Delete", "Properties": { - "AuthorizationType": "COGNITO_USER_POOLS", - "AuthorizerId": { - "Ref": "APIAuthorizer9DCC037B", - }, - "HttpMethod": "POST", - "Integration": { - "IntegrationHttpMethod": "POST", - "Type": "AWS_PROXY", - "Uri": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", - { - "Fn::GetAtt": [ - "APICreateChatE07AFAF4", - "Arn", - ], - }, - "/invocations", - ], - ], - }, - }, - "ResourceId": { - "Ref": "APIApichatsE061702A", + "ParentId": { + "Ref": "APIApiagents70FB378D", }, + "PathPart": "{proxy+}", "RestApiId": { "Ref": "APIApiFFA96F67", }, }, - "Type": "AWS::ApiGateway::Method", + "Type": "AWS::ApiGateway::Resource", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdDELETE4578D41B": { + "APIApiagentsproxyANY44A4A08E": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", "AuthorizerId": { - "Ref": "APIAuthorizer9DCC037B", + "Ref": "UseCaseBuilderAuthorizer8C07733E", }, - "HttpMethod": "DELETE", + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -6095,7 +5858,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIDeleteChat1517278C", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -6105,7 +5868,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApichatschatIdE67019A6", + "Ref": "APIApiagentsproxy440913A2", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -6114,13 +5877,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdDELETEApiPermissionGenerativeAiUseCasesStackAPIApi89219E17DELETEchatschatIdCBAD7732": { + "APIApiagentsproxyANYApiPermissionGenerativeAiUseCasesStackAPIApi89219E17ANYagentsproxyB1492E94": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIDeleteChat1517278C", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -6141,7 +5904,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/DELETE/chats/*", + "/*/agents/*", ], ], }, @@ -6149,13 +5912,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdDELETEApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17DELETEchatschatId6DBAD3C3": { + "APIApiagentsproxyANYApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17ANYagentsproxy619296F3": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIDeleteChat1517278C", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -6172,7 +5935,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/DELETE/chats/*", + "/test-invoke-stage/*/agents/*", ], ], }, @@ -6180,13 +5943,58 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdE67019A6": { + "APIApiagentsproxyOPTIONS65C845F9": { + "DeletionPolicy": "Delete", + "Properties": { + "ApiKeyRequired": false, + "AuthorizationType": "NONE", + "HttpMethod": "OPTIONS", + "Integration": { + "IntegrationResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", + "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'", + "method.response.header.Access-Control-Allow-Origin": "'*'", + }, + "StatusCode": "204", + }, + ], + "RequestTemplates": { + "application/json": "{ statusCode: 200 }", + }, + "Type": "MOCK", + }, + "MethodResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": true, + "method.response.header.Access-Control-Allow-Methods": true, + "method.response.header.Access-Control-Allow-Origin": true, + }, + "StatusCode": "204", + }, + ], + "ResourceId": { + "Ref": "APIApiagentsproxy440913A2", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatsE061702A": { "DeletionPolicy": "Delete", "Properties": { "ParentId": { - "Ref": "APIApichatsE061702A", + "Fn::GetAtt": [ + "APIApiFFA96F67", + "RootResourceId", + ], }, - "PathPart": "{chatId}", + "PathPart": "chats", "RestApiId": { "Ref": "APIApiFFA96F67", }, @@ -6194,7 +6002,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Resource", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdGET152C9123": { + "APIApichatsGET40767623": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", @@ -6216,7 +6024,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIFindChatbyId74476825", + "APIListChats12807275", "Arn", ], }, @@ -6226,7 +6034,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApichatschatIdE67019A6", + "Ref": "APIApichatsE061702A", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -6235,13 +6043,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdC82A138E": { + "APIApichatsGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETchats3464EF3A": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIFindChatbyId74476825", + "APIListChats12807275", "Arn", ], }, @@ -6262,7 +6070,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/GET/chats/*", + "/GET/chats", ], ], }, @@ -6270,13 +6078,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdCA130D83": { + "APIApichatsGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETchatsE1DE3C5A": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIFindChatbyId74476825", + "APIListChats12807275", "Arn", ], }, @@ -6293,7 +6101,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/GET/chats/*", + "/test-invoke-stage/GET/chats", ], ], }, @@ -6301,7 +6109,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdOPTIONS4498230E": { + "APIApichatsOPTIONSDFF708CB": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -6334,7 +6142,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, ], "ResourceId": { - "Ref": "APIApichatschatIdE67019A6", + "Ref": "APIApichatsE061702A", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -6343,54 +6151,105 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdfeedbacksF371F57A": { + "APIApichatsPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTchats6FB5CEC9": { "DeletionPolicy": "Delete", "Properties": { - "ParentId": { - "Ref": "APIApichatschatIdE67019A6", + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APICreateChatE07AFAF4", + "Arn", + ], }, - "PathPart": "feedbacks", - "RestApiId": { - "Ref": "APIApiFFA96F67", + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/", + { + "Ref": "APIApiDeploymentStageapiCD55D117", + }, + "/POST/chats", + ], + ], }, }, - "Type": "AWS::ApiGateway::Resource", + "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdfeedbacksOPTIONS7AB34AA5": { + "APIApichatsPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTchatsE0E202B2": { "DeletionPolicy": "Delete", "Properties": { - "ApiKeyRequired": false, - "AuthorizationType": "NONE", - "HttpMethod": "OPTIONS", - "Integration": { - "IntegrationResponses": [ - { - "ResponseParameters": { - "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", - "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'", - "method.response.header.Access-Control-Allow-Origin": "'*'", + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APICreateChatE07AFAF4", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", }, - "StatusCode": "204", - }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/test-invoke-stage/POST/chats", + ], ], - "RequestTemplates": { - "application/json": "{ statusCode: 200 }", - }, - "Type": "MOCK", }, - "MethodResponses": [ - { - "ResponseParameters": { - "method.response.header.Access-Control-Allow-Headers": true, - "method.response.header.Access-Control-Allow-Methods": true, - "method.response.header.Access-Control-Allow-Origin": true, - }, - "StatusCode": "204", + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatsPOSTF32299AA": { + "DeletionPolicy": "Delete", + "Properties": { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": { + "Ref": "APIAuthorizer9DCC037B", + }, + "HttpMethod": "POST", + "Integration": { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", + { + "Fn::GetAtt": [ + "APICreateChatE07AFAF4", + "Arn", + ], + }, + "/invocations", + ], + ], }, - ], + }, "ResourceId": { - "Ref": "APIApichatschatIdfeedbacksF371F57A", + "Ref": "APIApichatsE061702A", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -6399,14 +6258,14 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdfeedbacksPOST3E9ACBEC": { + "APIApichatschatIdDELETE4578D41B": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", "AuthorizerId": { "Ref": "APIAuthorizer9DCC037B", }, - "HttpMethod": "POST", + "HttpMethod": "DELETE", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -6421,7 +6280,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIUpdateFeedback2F9276A1", + "APIDeleteChat1517278C", "Arn", ], }, @@ -6431,7 +6290,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApichatschatIdfeedbacksF371F57A", + "Ref": "APIApichatschatIdE67019A6", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -6440,13 +6299,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdfeedbacksPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTchatschatIdfeedbacksE8588286": { + "APIApichatschatIdDELETEApiPermissionGenerativeAiUseCasesStackAPIApi89219E17DELETEchatschatIdCBAD7732": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIUpdateFeedback2F9276A1", + "APIDeleteChat1517278C", "Arn", ], }, @@ -6467,7 +6326,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/POST/chats/*/feedbacks", + "/DELETE/chats/*", ], ], }, @@ -6475,13 +6334,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdfeedbacksPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTchatschatIdfeedbacks52610594": { + "APIApichatschatIdDELETEApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17DELETEchatschatId6DBAD3C3": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIUpdateFeedback2F9276A1", + "APIDeleteChat1517278C", "Arn", ], }, @@ -6498,7 +6357,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/POST/chats/*/feedbacks", + "/test-invoke-stage/DELETE/chats/*", ], ], }, @@ -6506,13 +6365,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdmessagesAF527CE8": { + "APIApichatschatIdE67019A6": { "DeletionPolicy": "Delete", "Properties": { "ParentId": { - "Ref": "APIApichatschatIdE67019A6", + "Ref": "APIApichatsE061702A", }, - "PathPart": "messages", + "PathPart": "{chatId}", "RestApiId": { "Ref": "APIApiFFA96F67", }, @@ -6520,7 +6379,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Resource", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdmessagesGET94AB097F": { + "APIApichatschatIdGET152C9123": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", @@ -6542,7 +6401,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIListMessages536ED2CC", + "APIFindChatbyId74476825", "Arn", ], }, @@ -6552,7 +6411,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApichatschatIdmessagesAF527CE8", + "Ref": "APIApichatschatIdE67019A6", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -6561,13 +6420,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdmessagesGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdmessages122A59FC": { + "APIApichatschatIdGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdC82A138E": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIListMessages536ED2CC", + "APIFindChatbyId74476825", "Arn", ], }, @@ -6588,7 +6447,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/GET/chats/*/messages", + "/GET/chats/*", ], ], }, @@ -6596,13 +6455,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdmessagesGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdmessages3F025E8E": { + "APIApichatschatIdGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdCA130D83": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIListMessages536ED2CC", + "APIFindChatbyId74476825", "Arn", ], }, @@ -6619,7 +6478,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/GET/chats/*/messages", + "/test-invoke-stage/GET/chats/*", ], ], }, @@ -6627,7 +6486,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdmessagesOPTIONS20207E07": { + "APIApichatschatIdOPTIONS4498230E": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -6660,7 +6519,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, ], "ResourceId": { - "Ref": "APIApichatschatIdmessagesAF527CE8", + "Ref": "APIApichatschatIdE67019A6", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -6669,7 +6528,63 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdmessagesPOST4197DA8F": { + "APIApichatschatIdfeedbacksF371F57A": { + "DeletionPolicy": "Delete", + "Properties": { + "ParentId": { + "Ref": "APIApichatschatIdE67019A6", + }, + "PathPart": "feedbacks", + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Resource", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatschatIdfeedbacksOPTIONS7AB34AA5": { + "DeletionPolicy": "Delete", + "Properties": { + "ApiKeyRequired": false, + "AuthorizationType": "NONE", + "HttpMethod": "OPTIONS", + "Integration": { + "IntegrationResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", + "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'", + "method.response.header.Access-Control-Allow-Origin": "'*'", + }, + "StatusCode": "204", + }, + ], + "RequestTemplates": { + "application/json": "{ statusCode: 200 }", + }, + "Type": "MOCK", + }, + "MethodResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": true, + "method.response.header.Access-Control-Allow-Methods": true, + "method.response.header.Access-Control-Allow-Origin": true, + }, + "StatusCode": "204", + }, + ], + "ResourceId": { + "Ref": "APIApichatschatIdfeedbacksF371F57A", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatschatIdfeedbacksPOST3E9ACBEC": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", @@ -6691,7 +6606,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APICreateMessages1C3421C0", + "APIUpdateFeedback2F9276A1", "Arn", ], }, @@ -6701,7 +6616,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApichatschatIdmessagesAF527CE8", + "Ref": "APIApichatschatIdfeedbacksF371F57A", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -6710,13 +6625,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdmessagesPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTchatschatIdmessages832E69DC": { + "APIApichatschatIdfeedbacksPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTchatschatIdfeedbacksE8588286": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APICreateMessages1C3421C0", + "APIUpdateFeedback2F9276A1", "Arn", ], }, @@ -6737,7 +6652,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/POST/chats/*/messages", + "/POST/chats/*/feedbacks", ], ], }, @@ -6745,13 +6660,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdmessagesPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTchatschatIdmessagesDB24918A": { + "APIApichatschatIdfeedbacksPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTchatschatIdfeedbacks52610594": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APICreateMessages1C3421C0", + "APIUpdateFeedback2F9276A1", "Arn", ], }, @@ -6768,7 +6683,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/POST/chats/*/messages", + "/test-invoke-stage/POST/chats/*/feedbacks", ], ], }, @@ -6776,13 +6691,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdtitleC5AEA917": { + "APIApichatschatIdmessagesAF527CE8": { "DeletionPolicy": "Delete", "Properties": { "ParentId": { "Ref": "APIApichatschatIdE67019A6", }, - "PathPart": "title", + "PathPart": "messages", "RestApiId": { "Ref": "APIApiFFA96F67", }, @@ -6790,56 +6705,14 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Resource", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdtitleOPTIONSFA0EB6B7": { - "DeletionPolicy": "Delete", - "Properties": { - "ApiKeyRequired": false, - "AuthorizationType": "NONE", - "HttpMethod": "OPTIONS", - "Integration": { - "IntegrationResponses": [ - { - "ResponseParameters": { - "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", - "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'", - "method.response.header.Access-Control-Allow-Origin": "'*'", - }, - "StatusCode": "204", - }, - ], - "RequestTemplates": { - "application/json": "{ statusCode: 200 }", - }, - "Type": "MOCK", - }, - "MethodResponses": [ - { - "ResponseParameters": { - "method.response.header.Access-Control-Allow-Headers": true, - "method.response.header.Access-Control-Allow-Methods": true, - "method.response.header.Access-Control-Allow-Origin": true, - }, - "StatusCode": "204", - }, - ], - "ResourceId": { - "Ref": "APIApichatschatIdtitleC5AEA917", - }, - "RestApiId": { - "Ref": "APIApiFFA96F67", - }, - }, - "Type": "AWS::ApiGateway::Method", - "UpdateReplacePolicy": "Delete", - }, - "APIApichatschatIdtitlePUT15099F54": { + "APIApichatschatIdmessagesGET94AB097F": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", "AuthorizerId": { "Ref": "APIAuthorizer9DCC037B", }, - "HttpMethod": "PUT", + "HttpMethod": "GET", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -6854,7 +6727,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIUpdateChatTitleF8FCA547", + "APIListMessages536ED2CC", "Arn", ], }, @@ -6864,7 +6737,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApichatschatIdtitleC5AEA917", + "Ref": "APIApichatschatIdmessagesAF527CE8", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -6873,13 +6746,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdtitlePUTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17PUTchatschatIdtitleF57C315F": { + "APIApichatschatIdmessagesGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdmessages122A59FC": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIUpdateChatTitleF8FCA547", + "APIListMessages536ED2CC", "Arn", ], }, @@ -6900,7 +6773,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/PUT/chats/*/title", + "/GET/chats/*/messages", ], ], }, @@ -6908,13 +6781,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdtitlePUTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17PUTchatschatIdtitle5F294013": { + "APIApichatschatIdmessagesGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdmessages3F025E8E": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIUpdateChatTitleF8FCA547", + "APIListMessages536ED2CC", "Arn", ], }, @@ -6931,7 +6804,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/PUT/chats/*/title", + "/test-invoke-stage/GET/chats/*/messages", ], ], }, @@ -6939,24 +6812,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApifile76AB343B": { - "DeletionPolicy": "Delete", - "Properties": { - "ParentId": { - "Fn::GetAtt": [ - "APIApiFFA96F67", - "RootResourceId", - ], - }, - "PathPart": "file", - "RestApiId": { - "Ref": "APIApiFFA96F67", - }, - }, - "Type": "AWS::ApiGateway::Resource", - "UpdateReplacePolicy": "Delete", - }, - "APIApifileOPTIONS64A72556": { + "APIApichatschatIdmessagesOPTIONS20207E07": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -6989,7 +6845,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, ], "ResourceId": { - "Ref": "APIApifile76AB343B", + "Ref": "APIApichatschatIdmessagesAF527CE8", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -6998,28 +6854,14 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApifilefileName2B0471F4": { - "DeletionPolicy": "Delete", - "Properties": { - "ParentId": { - "Ref": "APIApifile76AB343B", - }, - "PathPart": "{fileName}", - "RestApiId": { - "Ref": "APIApiFFA96F67", - }, - }, - "Type": "AWS::ApiGateway::Resource", - "UpdateReplacePolicy": "Delete", - }, - "APIApifilefileNameDELETE54EB1050": { + "APIApichatschatIdmessagesPOST4197DA8F": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", "AuthorizerId": { "Ref": "APIAuthorizer9DCC037B", }, - "HttpMethod": "DELETE", + "HttpMethod": "POST", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -7034,7 +6876,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIDeleteFileFunctionC52312C7", + "APICreateMessages1C3421C0", "Arn", ], }, @@ -7044,7 +6886,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApifilefileName2B0471F4", + "Ref": "APIApichatschatIdmessagesAF527CE8", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -7053,13 +6895,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApifilefileNameDELETEApiPermissionGenerativeAiUseCasesStackAPIApi89219E17DELETEfilefileName48EC68D3": { + "APIApichatschatIdmessagesPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTchatschatIdmessages832E69DC": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIDeleteFileFunctionC52312C7", + "APICreateMessages1C3421C0", "Arn", ], }, @@ -7080,7 +6922,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/DELETE/file/*", + "/POST/chats/*/messages", ], ], }, @@ -7088,13 +6930,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApifilefileNameDELETEApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17DELETEfilefileName6979E07E": { + "APIApichatschatIdmessagesPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTchatschatIdmessagesDB24918A": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIDeleteFileFunctionC52312C7", + "APICreateMessages1C3421C0", "Arn", ], }, @@ -7111,7 +6953,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/DELETE/file/*", + "/test-invoke-stage/POST/chats/*/messages", ], ], }, @@ -7119,7 +6961,21 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApifilefileNameOPTIONS6C97AC5A": { + "APIApichatschatIdtitleC5AEA917": { + "DeletionPolicy": "Delete", + "Properties": { + "ParentId": { + "Ref": "APIApichatschatIdE67019A6", + }, + "PathPart": "title", + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Resource", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatschatIdtitleOPTIONSFA0EB6B7": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -7152,7 +7008,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, ], "ResourceId": { - "Ref": "APIApifilefileName2B0471F4", + "Ref": "APIApichatschatIdtitleC5AEA917", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -7161,28 +7017,14 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApifileurl08DA507F": { - "DeletionPolicy": "Delete", - "Properties": { - "ParentId": { - "Ref": "APIApifile76AB343B", - }, - "PathPart": "url", - "RestApiId": { - "Ref": "APIApiFFA96F67", - }, - }, - "Type": "AWS::ApiGateway::Resource", - "UpdateReplacePolicy": "Delete", - }, - "APIApifileurlGET6E9EDFE6": { + "APIApichatschatIdtitlePUT15099F54": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", "AuthorizerId": { "Ref": "APIAuthorizer9DCC037B", }, - "HttpMethod": "GET", + "HttpMethod": "PUT", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -7197,7 +7039,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIGetFileDownloadSignedUrlFunction8B43389C", + "APIUpdateChatTitleF8FCA547", "Arn", ], }, @@ -7207,7 +7049,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApifileurl08DA507F", + "Ref": "APIApichatschatIdtitleC5AEA917", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -7216,13 +7058,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApifileurlGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETfileurl0485E8FF": { + "APIApichatschatIdtitlePUTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17PUTchatschatIdtitleF57C315F": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIGetFileDownloadSignedUrlFunction8B43389C", + "APIUpdateChatTitleF8FCA547", "Arn", ], }, @@ -7243,7 +7085,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/GET/file/url", + "/PUT/chats/*/title", ], ], }, @@ -7251,13 +7093,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApifileurlGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETfileurl88BCDC54": { + "APIApichatschatIdtitlePUTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17PUTchatschatIdtitle5F294013": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIGetFileDownloadSignedUrlFunction8B43389C", + "APIUpdateChatTitleF8FCA547", "Arn", ], }, @@ -7274,7 +7116,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/GET/file/url", + "/test-invoke-stage/PUT/chats/*/title", ], ], }, @@ -7282,7 +7124,24 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApifileurlOPTIONS658BFB93": { + "APIApifile76AB343B": { + "DeletionPolicy": "Delete", + "Properties": { + "ParentId": { + "Fn::GetAtt": [ + "APIApiFFA96F67", + "RootResourceId", + ], + }, + "PathPart": "file", + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Resource", + "UpdateReplacePolicy": "Delete", + }, + "APIApifileOPTIONS64A72556": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -7315,7 +7174,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, ], "ResourceId": { - "Ref": "APIApifileurl08DA507F", + "Ref": "APIApifile76AB343B", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -7324,14 +7183,28 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApifileurlPOST73D5BB3A": { + "APIApifilefileName2B0471F4": { + "DeletionPolicy": "Delete", + "Properties": { + "ParentId": { + "Ref": "APIApifile76AB343B", + }, + "PathPart": "{fileName}", + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Resource", + "UpdateReplacePolicy": "Delete", + }, + "APIApifilefileNameDELETE54EB1050": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", "AuthorizerId": { "Ref": "APIAuthorizer9DCC037B", }, - "HttpMethod": "POST", + "HttpMethod": "DELETE", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -7346,7 +7219,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIGetSignedUrl0A6EC682", + "APIDeleteFileFunctionC52312C7", "Arn", ], }, @@ -7356,7 +7229,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApifileurl08DA507F", + "Ref": "APIApifilefileName2B0471F4", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -7365,13 +7238,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApifileurlPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTfileurl83D310CC": { + "APIApifilefileNameDELETEApiPermissionGenerativeAiUseCasesStackAPIApi89219E17DELETEfilefileName48EC68D3": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIGetSignedUrl0A6EC682", + "APIDeleteFileFunctionC52312C7", "Arn", ], }, @@ -7392,7 +7265,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/POST/file/url", + "/DELETE/file/*", ], ], }, @@ -7400,13 +7273,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApifileurlPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTfileurlB327A180": { + "APIApifilefileNameDELETEApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17DELETEfilefileName6979E07E": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIGetSignedUrl0A6EC682", + "APIDeleteFileFunctionC52312C7", "Arn", ], }, @@ -7423,7 +7296,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/POST/file/url", + "/test-invoke-stage/DELETE/file/*", ], ], }, @@ -7431,24 +7304,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApiimage6FBCA1DF": { - "DeletionPolicy": "Delete", - "Properties": { - "ParentId": { - "Fn::GetAtt": [ - "APIApiFFA96F67", - "RootResourceId", - ], - }, - "PathPart": "image", - "RestApiId": { - "Ref": "APIApiFFA96F67", - }, - }, - "Type": "AWS::ApiGateway::Resource", - "UpdateReplacePolicy": "Delete", - }, - "APIApiimageOPTIONSA57099DB": { + "APIApifilefileNameOPTIONS6C97AC5A": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -7481,7 +7337,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, ], "ResourceId": { - "Ref": "APIApiimage6FBCA1DF", + "Ref": "APIApifilefileName2B0471F4", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -7490,13 +7346,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApiimagegenerate70662BCD": { + "APIApifileurl08DA507F": { "DeletionPolicy": "Delete", "Properties": { "ParentId": { - "Ref": "APIApiimage6FBCA1DF", + "Ref": "APIApifile76AB343B", }, - "PathPart": "generate", + "PathPart": "url", "RestApiId": { "Ref": "APIApiFFA96F67", }, @@ -7504,56 +7360,14 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Resource", "UpdateReplacePolicy": "Delete", }, - "APIApiimagegenerateOPTIONS58BC3827": { - "DeletionPolicy": "Delete", - "Properties": { - "ApiKeyRequired": false, - "AuthorizationType": "NONE", - "HttpMethod": "OPTIONS", - "Integration": { - "IntegrationResponses": [ - { - "ResponseParameters": { - "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", - "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'", - "method.response.header.Access-Control-Allow-Origin": "'*'", - }, - "StatusCode": "204", - }, - ], - "RequestTemplates": { - "application/json": "{ statusCode: 200 }", - }, - "Type": "MOCK", - }, - "MethodResponses": [ - { - "ResponseParameters": { - "method.response.header.Access-Control-Allow-Headers": true, - "method.response.header.Access-Control-Allow-Methods": true, - "method.response.header.Access-Control-Allow-Origin": true, - }, - "StatusCode": "204", - }, - ], - "ResourceId": { - "Ref": "APIApiimagegenerate70662BCD", - }, - "RestApiId": { - "Ref": "APIApiFFA96F67", - }, - }, - "Type": "AWS::ApiGateway::Method", - "UpdateReplacePolicy": "Delete", - }, - "APIApiimagegeneratePOST0F60597D": { + "APIApifileurlGET6E9EDFE6": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", "AuthorizerId": { "Ref": "APIAuthorizer9DCC037B", }, - "HttpMethod": "POST", + "HttpMethod": "GET", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -7568,7 +7382,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIGenerateImage777647C7", + "APIGetFileDownloadSignedUrlFunction8B43389C", "Arn", ], }, @@ -7578,7 +7392,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApiimagegenerate70662BCD", + "Ref": "APIApifileurl08DA507F", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -7587,13 +7401,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApiimagegeneratePOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTimagegenerate41F8E49F": { + "APIApifileurlGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETfileurl0485E8FF": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIGenerateImage777647C7", + "APIGetFileDownloadSignedUrlFunction8B43389C", "Arn", ], }, @@ -7614,7 +7428,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/POST/image/generate", + "/GET/file/url", ], ], }, @@ -7622,13 +7436,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApiimagegeneratePOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTimagegenerateFE576B22": { + "APIApifileurlGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETfileurl88BCDC54": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIGenerateImage777647C7", + "APIGetFileDownloadSignedUrlFunction8B43389C", "Arn", ], }, @@ -7645,7 +7459,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/POST/image/generate", + "/test-invoke-stage/GET/file/url", ], ], }, @@ -7653,24 +7467,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApipredict6CA3C413": { - "DeletionPolicy": "Delete", - "Properties": { - "ParentId": { - "Fn::GetAtt": [ - "APIApiFFA96F67", - "RootResourceId", - ], - }, - "PathPart": "predict", - "RestApiId": { - "Ref": "APIApiFFA96F67", - }, - }, - "Type": "AWS::ApiGateway::Resource", - "UpdateReplacePolicy": "Delete", - }, - "APIApipredictOPTIONS9065A8D6": { + "APIApifileurlOPTIONS658BFB93": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -7703,7 +7500,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, ], "ResourceId": { - "Ref": "APIApipredict6CA3C413", + "Ref": "APIApifileurl08DA507F", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -7712,7 +7509,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApipredictPOST376D7D2E": { + "APIApifileurlPOST73D5BB3A": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", @@ -7734,7 +7531,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIPredict09E4E4FF", + "APIGetSignedUrl0A6EC682", "Arn", ], }, @@ -7744,7 +7541,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApipredict6CA3C413", + "Ref": "APIApifileurl08DA507F", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -7753,13 +7550,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApipredictPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTpredict03DB8E81": { + "APIApifileurlPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTfileurl83D310CC": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIPredict09E4E4FF", + "APIGetSignedUrl0A6EC682", "Arn", ], }, @@ -7780,7 +7577,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/POST/predict", + "/POST/file/url", ], ], }, @@ -7788,13 +7585,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApipredictPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTpredictFAF8FA72": { + "APIApifileurlPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTfileurlB327A180": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIPredict09E4E4FF", + "APIGetSignedUrl0A6EC682", "Arn", ], }, @@ -7811,7 +7608,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/POST/predict", + "/test-invoke-stage/POST/file/url", ], ], }, @@ -7819,13 +7616,16 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApipredicttitle8F6A9913": { + "APIApiimage6FBCA1DF": { "DeletionPolicy": "Delete", "Properties": { "ParentId": { - "Ref": "APIApipredict6CA3C413", + "Fn::GetAtt": [ + "APIApiFFA96F67", + "RootResourceId", + ], }, - "PathPart": "title", + "PathPart": "image", "RestApiId": { "Ref": "APIApiFFA96F67", }, @@ -7833,7 +7633,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Resource", "UpdateReplacePolicy": "Delete", }, - "APIApipredicttitleOPTIONS3DCF08ED": { + "APIApiimageOPTIONSA57099DB": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -7866,7 +7666,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, ], "ResourceId": { - "Ref": "APIApipredicttitle8F6A9913", + "Ref": "APIApiimage6FBCA1DF", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -7875,7 +7675,63 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApipredicttitlePOSTAC11F63E": { + "APIApiimagegenerate70662BCD": { + "DeletionPolicy": "Delete", + "Properties": { + "ParentId": { + "Ref": "APIApiimage6FBCA1DF", + }, + "PathPart": "generate", + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Resource", + "UpdateReplacePolicy": "Delete", + }, + "APIApiimagegenerateOPTIONS58BC3827": { + "DeletionPolicy": "Delete", + "Properties": { + "ApiKeyRequired": false, + "AuthorizationType": "NONE", + "HttpMethod": "OPTIONS", + "Integration": { + "IntegrationResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", + "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'", + "method.response.header.Access-Control-Allow-Origin": "'*'", + }, + "StatusCode": "204", + }, + ], + "RequestTemplates": { + "application/json": "{ statusCode: 200 }", + }, + "Type": "MOCK", + }, + "MethodResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": true, + "method.response.header.Access-Control-Allow-Methods": true, + "method.response.header.Access-Control-Allow-Origin": true, + }, + "StatusCode": "204", + }, + ], + "ResourceId": { + "Ref": "APIApiimagegenerate70662BCD", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApiimagegeneratePOST0F60597D": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", @@ -7897,7 +7753,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIPredictTitle95F64FA4", + "APIGenerateImage777647C7", "Arn", ], }, @@ -7907,7 +7763,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "ResourceId": { - "Ref": "APIApipredicttitle8F6A9913", + "Ref": "APIApiimagegenerate70662BCD", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -7916,13 +7772,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApipredicttitlePOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTpredicttitle9C698441": { + "APIApiimagegeneratePOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTimagegenerate41F8E49F": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIPredictTitle95F64FA4", + "APIGenerateImage777647C7", "Arn", ], }, @@ -7943,7 +7799,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/POST/predict/title", + "/POST/image/generate", ], ], }, @@ -7951,13 +7807,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApipredicttitlePOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTpredicttitleF8561C52": { + "APIApiimagegeneratePOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTimagegenerateFE576B22": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIPredictTitle95F64FA4", + "APIGenerateImage777647C7", "Arn", ], }, @@ -7974,7 +7830,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/POST/predict/title", + "/test-invoke-stage/POST/image/generate", ], ], }, @@ -7982,7 +7838,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApiragB0FA73F7": { + "APIApipredict6CA3C413": { "DeletionPolicy": "Delete", "Properties": { "ParentId": { @@ -7991,7 +7847,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "RootResourceId", ], }, - "PathPart": "rag", + "PathPart": "predict", "RestApiId": { "Ref": "APIApiFFA96F67", }, @@ -7999,7 +7855,336 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::ApiGateway::Resource", "UpdateReplacePolicy": "Delete", }, - "APIApiragOPTIONSAF55562D": { + "APIApipredictOPTIONS9065A8D6": { + "DeletionPolicy": "Delete", + "Properties": { + "ApiKeyRequired": false, + "AuthorizationType": "NONE", + "HttpMethod": "OPTIONS", + "Integration": { + "IntegrationResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", + "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'", + "method.response.header.Access-Control-Allow-Origin": "'*'", + }, + "StatusCode": "204", + }, + ], + "RequestTemplates": { + "application/json": "{ statusCode: 200 }", + }, + "Type": "MOCK", + }, + "MethodResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": true, + "method.response.header.Access-Control-Allow-Methods": true, + "method.response.header.Access-Control-Allow-Origin": true, + }, + "StatusCode": "204", + }, + ], + "ResourceId": { + "Ref": "APIApipredict6CA3C413", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApipredictPOST376D7D2E": { + "DeletionPolicy": "Delete", + "Properties": { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": { + "Ref": "APIAuthorizer9DCC037B", + }, + "HttpMethod": "POST", + "Integration": { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", + { + "Fn::GetAtt": [ + "APIPredict09E4E4FF", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": { + "Ref": "APIApipredict6CA3C413", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApipredictPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTpredict03DB8E81": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APIPredict09E4E4FF", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/", + { + "Ref": "APIApiDeploymentStageapiCD55D117", + }, + "/POST/predict", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApipredictPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTpredictFAF8FA72": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APIPredict09E4E4FF", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/test-invoke-stage/POST/predict", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApipredicttitle8F6A9913": { + "DeletionPolicy": "Delete", + "Properties": { + "ParentId": { + "Ref": "APIApipredict6CA3C413", + }, + "PathPart": "title", + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Resource", + "UpdateReplacePolicy": "Delete", + }, + "APIApipredicttitleOPTIONS3DCF08ED": { + "DeletionPolicy": "Delete", + "Properties": { + "ApiKeyRequired": false, + "AuthorizationType": "NONE", + "HttpMethod": "OPTIONS", + "Integration": { + "IntegrationResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", + "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'", + "method.response.header.Access-Control-Allow-Origin": "'*'", + }, + "StatusCode": "204", + }, + ], + "RequestTemplates": { + "application/json": "{ statusCode: 200 }", + }, + "Type": "MOCK", + }, + "MethodResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": true, + "method.response.header.Access-Control-Allow-Methods": true, + "method.response.header.Access-Control-Allow-Origin": true, + }, + "StatusCode": "204", + }, + ], + "ResourceId": { + "Ref": "APIApipredicttitle8F6A9913", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApipredicttitlePOSTAC11F63E": { + "DeletionPolicy": "Delete", + "Properties": { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": { + "Ref": "APIAuthorizer9DCC037B", + }, + "HttpMethod": "POST", + "Integration": { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", + { + "Fn::GetAtt": [ + "APIPredictTitle95F64FA4", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": { + "Ref": "APIApipredicttitle8F6A9913", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApipredicttitlePOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTpredicttitle9C698441": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APIPredictTitle95F64FA4", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/", + { + "Ref": "APIApiDeploymentStageapiCD55D117", + }, + "/POST/predict/title", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApipredicttitlePOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTpredicttitleF8561C52": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APIPredictTitle95F64FA4", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/test-invoke-stage/POST/predict/title", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApiragB0FA73F7": { + "DeletionPolicy": "Delete", + "Properties": { + "ParentId": { + "Fn::GetAtt": [ + "APIApiFFA96F67", + "RootResourceId", + ], + }, + "PathPart": "rag", + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Resource", + "UpdateReplacePolicy": "Delete", + }, + "APIApiragOPTIONSAF55562D": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -18258,7 +18443,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "", [ { - "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7AgentCoreRuntimeArn010E372F", + "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803AgentRuntimeArn53FA08A2", }, "*", ], @@ -18297,22 +18482,22 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "destinationBucketName": "cdk-hnb659fds-assets-123456890123-us-east-1", "environment": { "NODE_OPTIONS": "--max-old-space-size=4096", + "VITE_APP_AGENTS": "[{"displayName":"SearchEngine","description":"Agent with Web Search Functionality"},{"displayName":"CodeInterpreter","description":"Agent with Code Interpreter Functionality"}]", "VITE_APP_AGENT_CORE_ENABLED": "true", "VITE_APP_AGENT_CORE_EXTERNAL_RUNTIMES": "[]", "VITE_APP_AGENT_CORE_GENERIC_RUNTIME": { "Fn::Join": [ "", [ - "{"name":"GenericAgentCoreRuntime","arn":"", + "{"name":"GenUAgentCoreRuntime","arn":"", { - "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7AgentCoreRuntimeArn010E372F", + "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803AgentRuntimeArn53FA08A2", }, - ""}", + "","description":"Generic Agent Core Runtime for custom agents"}", ], ], }, "VITE_APP_AGENT_ENABLED": "true", - "VITE_APP_AGENT_NAMES": "["SearchEngine","CodeInterpreter"]", "VITE_APP_API_ENDPOINT": { "Fn::Join": [ "", @@ -18400,6 +18585,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "VITE_APP_INLINE_AGENTS": "false", "VITE_APP_MCP_ENABLED": "false", "VITE_APP_MCP_ENDPOINT": "", + "VITE_APP_MCP_SERVERS_CONFIG": "{"time":{"metadata":{"category":"Utility","description":"Provides current time and date functionality"}},"aws-knowledge-mcp-server":{"metadata":{"category":"AWS","description":"AWS Knowledge Base MCP server for enterprise knowledge access"}},"awslabs.aws-documentation-mcp-server":{"metadata":{"category":"AWS","description":"Access AWS documentation and guides"}},"awslabs.cdk-mcp-server":{"metadata":{"category":"AWS","description":"AWS CDK code generation and assistance"}},"awslabs.aws-diagram-mcp-server":{"metadata":{"category":"AWS","description":"Generate AWS architecture diagrams"}},"awslabs.nova-canvas-mcp-server":{"metadata":{"category":"AI/ML","description":"Amazon Nova Canvas image generation"}},"tavily-search":{"metadata":{"category":"Search","description":"Web search and research capabilities powered by Tavily"}}}", "VITE_APP_MODEL_IDS": { "Fn::Join": [ "", @@ -18538,6 +18724,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ], }, ], + "WaitForDistributionInvalidation": true, }, "Type": "Custom::CDKBucketDeployment", "UpdateReplacePolicy": "Delete", @@ -19200,7 +19387,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Arn", ], }, - "Runtime": "python3.11", + "Runtime": "python3.13", "Timeout": 900, }, "Type": "AWS::Lambda::Function", @@ -19357,7 +19544,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Arn", ], }, - "Runtime": "python3.11", + "Runtime": "python3.13", "Timeout": 900, }, "Type": "AWS::Lambda::Function", @@ -20151,6 +20338,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "SourceObjectKeys": [ "HASH-REPLACED.zip", ], + "WaitForDistributionInvalidation": true, }, "Type": "Custom::CDKBucketDeployment", "UpdateReplacePolicy": "Delete", @@ -21945,32 +22133,11 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::S3::BucketPolicy", "UpdateReplacePolicy": "Delete", }, - "UseCaseBuilderAuthorizer8C07733E": { - "DeletionPolicy": "Delete", - "Properties": { - "IdentitySource": "method.request.header.Authorization", - "Name": "GenerativeAiUseCasesStackUseCaseBuilderAuthorizer9AB4C426", - "ProviderARNs": [ - { - "Fn::GetAtt": [ - "AuthUserPool8115E87F", - "Arn", - ], - }, - ], - "RestApiId": { - "Ref": "APIApiFFA96F67", - }, - "Type": "COGNITO_USER_POOLS", - }, - "Type": "AWS::ApiGateway::Authorizer", - "UpdateReplacePolicy": "Delete", - }, - "UseCaseBuilderCreateUseCase63174982": { + "UseCaseBuilderAgentBuilderDAB96216": { "DeletionPolicy": "Delete", "DependsOn": [ - "UseCaseBuilderCreateUseCaseServiceRoleDefaultPolicyC8ABD900", - "UseCaseBuilderCreateUseCaseServiceRoleA3FFCC29", + "UseCaseBuilderAgentBuilderServiceRoleDefaultPolicy55D3FBBC", + "UseCaseBuilderAgentBuilderServiceRole9C6C40B9", ], "Properties": { "Code": { @@ -21979,16 +22146,21 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, "Environment": { "Variables": { + "MODEL_REGION": "us-east-1", "USECASE_ID_INDEX_NAME": "UseCaseIdIndexName", "USECASE_TABLE_NAME": { "Ref": "UseCaseBuilderUseCaseBuilderTable449740F3", }, + "USER_POOL_ID": { + "Ref": "AuthUserPool8115E87F", + }, }, }, "Handler": "index.handler", + "MemorySize": 1024, "Role": { "Fn::GetAtt": [ - "UseCaseBuilderCreateUseCaseServiceRoleA3FFCC29", + "UseCaseBuilderAgentBuilderServiceRole9C6C40B9", "Arn", ], }, @@ -22016,7 +22188,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Function", "UpdateReplacePolicy": "Delete", }, - "UseCaseBuilderCreateUseCaseServiceRoleA3FFCC29": { + "UseCaseBuilderAgentBuilderServiceRole9C6C40B9": { "DeletionPolicy": "Delete", "Properties": { "AssumeRolePolicyDocument": { @@ -22061,13 +22233,20 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::IAM::Role", "UpdateReplacePolicy": "Delete", }, - "UseCaseBuilderCreateUseCaseServiceRoleDefaultPolicyC8ABD900": { + "UseCaseBuilderAgentBuilderServiceRoleDefaultPolicy55D3FBBC": { "DeletionPolicy": "Delete", "Properties": { "PolicyDocument": { "Statement": [ { "Action": [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", @@ -22098,24 +22277,63 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, ], }, + { + "Action": [ + "bedrock:*", + "logs:*", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": "cognito-idp:AdminGetUser", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "AuthUserPool8115E87F", + "Arn", + ], + }, + }, ], "Version": "2012-10-17", }, - "PolicyName": "UseCaseBuilderCreateUseCaseServiceRoleDefaultPolicyC8ABD900", + "PolicyName": "UseCaseBuilderAgentBuilderServiceRoleDefaultPolicy55D3FBBC", "Roles": [ { - "Ref": "UseCaseBuilderCreateUseCaseServiceRoleA3FFCC29", + "Ref": "UseCaseBuilderAgentBuilderServiceRole9C6C40B9", }, ], }, "Type": "AWS::IAM::Policy", "UpdateReplacePolicy": "Delete", }, - "UseCaseBuilderDeleteUseCaseA7529A4C": { + "UseCaseBuilderAuthorizer8C07733E": { + "DeletionPolicy": "Delete", + "Properties": { + "IdentitySource": "method.request.header.Authorization", + "Name": "GenerativeAiUseCasesStackUseCaseBuilderAuthorizer9AB4C426", + "ProviderARNs": [ + { + "Fn::GetAtt": [ + "AuthUserPool8115E87F", + "Arn", + ], + }, + ], + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + "Type": "COGNITO_USER_POOLS", + }, + "Type": "AWS::ApiGateway::Authorizer", + "UpdateReplacePolicy": "Delete", + }, + "UseCaseBuilderCreateUseCase63174982": { "DeletionPolicy": "Delete", "DependsOn": [ - "UseCaseBuilderDeleteUseCaseServiceRoleDefaultPolicy40E63535", - "UseCaseBuilderDeleteUseCaseServiceRoleCC0155F5", + "UseCaseBuilderCreateUseCaseServiceRoleDefaultPolicyC8ABD900", + "UseCaseBuilderCreateUseCaseServiceRoleA3FFCC29", ], "Properties": { "Code": { @@ -22133,7 +22351,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Handler": "index.handler", "Role": { "Fn::GetAtt": [ - "UseCaseBuilderDeleteUseCaseServiceRoleCC0155F5", + "UseCaseBuilderCreateUseCaseServiceRoleA3FFCC29", "Arn", ], }, @@ -22161,7 +22379,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Function", "UpdateReplacePolicy": "Delete", }, - "UseCaseBuilderDeleteUseCaseServiceRoleCC0155F5": { + "UseCaseBuilderCreateUseCaseServiceRoleA3FFCC29": { "DeletionPolicy": "Delete", "Properties": { "AssumeRolePolicyDocument": { @@ -22206,20 +22424,13 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::IAM::Role", "UpdateReplacePolicy": "Delete", }, - "UseCaseBuilderDeleteUseCaseServiceRoleDefaultPolicy40E63535": { + "UseCaseBuilderCreateUseCaseServiceRoleDefaultPolicyC8ABD900": { "DeletionPolicy": "Delete", "Properties": { "PolicyDocument": { "Statement": [ { "Action": [ - "dynamodb:BatchGetItem", - "dynamodb:GetRecords", - "dynamodb:GetShardIterator", - "dynamodb:Query", - "dynamodb:GetItem", - "dynamodb:Scan", - "dynamodb:ConditionCheckItem", "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", @@ -22253,21 +22464,21 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ], "Version": "2012-10-17", }, - "PolicyName": "UseCaseBuilderDeleteUseCaseServiceRoleDefaultPolicy40E63535", + "PolicyName": "UseCaseBuilderCreateUseCaseServiceRoleDefaultPolicyC8ABD900", "Roles": [ { - "Ref": "UseCaseBuilderDeleteUseCaseServiceRoleCC0155F5", + "Ref": "UseCaseBuilderCreateUseCaseServiceRoleA3FFCC29", }, ], }, "Type": "AWS::IAM::Policy", "UpdateReplacePolicy": "Delete", }, - "UseCaseBuilderGetUseCaseAB744D97": { + "UseCaseBuilderDeleteUseCaseA7529A4C": { "DeletionPolicy": "Delete", "DependsOn": [ - "UseCaseBuilderGetUseCaseServiceRoleDefaultPolicyB8CCBF75", - "UseCaseBuilderGetUseCaseServiceRoleF32AAC5F", + "UseCaseBuilderDeleteUseCaseServiceRoleDefaultPolicy40E63535", + "UseCaseBuilderDeleteUseCaseServiceRoleCC0155F5", ], "Properties": { "Code": { @@ -22283,10 +22494,9 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` }, }, "Handler": "index.handler", - "MemorySize": 512, "Role": { "Fn::GetAtt": [ - "UseCaseBuilderGetUseCaseServiceRoleF32AAC5F", + "UseCaseBuilderDeleteUseCaseServiceRoleCC0155F5", "Arn", ], }, @@ -22314,7 +22524,52 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Function", "UpdateReplacePolicy": "Delete", }, - "UseCaseBuilderGetUseCaseServiceRoleDefaultPolicyB8CCBF75": { + "UseCaseBuilderDeleteUseCaseServiceRoleCC0155F5": { + "DeletionPolicy": "Delete", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + "UpdateReplacePolicy": "Delete", + }, + "UseCaseBuilderDeleteUseCaseServiceRoleDefaultPolicy40E63535": { "DeletionPolicy": "Delete", "Properties": { "PolicyDocument": { @@ -22328,6 +22583,10 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "dynamodb:GetItem", "dynamodb:Scan", "dynamodb:ConditionCheckItem", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", "dynamodb:DescribeTable", ], "Effect": "Allow", @@ -22357,66 +22616,21 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` ], "Version": "2012-10-17", }, - "PolicyName": "UseCaseBuilderGetUseCaseServiceRoleDefaultPolicyB8CCBF75", + "PolicyName": "UseCaseBuilderDeleteUseCaseServiceRoleDefaultPolicy40E63535", "Roles": [ { - "Ref": "UseCaseBuilderGetUseCaseServiceRoleF32AAC5F", + "Ref": "UseCaseBuilderDeleteUseCaseServiceRoleCC0155F5", }, ], }, "Type": "AWS::IAM::Policy", "UpdateReplacePolicy": "Delete", }, - "UseCaseBuilderGetUseCaseServiceRoleF32AAC5F": { - "DeletionPolicy": "Delete", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - ], - ], - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole", - ], - ], - }, - ], - }, - "Type": "AWS::IAM::Role", - "UpdateReplacePolicy": "Delete", - }, - "UseCaseBuilderListFavoriteUseCasesC4AF9A45": { + "UseCaseBuilderGetUseCaseAB744D97": { "DeletionPolicy": "Delete", "DependsOn": [ - "UseCaseBuilderListFavoriteUseCasesServiceRoleDefaultPolicy51BC1ECC", - "UseCaseBuilderListFavoriteUseCasesServiceRole5BCFD9A7", + "UseCaseBuilderGetUseCaseServiceRoleDefaultPolicyB8CCBF75", + "UseCaseBuilderGetUseCaseServiceRoleF32AAC5F", ], "Properties": { "Code": { @@ -22435,7 +22649,7 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "MemorySize": 512, "Role": { "Fn::GetAtt": [ - "UseCaseBuilderListFavoriteUseCasesServiceRole5BCFD9A7", + "UseCaseBuilderGetUseCaseServiceRoleF32AAC5F", "Arn", ], }, @@ -22463,52 +22677,201 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = ` "Type": "AWS::Lambda::Function", "UpdateReplacePolicy": "Delete", }, - "UseCaseBuilderListFavoriteUseCasesServiceRole5BCFD9A7": { - "DeletionPolicy": "Delete", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - ], - ], - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole", - ], - ], - }, - ], - }, - "Type": "AWS::IAM::Role", - "UpdateReplacePolicy": "Delete", - }, - "UseCaseBuilderListFavoriteUseCasesServiceRoleDefaultPolicy51BC1ECC": { + "UseCaseBuilderGetUseCaseServiceRoleDefaultPolicyB8CCBF75": { + "DeletionPolicy": "Delete", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", + "dynamodb:DescribeTable", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "UseCaseBuilderUseCaseBuilderTable449740F3", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "UseCaseBuilderUseCaseBuilderTable449740F3", + "Arn", + ], + }, + "/index/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "UseCaseBuilderGetUseCaseServiceRoleDefaultPolicyB8CCBF75", + "Roles": [ + { + "Ref": "UseCaseBuilderGetUseCaseServiceRoleF32AAC5F", + }, + ], + }, + "Type": "AWS::IAM::Policy", + "UpdateReplacePolicy": "Delete", + }, + "UseCaseBuilderGetUseCaseServiceRoleF32AAC5F": { + "DeletionPolicy": "Delete", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + "UpdateReplacePolicy": "Delete", + }, + "UseCaseBuilderListFavoriteUseCasesC4AF9A45": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "UseCaseBuilderListFavoriteUseCasesServiceRoleDefaultPolicy51BC1ECC", + "UseCaseBuilderListFavoriteUseCasesServiceRole5BCFD9A7", + ], + "Properties": { + "Code": { + "S3Bucket": "cdk-hnb659fds-assets-123456890123-us-east-1", + "S3Key": "HASH-REPLACED.zip", + }, + "Environment": { + "Variables": { + "USECASE_ID_INDEX_NAME": "UseCaseIdIndexName", + "USECASE_TABLE_NAME": { + "Ref": "UseCaseBuilderUseCaseBuilderTable449740F3", + }, + }, + }, + "Handler": "index.handler", + "MemorySize": 512, + "Role": { + "Fn::GetAtt": [ + "UseCaseBuilderListFavoriteUseCasesServiceRole5BCFD9A7", + "Arn", + ], + }, + "Runtime": "nodejs22.x", + "Timeout": 900, + "VpcConfig": { + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "LambdaSeurityGroup14B5161A", + "GroupId", + ], + }, + ], + "SubnetIds": [ + { + "Fn::ImportValue": "ClosedNetworkStack:ExportsOutputRefClosedVpcisolatedSubnet1Subnet2EF6D3F36370B312", + }, + { + "Fn::ImportValue": "ClosedNetworkStack:ExportsOutputRefClosedVpcisolatedSubnet2SubnetB169C8D3D828FC40", + }, + ], + }, + }, + "Type": "AWS::Lambda::Function", + "UpdateReplacePolicy": "Delete", + }, + "UseCaseBuilderListFavoriteUseCasesServiceRole5BCFD9A7": { + "DeletionPolicy": "Delete", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + "UpdateReplacePolicy": "Delete", + }, + "UseCaseBuilderListFavoriteUseCasesServiceRoleDefaultPolicy51BC1ECC": { "DeletionPolicy": "Delete", "Properties": { "PolicyDocument": { @@ -24012,7 +24375,7 @@ exports[`GenerativeAiUseCases matches the snapshot 2`] = ` "Arn", ], }, - "Runtime": "python3.11", + "Runtime": "python3.13", "Timeout": 900, }, "Type": "AWS::Lambda::Function", @@ -24545,6 +24908,7 @@ exports[`GenerativeAiUseCases matches the snapshot 2`] = ` "SourceObjectKeys": [ "HASH-REPLACED.zip", ], + "WaitForDistributionInvalidation": true, }, "Type": "Custom::CDKBucketDeployment", "UpdateReplacePolicy": "Delete", @@ -24908,6 +25272,7 @@ exports[`GenerativeAiUseCases matches the snapshot 3`] = ` "SourceObjectKeys": [ "HASH-REPLACED.zip", ], + "WaitForDistributionInvalidation": true, }, "Type": "Custom::CDKBucketDeployment", "UpdateReplacePolicy": "Delete", @@ -25315,7 +25680,7 @@ Automatically detect the language of the user's request and think and answer in ], }, "AutoPrepare": true, - "Description": "Search Agent", + "Description": "Agent with Web Search Functionality", "FoundationModel": "us.anthropic.claude-3-5-sonnet-20241022-v2:0", "IdleSessionTTLInSeconds": 3600, "Instruction": "You are an advanced assistant with the ability to search and retrieve information from the web to perform complex research tasks. @@ -25373,7 +25738,7 @@ Automatically detect the language of the user's request and think and answer in "Arn", ], }, - "Runtime": "python3.11", + "Runtime": "python3.13", "Timeout": 900, }, "Type": "AWS::Lambda::Function", @@ -25586,14 +25951,14 @@ Automatically detect the language of the user's request and think and answer in exports[`GenerativeAiUseCases matches the snapshot 4`] = ` { "Outputs": { - "ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7AgentCoreRuntimeArn010E372F": { + "ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803AgentRuntimeArn53FA08A2": { "Export": { - "Name": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7AgentCoreRuntimeArn010E372F", + "Name": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803AgentRuntimeArn53FA08A2", }, "Value": { "Fn::GetAtt": [ - "GenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7", - "AgentCoreRuntimeArn", + "GenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803", + "AgentRuntimeArn", ], }, }, @@ -25611,8 +25976,8 @@ exports[`GenerativeAiUseCases matches the snapshot 4`] = ` }, "Value": { "Fn::GetAtt": [ - "GenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7", - "AgentCoreRuntimeArn", + "GenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803", + "AgentRuntimeArn", ], }, }, @@ -25620,7 +25985,7 @@ exports[`GenerativeAiUseCases matches the snapshot 4`] = ` "Export": { "Name": "AgentCoreStack-GenericAgentCoreRuntimeName", }, - "Value": "GenericAgentCoreRuntime", + "Value": "GenUAgentCoreRuntime", }, }, "Parameters": { @@ -25687,70 +26052,6 @@ exports[`GenerativeAiUseCases matches the snapshot 4`] = ` }, "Type": "AWS::IAM::Role", }, - "GenericAgentCoreAgentCoreCustomResourceRoleBDED8F6B": { - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - ], - ], - }, - ], - }, - "Type": "AWS::IAM::Role", - }, - "GenericAgentCoreAgentCoreCustomResourceRoleDefaultPolicy673FD2FE": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "bedrock-agentcore:*", - "Effect": "Allow", - "Resource": "*", - "Sid": "BedrockAgentCorePermissions", - }, - { - "Action": "iam:PassRole", - "Condition": { - "StringEquals": { - "iam:PassedToService": "bedrock-agentcore.amazonaws.com", - }, - }, - "Effect": "Allow", - "Resource": "*", - "Sid": "IAMPassRolePermissions", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GenericAgentCoreAgentCoreCustomResourceRoleDefaultPolicy673FD2FE", - "Roles": [ - { - "Ref": "GenericAgentCoreAgentCoreCustomResourceRoleBDED8F6B", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, "GenericAgentCoreAgentCoreFileBucket0430DA42": { "DeletionPolicy": "Delete", "Properties": { @@ -25850,126 +26151,6 @@ exports[`GenerativeAiUseCases matches the snapshot 4`] = ` }, "Type": "AWS::S3::BucketPolicy", }, - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventC9CCB51A": { - "DependsOn": [ - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRoleDefaultPolicyBB9E52E2", - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRole032FFAFA", - ], - "Properties": { - "Code": { - "S3Bucket": "cdk-hnb659fds-assets-123456890123-us-east-1", - "S3Key": "HASH-REPLACED.zip", - }, - "Description": "AWS CDK resource provider framework - onEvent (AgentCoreStack/GenericAgentCore/AgentCoreRuntimeProvider)", - "Environment": { - "Variables": { - "USER_ON_EVENT_FUNCTION_ARN": { - "Fn::GetAtt": [ - "SingletonB8F5E8923A1C4D2F9B7E6C8A5F9D2E1B1B378805", - "Arn", - ], - }, - }, - }, - "Handler": "framework.onEvent", - "LoggingConfig": { - "ApplicationLogLevel": "FATAL", - "LogFormat": "JSON", - }, - "Role": { - "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRole032FFAFA", - "Arn", - ], - }, - "Runtime": "nodejs22.x", - "Timeout": 900, - }, - "Type": "AWS::Lambda::Function", - }, - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRole032FFAFA": { - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - ], - ], - }, - ], - }, - "Type": "AWS::IAM::Role", - }, - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRoleDefaultPolicyBB9E52E2": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "SingletonB8F5E8923A1C4D2F9B7E6C8A5F9D2E1B1B378805", - "Arn", - ], - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "SingletonB8F5E8923A1C4D2F9B7E6C8A5F9D2E1B1B378805", - "Arn", - ], - }, - ":*", - ], - ], - }, - ], - }, - { - "Action": "lambda:GetFunction", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "SingletonB8F5E8923A1C4D2F9B7E6C8A5F9D2E1B1B378805", - "Arn", - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRoleDefaultPolicyBB9E52E2", - "Roles": [ - { - "Ref": "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventServiceRole032FFAFA", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, "GenericAgentCoreAgentCoreRuntimeRepository6901D0DC": { "DeletionPolicy": "Delete", "Properties": { @@ -25991,8 +26172,11 @@ exports[`GenerativeAiUseCases matches the snapshot 4`] = ` "bedrock:InvokeModelWithResponseStream", ], "Effect": "Allow", - "Resource": "*", - "Sid": "BedrockPermissions", + "Resource": [ + "arn:aws:bedrock:*::foundation-model/*", + "arn:aws:bedrock:us-east-1:123456890123:*", + ], + "Sid": "BedrockModelInvocation", }, { "Action": [ @@ -26065,9 +26249,6 @@ exports[`GenerativeAiUseCases matches the snapshot 4`] = ` }, { "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*", "s3:DeleteObject*", "s3:PutObject", "s3:PutObjectLegalHold", @@ -26100,38 +26281,6 @@ exports[`GenerativeAiUseCases matches the snapshot 4`] = ` }, ], }, - { - "Action": [ - "s3:GetObject", - "s3:PutObject", - "s3:ListBucket", - "s3:DeleteObject", - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreFileBucket0430DA42", - "Arn", - ], - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreFileBucket0430DA42", - "Arn", - ], - }, - "/*", - ], - ], - }, - ], - "Sid": "S3BucketAccess", - }, { "Action": [ "bedrock-agentcore:CreateCodeInterpreter", @@ -26182,83 +26331,36 @@ exports[`GenerativeAiUseCases matches the snapshot 4`] = ` ], "Version": "2012-10-17", }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - ], - ], - }, - ], }, "Type": "AWS::IAM::Role", }, - "GenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7": { - "DeletionPolicy": "Delete", + "GenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803": { "Properties": { - "AgentCoreRuntimeName": "GenericAgentCoreRuntime", - "CustomConfig": { - "containerImageUri": { - "Fn::Sub": "123456890123.dkr.ecr.us-east-1.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-123456890123-us-east-1:736d91ac33c9bb64c93f49d1258dbf8aff8d6ec20441291f20f42076efb65f00", - }, - "environmentVariables": { - "FILE_BUCKET": { - "Ref": "GenericAgentCoreAgentCoreFileBucket0430DA42", + "AgentRuntimeArtifact": { + "ContainerConfiguration": { + "ContainerUri": { + "Fn::Sub": "123456890123.dkr.ecr.us-east-1.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-123456890123-us-east-1:eacaf716c76a59b8488fd6fb1f733b73392992af31a340e37d0bb3818021b832", }, }, }, - "NetworkMode": "PUBLIC", - "RoleArn": { - "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreRuntimeRoleF34B80EA", - "Arn", - ], - }, - "ServerProtocol": "HTTP", - "ServiceToken": { - "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreRuntimeProviderframeworkonEventC9CCB51A", - "Arn", - ], - }, - }, - "Type": "AWS::CloudFormation::CustomResource", - "UpdateReplacePolicy": "Delete", - }, - "SingletonB8F5E8923A1C4D2F9B7E6C8A5F9D2E1B1B378805": { - "DependsOn": [ - "GenericAgentCoreAgentCoreCustomResourceRoleDefaultPolicy673FD2FE", - "GenericAgentCoreAgentCoreCustomResourceRoleBDED8F6B", - ], - "Properties": { - "Code": { - "S3Bucket": "cdk-hnb659fds-assets-123456890123-us-east-1", - "S3Key": "HASH-REPLACED.zip", - }, - "Description": "AgentCoreRuntime CustomResource Lambda Function (Singleton)", - "Environment": { - "Variables": { - "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "AgentRuntimeName": "GenUAgentCoreRuntime", + "EnvironmentVariables": { + "FILE_BUCKET": { + "Ref": "GenericAgentCoreAgentCoreFileBucket0430DA42", }, }, - "FunctionName": "AgentCoreRuntime-AgentCoreStack-B8F5E892", - "Handler": "index.handler", - "Role": { + "NetworkConfiguration": { + "NetworkMode": "PUBLIC", + }, + "ProtocolConfiguration": "HTTP", + "RoleArn": { "Fn::GetAtt": [ - "GenericAgentCoreAgentCoreCustomResourceRoleBDED8F6B", + "GenericAgentCoreAgentCoreRuntimeRoleF34B80EA", "Arn", ], }, - "Runtime": "nodejs22.x", - "Timeout": 600, }, - "Type": "AWS::Lambda::Function", + "Type": "AWS::BedrockAgentCore::Runtime", }, }, "Rules": { @@ -26462,9 +26564,9 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Fn::Join": [ "", [ - "{"name":"GenericAgentCoreRuntime","arn":"", + "{"name":"GenUAgentCoreRuntime","arn":"", { - "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7AgentCoreRuntimeArn010E372F", + "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803AgentRuntimeArn53FA08A2", }, ""}", ], @@ -26474,8 +26576,8 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "AgentEnabled": { "Value": "true", }, - "AgentNames": { - "Value": "WyJTZWFyY2hFbmdpbmUiLCJDb2RlSW50ZXJwcmV0ZXIiXQ==", + "Agents": { + "Value": "W3siZGlzcGxheU5hbWUiOiJTZWFyY2hFbmdpbmUiLCJkZXNjcmlwdGlvbiI6IkFnZW50IHdpdGggV2ViIFNlYXJjaCBGdW5jdGlvbmFsaXR5In0seyJkaXNwbGF5TmFtZSI6IkNvZGVJbnRlcnByZXRlciIsImRlc2NyaXB0aW9uIjoiQWdlbnQgd2l0aCBDb2RlIEludGVycHJldGVyIEZ1bmN0aW9uYWxpdHkifV0=", }, "ApiEndpoint": { "Value": { @@ -26560,6 +26662,9 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "McpEndpoint": { "Value": "", }, + "McpServersConfig": { + "Value": "{"time":{"metadata":{"category":"Utility","description":"Provides current time and date functionality"}},"aws-knowledge-mcp-server":{"metadata":{"category":"AWS","description":"AWS Knowledge Base MCP server for enterprise knowledge access"}},"awslabs.aws-documentation-mcp-server":{"metadata":{"category":"AWS","description":"Access AWS documentation and guides"}},"awslabs.cdk-mcp-server":{"metadata":{"category":"AWS","description":"AWS CDK code generation and assistance"}},"awslabs.aws-diagram-mcp-server":{"metadata":{"category":"AWS","description":"Generate AWS architecture diagrams"}},"awslabs.nova-canvas-mcp-server":{"metadata":{"category":"AI/ML","description":"Amazon Nova Canvas image generation"}},"tavily-search":{"metadata":{"category":"Search","description":"Web search and research capabilities powered by Tavily"}}}", + }, "ModelIds": { "Value": { "Fn::Join": [ @@ -26777,11 +26882,18 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::IAM::Role", "UpdateReplacePolicy": "Delete", }, - "APIApiDeployment3A502123f0975eea7d864770e54fb622c5a1b52e": { + "APIApiDeployment3A502123c1c381eebb266bc52e27b7e87659ddd8": { "DeletionPolicy": "Delete", "DependsOn": [ "APIApiApi4XXDCF913C8", "APIApiApi5XX11B67643", + "APIApiagentsproxyANY44A4A08E", + "APIApiagentsproxyOPTIONS65C845F9", + "APIApiagentsproxy440913A2", + "APIApiagentsGETFE9F47E4", + "APIApiagentsOPTIONS064D2F41", + "APIApiagentsPOST28B48D5F", + "APIApiagents70FB378D", "APIApichatschatIdDELETE4578D41B", "APIApichatschatIdfeedbacksOPTIONS7AB34AA5", "APIApichatschatIdfeedbacksPOST3E9ACBEC", @@ -26933,7 +27045,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` ], "Properties": { "DeploymentId": { - "Ref": "APIApiDeployment3A502123f0975eea7d864770e54fb622c5a1b52e", + "Ref": "APIApiDeployment3A502123c1c381eebb266bc52e27b7e87659ddd8", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -26996,7 +27108,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatsE061702A": { + "APIApiagents70FB378D": { "DeletionPolicy": "Delete", "Properties": { "ParentId": { @@ -27005,7 +27117,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "RootResourceId", ], }, - "PathPart": "chats", + "PathPart": "agents", "RestApiId": { "Ref": "APIApiFFA96F67", }, @@ -27013,54 +27125,13 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::ApiGateway::Resource", "UpdateReplacePolicy": "Delete", }, - "APIApichatsGET40767623": { - "DeletionPolicy": "Delete", - "Properties": { - "AuthorizationType": "COGNITO_USER_POOLS", - "AuthorizerId": { - "Ref": "APIAuthorizer9DCC037B", - }, - "HttpMethod": "GET", - "Integration": { - "IntegrationHttpMethod": "POST", - "Type": "AWS_PROXY", - "Uri": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", - { - "Fn::GetAtt": [ - "APIListChats12807275", - "Arn", - ], - }, - "/invocations", - ], - ], - }, - }, - "ResourceId": { - "Ref": "APIApichatsE061702A", - }, - "RestApiId": { - "Ref": "APIApiFFA96F67", - }, - }, - "Type": "AWS::ApiGateway::Method", - "UpdateReplacePolicy": "Delete", - }, - "APIApichatsGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETchats3464EF3A": { + "APIApiagentsGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETagents5FFFAEBF": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIListChats12807275", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -27081,7 +27152,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/GET/chats", + "/GET/agents", ], ], }, @@ -27089,13 +27160,13 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatsGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETchatsE1DE3C5A": { + "APIApiagentsGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETagents2809AEEE": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIListChats12807275", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -27112,7 +27183,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/GET/chats", + "/test-invoke-stage/GET/agents", ], ], }, @@ -27120,7 +27191,48 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatsOPTIONSDFF708CB": { + "APIApiagentsGETFE9F47E4": { + "DeletionPolicy": "Delete", + "Properties": { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": { + "Ref": "UseCaseBuilderAuthorizer8C07733E", + }, + "HttpMethod": "GET", + "Integration": { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", + { + "Fn::GetAtt": [ + "UseCaseBuilderAgentBuilderDAB96216", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": { + "Ref": "APIApiagents70FB378D", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApiagentsOPTIONS064D2F41": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -27153,7 +27265,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` }, ], "ResourceId": { - "Ref": "APIApichatsE061702A", + "Ref": "APIApiagents70FB378D", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -27162,78 +27274,12 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatsPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTchats6FB5CEC9": { - "DeletionPolicy": "Delete", - "Properties": { - "Action": "lambda:InvokeFunction", - "FunctionName": { - "Fn::GetAtt": [ - "APICreateChatE07AFAF4", - "Arn", - ], - }, - "Principal": "apigateway.amazonaws.com", - "SourceArn": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":execute-api:us-east-1:123456890123:", - { - "Ref": "APIApiFFA96F67", - }, - "/", - { - "Ref": "APIApiDeploymentStageapiCD55D117", - }, - "/POST/chats", - ], - ], - }, - }, - "Type": "AWS::Lambda::Permission", - "UpdateReplacePolicy": "Delete", - }, - "APIApichatsPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTchatsE0E202B2": { - "DeletionPolicy": "Delete", - "Properties": { - "Action": "lambda:InvokeFunction", - "FunctionName": { - "Fn::GetAtt": [ - "APICreateChatE07AFAF4", - "Arn", - ], - }, - "Principal": "apigateway.amazonaws.com", - "SourceArn": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":execute-api:us-east-1:123456890123:", - { - "Ref": "APIApiFFA96F67", - }, - "/test-invoke-stage/POST/chats", - ], - ], - }, - }, - "Type": "AWS::Lambda::Permission", - "UpdateReplacePolicy": "Delete", - }, - "APIApichatsPOSTF32299AA": { + "APIApiagentsPOST28B48D5F": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", "AuthorizerId": { - "Ref": "APIAuthorizer9DCC037B", + "Ref": "UseCaseBuilderAuthorizer8C07733E", }, "HttpMethod": "POST", "Integration": { @@ -27250,7 +27296,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APICreateChatE07AFAF4", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -27260,7 +27306,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` }, }, "ResourceId": { - "Ref": "APIApichatsE061702A", + "Ref": "APIApiagents70FB378D", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -27269,54 +27315,13 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdDELETE4578D41B": { - "DeletionPolicy": "Delete", - "Properties": { - "AuthorizationType": "COGNITO_USER_POOLS", - "AuthorizerId": { - "Ref": "APIAuthorizer9DCC037B", - }, - "HttpMethod": "DELETE", - "Integration": { - "IntegrationHttpMethod": "POST", - "Type": "AWS_PROXY", - "Uri": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", - { - "Fn::GetAtt": [ - "APIDeleteChat1517278C", - "Arn", - ], - }, - "/invocations", - ], - ], - }, - }, - "ResourceId": { - "Ref": "APIApichatschatIdE67019A6", - }, - "RestApiId": { - "Ref": "APIApiFFA96F67", - }, - }, - "Type": "AWS::ApiGateway::Method", - "UpdateReplacePolicy": "Delete", - }, - "APIApichatschatIdDELETEApiPermissionGenerativeAiUseCasesStackAPIApi89219E17DELETEchatschatIdCBAD7732": { + "APIApiagentsPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTagentsBB862BB1": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIDeleteChat1517278C", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -27337,7 +27342,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/DELETE/chats/*", + "/POST/agents", ], ], }, @@ -27345,13 +27350,13 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdDELETEApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17DELETEchatschatId6DBAD3C3": { + "APIApiagentsPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTagents9F230B2C": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIDeleteChat1517278C", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -27368,7 +27373,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/DELETE/chats/*", + "/test-invoke-stage/POST/agents", ], ], }, @@ -27376,13 +27381,13 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdE67019A6": { + "APIApiagentsproxy440913A2": { "DeletionPolicy": "Delete", "Properties": { "ParentId": { - "Ref": "APIApichatsE061702A", + "Ref": "APIApiagents70FB378D", }, - "PathPart": "{chatId}", + "PathPart": "{proxy+}", "RestApiId": { "Ref": "APIApiFFA96F67", }, @@ -27390,14 +27395,14 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::ApiGateway::Resource", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdGET152C9123": { + "APIApiagentsproxyANY44A4A08E": { "DeletionPolicy": "Delete", "Properties": { "AuthorizationType": "COGNITO_USER_POOLS", "AuthorizerId": { - "Ref": "APIAuthorizer9DCC037B", + "Ref": "UseCaseBuilderAuthorizer8C07733E", }, - "HttpMethod": "GET", + "HttpMethod": "ANY", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -27412,7 +27417,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ - "APIFindChatbyId74476825", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -27422,7 +27427,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` }, }, "ResourceId": { - "Ref": "APIApichatschatIdE67019A6", + "Ref": "APIApiagentsproxy440913A2", }, "RestApiId": { "Ref": "APIApiFFA96F67", @@ -27431,13 +27436,13 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::ApiGateway::Method", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdC82A138E": { + "APIApiagentsproxyANYApiPermissionGenerativeAiUseCasesStackAPIApi89219E17ANYagentsproxyB1492E94": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIFindChatbyId74476825", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -27458,7 +27463,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` { "Ref": "APIApiDeploymentStageapiCD55D117", }, - "/GET/chats/*", + "/*/agents/*", ], ], }, @@ -27466,13 +27471,13 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdCA130D83": { + "APIApiagentsproxyANYApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17ANYagentsproxy619296F3": { "DeletionPolicy": "Delete", "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ - "APIFindChatbyId74476825", + "UseCaseBuilderAgentBuilderDAB96216", "Arn", ], }, @@ -27489,7 +27494,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` { "Ref": "APIApiFFA96F67", }, - "/test-invoke-stage/GET/chats/*", + "/test-invoke-stage/*/agents/*", ], ], }, @@ -27497,7 +27502,550 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::Lambda::Permission", "UpdateReplacePolicy": "Delete", }, - "APIApichatschatIdOPTIONS4498230E": { + "APIApiagentsproxyOPTIONS65C845F9": { + "DeletionPolicy": "Delete", + "Properties": { + "ApiKeyRequired": false, + "AuthorizationType": "NONE", + "HttpMethod": "OPTIONS", + "Integration": { + "IntegrationResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", + "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'", + "method.response.header.Access-Control-Allow-Origin": "'*'", + }, + "StatusCode": "204", + }, + ], + "RequestTemplates": { + "application/json": "{ statusCode: 200 }", + }, + "Type": "MOCK", + }, + "MethodResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": true, + "method.response.header.Access-Control-Allow-Methods": true, + "method.response.header.Access-Control-Allow-Origin": true, + }, + "StatusCode": "204", + }, + ], + "ResourceId": { + "Ref": "APIApiagentsproxy440913A2", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatsE061702A": { + "DeletionPolicy": "Delete", + "Properties": { + "ParentId": { + "Fn::GetAtt": [ + "APIApiFFA96F67", + "RootResourceId", + ], + }, + "PathPart": "chats", + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Resource", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatsGET40767623": { + "DeletionPolicy": "Delete", + "Properties": { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": { + "Ref": "APIAuthorizer9DCC037B", + }, + "HttpMethod": "GET", + "Integration": { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", + { + "Fn::GetAtt": [ + "APIListChats12807275", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": { + "Ref": "APIApichatsE061702A", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatsGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETchats3464EF3A": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APIListChats12807275", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/", + { + "Ref": "APIApiDeploymentStageapiCD55D117", + }, + "/GET/chats", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatsGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETchatsE1DE3C5A": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APIListChats12807275", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/test-invoke-stage/GET/chats", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatsOPTIONSDFF708CB": { + "DeletionPolicy": "Delete", + "Properties": { + "ApiKeyRequired": false, + "AuthorizationType": "NONE", + "HttpMethod": "OPTIONS", + "Integration": { + "IntegrationResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", + "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'", + "method.response.header.Access-Control-Allow-Origin": "'*'", + }, + "StatusCode": "204", + }, + ], + "RequestTemplates": { + "application/json": "{ statusCode: 200 }", + }, + "Type": "MOCK", + }, + "MethodResponses": [ + { + "ResponseParameters": { + "method.response.header.Access-Control-Allow-Headers": true, + "method.response.header.Access-Control-Allow-Methods": true, + "method.response.header.Access-Control-Allow-Origin": true, + }, + "StatusCode": "204", + }, + ], + "ResourceId": { + "Ref": "APIApichatsE061702A", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatsPOSTApiPermissionGenerativeAiUseCasesStackAPIApi89219E17POSTchats6FB5CEC9": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APICreateChatE07AFAF4", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/", + { + "Ref": "APIApiDeploymentStageapiCD55D117", + }, + "/POST/chats", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatsPOSTApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17POSTchatsE0E202B2": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APICreateChatE07AFAF4", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/test-invoke-stage/POST/chats", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatsPOSTF32299AA": { + "DeletionPolicy": "Delete", + "Properties": { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": { + "Ref": "APIAuthorizer9DCC037B", + }, + "HttpMethod": "POST", + "Integration": { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", + { + "Fn::GetAtt": [ + "APICreateChatE07AFAF4", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": { + "Ref": "APIApichatsE061702A", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatschatIdDELETE4578D41B": { + "DeletionPolicy": "Delete", + "Properties": { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": { + "Ref": "APIAuthorizer9DCC037B", + }, + "HttpMethod": "DELETE", + "Integration": { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", + { + "Fn::GetAtt": [ + "APIDeleteChat1517278C", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": { + "Ref": "APIApichatschatIdE67019A6", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatschatIdDELETEApiPermissionGenerativeAiUseCasesStackAPIApi89219E17DELETEchatschatIdCBAD7732": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APIDeleteChat1517278C", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/", + { + "Ref": "APIApiDeploymentStageapiCD55D117", + }, + "/DELETE/chats/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatschatIdDELETEApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17DELETEchatschatId6DBAD3C3": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APIDeleteChat1517278C", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/test-invoke-stage/DELETE/chats/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatschatIdE67019A6": { + "DeletionPolicy": "Delete", + "Properties": { + "ParentId": { + "Ref": "APIApichatsE061702A", + }, + "PathPart": "{chatId}", + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Resource", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatschatIdGET152C9123": { + "DeletionPolicy": "Delete", + "Properties": { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": { + "Ref": "APIAuthorizer9DCC037B", + }, + "HttpMethod": "GET", + "Integration": { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":apigateway:us-east-1:lambda:path/2015-03-31/functions/", + { + "Fn::GetAtt": [ + "APIFindChatbyId74476825", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": { + "Ref": "APIApichatschatIdE67019A6", + }, + "RestApiId": { + "Ref": "APIApiFFA96F67", + }, + }, + "Type": "AWS::ApiGateway::Method", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatschatIdGETApiPermissionGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdC82A138E": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APIFindChatbyId74476825", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/", + { + "Ref": "APIApiDeploymentStageapiCD55D117", + }, + "/GET/chats/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatschatIdGETApiPermissionTestGenerativeAiUseCasesStackAPIApi89219E17GETchatschatIdCA130D83": { + "DeletionPolicy": "Delete", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "APIFindChatbyId74476825", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":execute-api:us-east-1:123456890123:", + { + "Ref": "APIApiFFA96F67", + }, + "/test-invoke-stage/GET/chats/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + "UpdateReplacePolicy": "Delete", + }, + "APIApichatschatIdOPTIONS4498230E": { "DeletionPolicy": "Delete", "Properties": { "ApiKeyRequired": false, @@ -38505,7 +39053,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "", [ { - "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7AgentCoreRuntimeArn010E372F", + "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803AgentRuntimeArn53FA08A2", }, "*", ], @@ -38544,22 +39092,22 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "destinationBucketName": "cdk-hnb659fds-assets-123456890123-us-east-1", "environment": { "NODE_OPTIONS": "--max-old-space-size=4096", + "VITE_APP_AGENTS": "[{"displayName":"SearchEngine","description":"Agent with Web Search Functionality"},{"displayName":"CodeInterpreter","description":"Agent with Code Interpreter Functionality"}]", "VITE_APP_AGENT_CORE_ENABLED": "true", "VITE_APP_AGENT_CORE_EXTERNAL_RUNTIMES": "[]", "VITE_APP_AGENT_CORE_GENERIC_RUNTIME": { "Fn::Join": [ "", [ - "{"name":"GenericAgentCoreRuntime","arn":"", + "{"name":"GenUAgentCoreRuntime","arn":"", { - "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeD3EBAAF7AgentCoreRuntimeArn010E372F", + "Fn::ImportValue": "AgentCoreStack:ExportsOutputFnGetAttGenericAgentCoreGenericAgentCoreRuntimeL1B2F7F803AgentRuntimeArn53FA08A2", }, - ""}", + "","description":"Generic Agent Core Runtime for custom agents"}", ], ], }, "VITE_APP_AGENT_ENABLED": "true", - "VITE_APP_AGENT_NAMES": "["SearchEngine","CodeInterpreter"]", "VITE_APP_API_ENDPOINT": { "Fn::Join": [ "", @@ -38609,6 +39157,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "VITE_APP_INLINE_AGENTS": "false", "VITE_APP_MCP_ENABLED": "false", "VITE_APP_MCP_ENDPOINT": "", + "VITE_APP_MCP_SERVERS_CONFIG": "{"time":{"metadata":{"category":"Utility","description":"Provides current time and date functionality"}},"aws-knowledge-mcp-server":{"metadata":{"category":"AWS","description":"AWS Knowledge Base MCP server for enterprise knowledge access"}},"awslabs.aws-documentation-mcp-server":{"metadata":{"category":"AWS","description":"Access AWS documentation and guides"}},"awslabs.cdk-mcp-server":{"metadata":{"category":"AWS","description":"AWS CDK code generation and assistance"}},"awslabs.aws-diagram-mcp-server":{"metadata":{"category":"AWS","description":"Generate AWS architecture diagrams"}},"awslabs.nova-canvas-mcp-server":{"metadata":{"category":"AI/ML","description":"Amazon Nova Canvas image generation"}},"tavily-search":{"metadata":{"category":"Search","description":"Web search and research capabilities powered by Tavily"}}}", "VITE_APP_MODEL_IDS": { "Fn::Join": [ "", @@ -38750,6 +39299,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` ], }, ], + "WaitForDistributionInvalidation": true, }, "Type": "Custom::CDKBucketDeployment", "UpdateReplacePolicy": "Delete", @@ -40345,7 +40895,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Arn", ], }, - "Runtime": "python3.11", + "Runtime": "python3.13", "Timeout": 900, }, "Type": "AWS::Lambda::Function", @@ -40502,7 +41052,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Arn", ], }, - "Runtime": "python3.11", + "Runtime": "python3.13", "Timeout": 900, }, "Type": "AWS::Lambda::Function", @@ -41292,6 +41842,7 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "SourceObjectKeys": [ "HASH-REPLACED.zip", ], + "WaitForDistributionInvalidation": true, }, "Type": "Custom::CDKBucketDeployment", "UpdateReplacePolicy": "Delete", @@ -42846,6 +43397,151 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = ` "Type": "AWS::S3::BucketPolicy", "UpdateReplacePolicy": "Delete", }, + "UseCaseBuilderAgentBuilderDAB96216": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "UseCaseBuilderAgentBuilderServiceRoleDefaultPolicy55D3FBBC", + "UseCaseBuilderAgentBuilderServiceRole9C6C40B9", + ], + "Properties": { + "Code": { + "S3Bucket": "cdk-hnb659fds-assets-123456890123-us-east-1", + "S3Key": "HASH-REPLACED.zip", + }, + "Environment": { + "Variables": { + "MODEL_REGION": "us-east-1", + "USECASE_ID_INDEX_NAME": "UseCaseIdIndexName", + "USECASE_TABLE_NAME": { + "Ref": "UseCaseBuilderUseCaseBuilderTable449740F3", + }, + "USER_POOL_ID": { + "Ref": "AuthUserPool8115E87F", + }, + }, + }, + "Handler": "index.handler", + "MemorySize": 1024, + "Role": { + "Fn::GetAtt": [ + "UseCaseBuilderAgentBuilderServiceRole9C6C40B9", + "Arn", + ], + }, + "Runtime": "nodejs22.x", + "Timeout": 900, + }, + "Type": "AWS::Lambda::Function", + "UpdateReplacePolicy": "Delete", + }, + "UseCaseBuilderAgentBuilderServiceRole9C6C40B9": { + "DeletionPolicy": "Delete", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + "UpdateReplacePolicy": "Delete", + }, + "UseCaseBuilderAgentBuilderServiceRoleDefaultPolicy55D3FBBC": { + "DeletionPolicy": "Delete", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:DescribeTable", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "UseCaseBuilderUseCaseBuilderTable449740F3", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "UseCaseBuilderUseCaseBuilderTable449740F3", + "Arn", + ], + }, + "/index/*", + ], + ], + }, + ], + }, + { + "Action": [ + "bedrock:*", + "logs:*", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": "cognito-idp:AdminGetUser", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "AuthUserPool8115E87F", + "Arn", + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "UseCaseBuilderAgentBuilderServiceRoleDefaultPolicy55D3FBBC", + "Roles": [ + { + "Ref": "UseCaseBuilderAgentBuilderServiceRole9C6C40B9", + }, + ], + }, + "Type": "AWS::IAM::Policy", + "UpdateReplacePolicy": "Delete", + }, "UseCaseBuilderAuthorizer8C07733E": { "DeletionPolicy": "Delete", "Properties": { diff --git a/packages/types/src/agent-builder.d.ts b/packages/types/src/agent-builder.d.ts new file mode 100644 index 000000000..5a36b8d79 --- /dev/null +++ b/packages/types/src/agent-builder.d.ts @@ -0,0 +1,189 @@ +import { UnrecordedMessage, Model } from './message'; + +// MCP Server Configuration (for internal use only) +export type MCPServerConfig = { + name: string; + command: string; + args: string[]; + env: Record; + enabled: boolean; + description?: string; +}; + +// MCP Server Reference (what users specify) +export type MCPServerReference = string; + +// Common items for all agent data +// Table: PartitionKey=id, SortKey=dataType +export type AgentCommon = { + id: string; // agent#{userId} + dataType: string; // agent#{agentId} + agentId: string; +}; + +// Agent content (request type for creating or updating Agent) +export type AgentContent = { + name: string; + description?: string; + systemPrompt: string; + mcpServers: MCPServerReference[]; // Changed to string array + modelId: string; + codeExecutionEnabled?: boolean; + tags?: string[]; + isPublic?: boolean; + createdByEmail?: string; +}; + +// Content recorded in Table +export type AgentInTable = AgentCommon & + AgentContent & { + description: string; // Required in table + codeExecutionEnabled: boolean; + isPublic: boolean; + tags: string[]; + starCount: number; // Number of users who favorited this agent + createdAt: string; + updatedAt: string; + createdBy: string; // User ID of the agent creator + }; + +// Content returned to Frontend +// isFavorite, isMyAgent are dynamically added +export type AgentAsOutput = AgentInTable & { + isFavorite?: boolean; + isMyAgent: boolean; + status?: 'available' | 'deleted' | 'private' | 'inaccessible'; +}; + +// Agent Configuration for API responses +export type AgentConfiguration = Omit & { + shareId?: string; + starCount: number; + createdBy: string; +}; + +// API Request Types +export type CreateAgentRequest = AgentContent; + +export type UpdateAgentRequest = CreateAgentRequest & { + agentId: string; +}; + +export type CloneAgentRequest = { + sourceAgentId: string; + name?: string; +}; + +// API Response Types +export type CreateAgentResponse = { + agent: AgentConfiguration; +}; + +export type UpdateAgentResponse = { + agent: AgentConfiguration; +}; + +export type DeleteAgentResponse = { + success: boolean; +}; + +export type CloneAgentResponse = { + success: boolean; + agent: AgentConfiguration; + missingDependencies?: string[]; + error?: string; +}; + +export type ListAgentsRequest = { + limit?: number; + nextToken?: string; + type?: 'my' | 'public' | 'favorites'; +}; + +export type ListAgentsResponse = { + agents: AgentConfiguration[]; + nextToken?: string; + totalCount?: number; + type: 'my' | 'public' | 'favorites'; + // For SWR Infinite compatibility + data?: AgentConfiguration[]; + lastEvaluatedKey?: string; +}; + +// Base agent response (common fields for sharing/importing) +export type BaseAgentResponse = { + agentId: string; + name: string; + description: string; + systemPrompt: string; + modelId: string; + mcpServers: MCPServerReference[]; // Changed to string array + codeExecutionEnabled: boolean; + tags: string[]; + isPublic: boolean; + createdAt: string; + updatedAt: string; +}; + +// Shared Agent Response (for getSharedAgent) +export type SharedAgentResponse = BaseAgentResponse & { + createdBy: string; + createdByEmail?: string; + isMyAgent: boolean; +}; + +// Clone Agent Response (for cloneAgent) +export type ClonedAgentResponse = BaseAgentResponse; + +// Public Agent Item (for listPublicAgents) +export type PublicAgentItem = SharedAgentResponse & { + isFavorite: boolean; +}; + +// Repository-specific response types +export type RepositoryListAgentsResponse = { + data: AgentAsOutput[]; + lastEvaluatedKey?: string; +}; + +export type ListFavoriteAgentsResponse = { + data: AgentAsOutput[]; + lastEvaluatedKey?: string; +}; + +// Validation types +export type ValidationResult = { + data?: T; + isValid: boolean; + error?: string; +}; + +// Extended types with additional fields +export type AgentWithFavorite = AgentConfiguration & { + isFavorite: boolean; + isMyAgent: boolean; +}; + +// Agent Builder State Types +export type AgentBuilderState = { + agents: AgentConfiguration[]; + currentAgent?: AgentConfiguration; + loading: boolean; + error?: string; +}; + +// Agent Core Runtime Request Types +export type AgentCoreRuntimeRequest = { + agentRuntimeArn: string; + sessionId?: string; + qualifier?: string; + system_prompt?: string; // Keep this name for backward compatibility with useAgentCore + prompt: string; // User prompt as string + previousMessages?: UnrecordedMessage[]; // Raw messages that will be converted to Strands format + model: Model; + files?: File[]; // Added support for file uploads + userId?: string; // User ID for MCP server management + mcpServers?: MCPServerReference[]; // Changed to string array + agentId?: string; // Agent ID for logging/tracking + codeExecutionEnabled?: boolean; // Code execution setting +}; diff --git a/packages/types/src/agent-core.d.ts b/packages/types/src/agent-core.d.ts index 93126d0c1..6170a6df3 100644 --- a/packages/types/src/agent-core.d.ts +++ b/packages/types/src/agent-core.d.ts @@ -3,10 +3,15 @@ import { Model } from './message'; export type AgentCoreConfiguration = { name: string; arn: string; + description: string; }; -// AgentCore Runtime Request (compatible with Strands) -export type AgentCoreRequest = StrandsRequest; +// AgentCore Runtime Request (extended from Strands with additional fields) +export type AgentCoreRequest = StrandsRequest & { + mcp_servers?: string[]; // Changed to string array + session_id?: string; + code_execution_enabled?: boolean; +}; export type AgentCoreStreamResponse = StrandsStreamEvent; diff --git a/packages/types/src/index.d.ts b/packages/types/src/index.d.ts index 2279f8258..2798d6ae5 100644 --- a/packages/types/src/index.d.ts +++ b/packages/types/src/index.d.ts @@ -18,3 +18,5 @@ export * from './speech-to-speech'; export * from './stat'; export * from './mcp'; export * from './agent-core'; +export * from './agent-builder'; +export * from './mcp-servers'; diff --git a/packages/types/src/mcp-servers.d.ts b/packages/types/src/mcp-servers.d.ts new file mode 100644 index 000000000..b9ea43f17 --- /dev/null +++ b/packages/types/src/mcp-servers.d.ts @@ -0,0 +1,7 @@ +export interface AvailableMCPServer { + name: string; + description: string; + category: string; +} + +export type AvailableMCPServers = AvailableMCPServer[]; diff --git a/packages/types/src/message.d.ts b/packages/types/src/message.d.ts index 5d3c219f3..88148e20e 100644 --- a/packages/types/src/message.d.ts +++ b/packages/types/src/message.d.ts @@ -13,8 +13,12 @@ export type Model = { inferenceProfileArn?: string; }; -export type Agent = { +export type AgentInfo = { displayName: string; + description: string; +}; + +export type Agent = AgentInfo & { agentId: string; aliasId: string; }; diff --git a/packages/web/public/locales/translation/en.yaml b/packages/web/public/locales/translation/en.yaml index cfacd0d13..70739274b 100644 --- a/packages/web/public/locales/translation/en.yaml +++ b/packages/web/public/locales/translation/en.yaml @@ -1,11 +1,119 @@ agent: drop_files: Drop files to upload title: Agent Chat +agent_builder: + add_agents_to_favorites_description: Add agents to your favorites to see them here + add_mcp_server: Add MCP Server + add_mcp_server_button: Add MCP Server + add_mcp_servers_help: Click "Add MCP Server" to add tools and capabilities to your agent + add_new_mcp_server: Add New MCP Server + agent_chat: Agent Chat + agent_cloned_successfully: Agent "{{name}}" cloned successfully! + agent_created_successfully: Agent created successfully + agent_deleted_successfully: Agent deleted successfully + agent_not_found: Agent Not Found + agent_updated_successfully: Agent updated successfully + all_categories: All + arguments: Arguments + arguments_help: Package name or command arguments (space-separated) + arguments_label: Arguments + arguments_placeholder: package-name arg1 arg2 + basic_information: Basic Information + bedrock_agent_description: Pre-configured Bedrock Agent with specialized capabilities + chat: chat + check_back_later_description: Check back later for new public agents + clone: Clone + code_execution: Code execution + code_execution_description: Allows this agent to run the code and run the scripts. + command: Command + command_help: Only 'uvx' command is allowed for security reasons + command_label: Command + command_placeholder: uvx + confirm_delete: Are you sure you want to delete this agent? + create_agent: Create Agent + create_first_agent_description: Create your first agent to get started + create_your_first_agent: Create Your First Agent + created_by: Created by + describe_agent: Please explain the functions of the agent + description: Description + description_label: Description + description_placeholder: Describe what your agent does... + edit_agent: Edit Agent + enable_code_execution: Enabling code execution + enter_agent_name: Enter the agent name + enter_system_prompt: Enter a system prompt that defines the agent behavior + enter_tags_comma_separated: Enter tags separated by commas + environment_help: JSON format environment variables (optional) + environment_variables: Environment Variables + environment_variables_label: Environment Variables + example_github: GitHub + external: External + external_agent_description: Pre-configured external agents with specialized capabilities + external_agents: External Agents + failed_to_clone_agent: Failed to clone agent + failed_to_create_agent: Failed to create agent + failed_to_delete_agent: Failed to delete agent + failed_to_load_agents: Failed to load agents + failed_to_toggle_favorite: Failed to toggle favorite + failed_to_update_agent: Failed to update agent + favorites: Favorites + filter_by_tag: Filter by tag + loading_agent: Loading agent... + marketplace: Marketplace + mcp_server_configuration: MCP Server Configuration + mcp_server_description: >- + Select MCP servers to enable additional capabilities for your agent. These + servers are pre-configured by administrators for security. + mcp_servers: MCP Servers + mcp_servers_description: Add MCP servers to provide tools and capabilities to your agent + model: Model + my_agents: My Agents + name: Name + no_agents_yet: No agents yet + no_external_agents_available: No external agents available + no_favorite_agents_yet: No favorite agents yet + no_mcp_servers: No MCP servers configured + no_mcp_servers_available: No MCP servers are currently available. + no_mcp_servers_match_filter: No MCP servers match your current filter. + no_mcp_servers_selected: No MCP servers selected. Your agent will have basic functionality only. + no_public_agents_available: No public agents available + public_sharing_description: >- + Make this agent available on public marketplaces and be discovered and + available to others. + + The agent is visible to all users, but you cannot modify the original. + quick_examples: Quick Examples + quick_examples_title: Quick Examples + search_agents: Search agents... + search_mcp_servers: Search MCP servers... + security_notice: Security Notice + security_notice_description: >- + Only uvx command is allowed. External network access is restricted for + security. + security_restrictions: >- + Only uvx command is allowed. External network access is restricted for + security. + separate_tags_with_commas: Separate multiple tags with commas + server_configuration: Server Configuration + server_description_placeholder: Brief description of what this server provides... + server_name: Server Name + server_name_label: Server Name + server_name_placeholder: e.g., github-mcp-server + share_publicly: Share publicly + showing_results: Showing {{start}}-{{end}} of {{total}} results + start_chatting_with: Start chatting with {{name}} + system_prompt: System Prompt + tags: Tags + test: Test + title: Agent Builder + tool_settings: Tool Settings + updated: Updated date agent_core: model: Model runtime: Runtime start_conversation: Start a conversation with AgentCore title: AgentCore +agent_dashboard: {} auth: loading: Loading... login: Login @@ -40,7 +148,9 @@ chat: title: Chat view_prompt_examples: View Prompt Examples common: + add: Add arrow: → + back: Back cancel: Cancel clear: Clear close: Close @@ -48,7 +158,13 @@ common: colon: ':' complete: Complete create: Create + default: Default delete: Delete + disable: Disable + disabled: Disabled + edit: Edit + enable: Enable + enabled: Enabled enter_text: Enter text error: An error occurred errorNoSuggestions: No suggestions were found. @@ -56,10 +172,14 @@ common: expand: Expand export: Export feedback_received: Feedback received. Thank you. + first_page: First page + form: Form here: here + last_page: Last page load_more: Load more loading: Loading... next: Next + next_page: Next page no_options_found: No options found none: None notAuthenticated: You are not authenticated. @@ -68,6 +188,8 @@ common: optional: Optional other: Other previous: Previous + previous_page: Previous page + remove: Remove required: Required reviewComplete: Review completed save: Save @@ -77,6 +199,7 @@ common: title: Title trace: Trace try: Try + update: Update demo: inter_use_cases: Use Case Integration diagram: @@ -546,7 +669,9 @@ landing: Amazon Bedrock. title: Agent Chat agent_core: - description: AgentCore Chat is a feature that utilizes various Agents created with Bedrock AgentCore. + description: >- + AgentCore Chat is a feature that utilizes various Agents created with + Bedrock AgentCore. title: AgentCore chat: description: >- @@ -888,7 +1013,10 @@ transcribe: result_placeholder: Speech recognition results will be displayed here screen_audio: Screen Audio screen_audio_error: Screen Audio Error - screen_audio_notice: 'For Windows: Select "Entire Screen" tab and turn ON "Share system audio".
For Mac: Select "Chrome Tab" and turn ON "Also share tab audio".
Chrome and Edge work. Firefox does not work.' + screen_audio_notice: >- + For Windows: Select "Entire Screen" tab and turn ON "Share system + audio".
For Mac: Select "Chrome Tab" and turn ON "Also share tab + audio".
Chrome and Edge work. Firefox does not work. select_input_method: Please select from microphone input or file upload speaker_names: Speaker names (comma separated) speaker_recognition: Speaker recognition @@ -902,7 +1030,9 @@ translate: additional_context_placeholder: You can enter additional points to consider (e.g., casualness, etc.) auto_detect_language: Auto detect language auto_translate: Auto translate - contextHelp: Context information helps improve translation accuracy by providing background information about the meeting. + contextHelp: >- + Context information helps improve translation accuracy by providing + background information about the meeting. continue_output: Continue output detectedLanguage: Detected Language enter_text: Enter text @@ -916,7 +1046,9 @@ translate: translating: Translating... translation: Translation userDefinedContext: User-defined Context - userDefinedContextPlaceholder: 'Enter context to improve translation accuracy (e.g., meeting topic, technical terms, etc.)' + userDefinedContextPlaceholder: >- + Enter context to improve translation accuracy (e.g., meeting topic, + technical terms, etc.) useCaseBuilder: accessError: Access Error addInputExample: Add Input Example diff --git a/packages/web/public/locales/translation/ja.yaml b/packages/web/public/locales/translation/ja.yaml index c62a4716a..2a0cdb0d2 100644 --- a/packages/web/public/locales/translation/ja.yaml +++ b/packages/web/public/locales/translation/ja.yaml @@ -1,11 +1,110 @@ agent: drop_files: ファイルをドロップしてアップロード title: Agent チャット +agent_builder: + add_agents_to_favorites_description: マーケットプレイスからエージェントをお気に入りに追加 + add_mcp_server: MCPサーバーを追加 + add_mcp_server_button: MCPサーバーを追加 + add_mcp_servers_help: 「MCPサーバーを追加」をクリックして、エージェントにツールと機能を追加します + add_new_mcp_server: 新しいMCPサーバーを追加 + agent_chat: エージェントチャット + agent_cloned_successfully: エージェント「{{name}}」が正常にクローンされました! + agent_created_successfully: エージェントが正常に作成されました + agent_deleted_successfully: エージェントが正常に削除されました + agent_not_found: エージェントが見つかりません + agent_updated_successfully: エージェントが正常に更新されました + all_categories: すべて + arguments: 引数 + arguments_help: パッケージ名またはコマンド引数(スペース区切り) + arguments_label: 引数 + arguments_placeholder: パッケージ名 引数1 引数2 + basic_information: 基本情報 + bedrock_agent_description: 特別な機能を持つ事前設定済みのBedrockエージェント + chat: チャット + check_back_later_description: 公開エージェントについては後でもう一度確認してください + clone: クローン + code_execution: コード実行 + code_execution_description: >- + このエージェントがコードを実行し、スクリプトを実行できるようにします。 + command: コマンド + command_help: セキュリティ上の理由により、'uvx'コマンドのみ許可されています + command_label: コマンド + command_placeholder: uvx + confirm_delete: このエージェントを削除してもよろしいですか? + create_agent: エージェントを作成 + create_first_agent_description: 最初のエージェントを作成して始めましょう + create_your_first_agent: 最初のエージェントを作成 + created_by: 作成者 + describe_agent: エージェントの機能を説明してください + description: 説明 + description_label: 説明 + description_placeholder: エージェントの機能を説明してください... + edit_agent: エージェントを編集 + enable_code_execution: コード実行を有効にする + enter_agent_name: エージェント名を入力 + enter_system_prompt: エージェントの動作を定義するシステムプロンプトを入力 + enter_tags_comma_separated: タグをカンマ区切りで入力 + environment_help: JSON形式の環境変数(オプション) + environment_variables: 環境変数 + environment_variables_label: 環境変数 + example_github: GitHub + external: 外部 + external_agent_description: 特別な機能を持つ事前設定済みの外部エージェント + external_agents: 外部エージェント + failed_to_clone_agent: エージェントのクローンに失敗しました + failed_to_create_agent: エージェントの作成に失敗しました + failed_to_delete_agent: エージェントの削除に失敗しました + failed_to_toggle_favorite: お気に入りの切り替えに失敗しました + failed_to_update_agent: エージェントの更新に失敗しました + favorites: お気に入り + filter_by_tag: タグでフィルター + loading_agent: エージェントを読み込み中... + marketplace: マーケットプレイス + mcp_server_configuration: MCPサーバー設定 + mcp_server_description: エージェントに追加機能を提供するMCPサーバーを選択してください。これらのサーバーはセキュリティのため管理者によって事前設定されています。 + mcp_servers: MCPサーバー + mcp_servers_description: MCPサーバーを追加して、エージェントにツールと機能を提供します + model: モデル + my_agents: マイエージェント + name: 名前 + no_agents_yet: まだエージェントがありません + no_external_agents_available: 利用可能な外部エージェントがありません + no_favorite_agents_yet: まだお気に入りのエージェントがありません + no_mcp_servers: MCPサーバーが設定されていません + no_mcp_servers_available: 現在利用可能なMCPサーバーがありません。 + no_mcp_servers_match_filter: 現在のフィルターに一致するMCPサーバーがありません。 + no_mcp_servers_selected: MCPサーバーが選択されていません。エージェントは基本機能のみ利用できます。 + no_public_agents_available: 利用可能な公開エージェントがありません + public_sharing_description: >- + このエージェントを公開マーケットプレイスで利用可能にし、他のユーザーが発見して利用できるようにします。エージェントはすべてのユーザーに表示されますが、オリジナルを変更することはできません。 + quick_examples: クイック例 + quick_examples_title: クイック例 + search_agents: エージェントを検索... + search_mcp_servers: MCPサーバーを検索... + security_notice: セキュリティ通知 + security_notice_description: uvxコマンドのみ許可されています。セキュリティのため外部ネットワークアクセスは制限されています。 + security_restrictions: uvxコマンドのみ許可されています。セキュリティのため外部ネットワークアクセスは制限されています。 + separate_tags_with_commas: 複数のタグはカンマで区切ってください + server_configuration: サーバー設定 + server_description_placeholder: このサーバーが提供する機能の簡単な説明... + server_name: サーバー名 + server_name_label: サーバー名 + server_name_placeholder: 例:github-mcp-server + share_publicly: 公開で共有 + showing_results: '{{total}}件中 {{start}}-{{end}}件を表示' + start_chatting_with: '{{name}}とのチャットを開始' + system_prompt: システムプロンプト + tags: タグ + test: テスト + title: エージェントビルダー + tool_settings: ツール設定 + updated: 更新日 agent_core: model: モデル runtime: ランタイム start_conversation: AgentCore と会話を始める title: AgentCore +agent_dashboard: {} auth: loading: 読み込み中... login: ログイン @@ -38,7 +137,9 @@ chat: title: チャット view_prompt_examples: プロンプト例を見る common: + add: 追加 arrow: → + back: 戻る cancel: キャンセル clear: クリア close: 閉じる @@ -46,7 +147,13 @@ common: colon: ':' complete: 完了 create: 作成 + default: デフォルト delete: 削除 + disable: 無効化 + disabled: 無効 + edit: 編集 + enable: 有効化 + enabled: 有効 enter_text: 入力してください error: エラー errorNoSuggestions: 候補が見つかりませんでした。 @@ -54,10 +161,14 @@ common: expand: 展開 export: エクスポート feedback_received: フィードバックを受け付けました。ありがとうございます。 + first_page: 最初のページ + form: フォーム here: こちら + last_page: 最後のページ load_more: さらに読み込む loading: 読み込み中... next: 次 + next_page: 次のページ no_options_found: オプションが見つかりません none: ありません notAuthenticated: 認証されていません。 @@ -66,6 +177,8 @@ common: optional: 任意 other: その他 previous: 前 + previous_page: 前のページ + remove: 削除 required: 必須 reviewComplete: レビュー完了 save: 保存 @@ -75,6 +188,7 @@ common: title: タイトル trace: トレース try: 試す + update: 更新 demo: inter_use_cases: ユースケース連携 diagram: diff --git a/packages/web/src/App.tsx b/packages/web/src/App.tsx index 3967c1515..15daa0193 100644 --- a/packages/web/src/App.tsx +++ b/packages/web/src/App.tsx @@ -46,12 +46,15 @@ const inlineAgents: boolean = import.meta.env.VITE_APP_INLINE_AGENTS === 'true'; const mcpEnabled: boolean = import.meta.env.VITE_APP_MCP_ENABLED === 'true'; const agentCoreEnabled: boolean = import.meta.env.VITE_APP_AGENT_CORE_ENABLED === 'true'; +const agentCoreGenericRuntimeEnabled: boolean = + import.meta.env.VITE_APP_AGENT_CORE_GENERIC_RUNTIME !== 'null'; + const { visionEnabled, imageGenModelIds, videoGenModelIds, speechToSpeechModelIds, - agentNames, + agents, flowChatEnabled, } = MODELS; @@ -120,10 +123,10 @@ const App: React.FC = () => { } : null, ...(agentEnabled && inlineAgents - ? agentNames.map((name: string) => { + ? agents.map((agent) => { return { - label: name, - to: `/agent/${name}`, + label: agent.displayName, + to: `/agent/${agent.displayName}`, icon: , display: 'usecase' as const, sub: 'Agent', @@ -139,7 +142,17 @@ const App: React.FC = () => { sub: 'Deprecated', } : null, - agentCoreEnabled + agentCoreGenericRuntimeEnabled + ? { + label: 'Agent Builder', + to: '/agent-builder', + icon: , + display: 'usecase' as const, + sub: 'Experimental', + } + : null, + // Do not show AgentCore in the drawer if Agent Builder is enabled + agentCoreEnabled && !agentCoreGenericRuntimeEnabled ? { label: t('agent_core.title'), to: '/agent-core', diff --git a/packages/web/src/components/ChatMessage.tsx b/packages/web/src/components/ChatMessage.tsx index 5e902af91..0f928dd22 100644 --- a/packages/web/src/components/ChatMessage.tsx +++ b/packages/web/src/components/ChatMessage.tsx @@ -186,8 +186,8 @@ const ChatMessage: React.FC = (props) => {
{t('common.trace')} - {props.loading && !chatContent?.content && ( -
+ {props.loading && ( +
)}
@@ -277,18 +277,18 @@ const ChatMessage: React.FC = (props) => { {chatContent.metadata.usage.inputTokens} {chatContent.metadata.usage.outputTokens} - {chatContent.metadata.usage.cacheWriteInputTokens && ( + {chatContent.metadata.usage.cacheWriteInputTokens ? ( <> {chatContent.metadata.usage.cacheWriteInputTokens} - )} - {chatContent.metadata.usage.cacheReadInputTokens && ( + ) : null} + {chatContent.metadata.usage.cacheReadInputTokens ? ( <> {chatContent.metadata.usage.cacheReadInputTokens} - )} + ) : null}
)}
diff --git a/packages/web/src/components/InputChatContent.tsx b/packages/web/src/components/InputChatContent.tsx index 1a7249c9f..a5b7060ae 100644 --- a/packages/web/src/components/InputChatContent.tsx +++ b/packages/web/src/components/InputChatContent.tsx @@ -30,6 +30,7 @@ type Props = { fullWidth?: boolean; resetDisabled?: boolean; loading?: boolean; + isEmpty?: boolean; onChangeContent: (content: string) => void; onSend: () => void; sendIcon?: React.ReactNode; @@ -59,7 +60,7 @@ const InputChatContent: React.FC = (props) => { const { t } = useTranslation(); const { settingSubmitCmdOrCtrlEnter } = useUserSetting(); const { pathname } = useLocation(); - const { loading: chatLoading, isEmpty } = useChat(pathname); + const { loading: chatLoading, isEmpty: chatIsEmpty } = useChat(pathname); const { uploadedFiles, uploadFiles, @@ -276,16 +277,18 @@ const InputChatContent: React.FC = (props) => { - {!isEmpty && !props.resetDisabled && !props.hideReset && ( - - )} + {!(props.isEmpty ?? chatIsEmpty) && + !props.resetDisabled && + !props.hideReset && ( + + )} {/* Show keyboard shortcut hint when cmd/ctrl+enter setting is enabled */} diff --git a/packages/web/src/components/Select.tsx b/packages/web/src/components/Select.tsx index cd7ce5763..8a35e830b 100644 --- a/packages/web/src/components/Select.tsx +++ b/packages/web/src/components/Select.tsx @@ -18,6 +18,7 @@ type Props = RowItemProps & { fullWidth?: boolean; showColorChips?: boolean; showTags?: boolean; + placeholder?: string; onChange: (value: string) => void; }; @@ -103,14 +104,18 @@ const Select: React.FC = (props) => {
+ className={`relative cursor-pointer rounded border border-black/30 bg-white py-1.5 pl-3 pr-10 text-left focus:outline-none ${props.fullWidth ? 'w-full' : 'w-fit'}`}> - {props.value && ( + {props.value ? ( + ) : ( + + {props.placeholder || 'Select an option'} + )} diff --git a/packages/web/src/components/agentBuilder/AgentChatUnified.tsx b/packages/web/src/components/agentBuilder/AgentChatUnified.tsx new file mode 100644 index 000000000..f658c2169 --- /dev/null +++ b/packages/web/src/components/agentBuilder/AgentChatUnified.tsx @@ -0,0 +1,475 @@ +import React, { useState, useCallback, useEffect, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation } from 'react-router-dom'; +import { v4 as uuidv4 } from 'uuid'; +import InputChatContent from '../InputChatContent'; +import ChatMessage from '../ChatMessage'; +import ScrollTopBottom from '../ScrollTopBottom'; +import useFollow from '../../hooks/useFollow'; +import { useAgentCore } from '../../hooks/useAgentCore'; +import { MODELS } from '../../hooks/useModel'; +import useFiles from '../../hooks/useFiles'; +import { FileLimit, AgentConfiguration } from 'generative-ai-use-cases'; +import BedrockIcon from '../../assets/bedrock.svg?react'; +import { PiRobot as RobotIcon, PiPencil as EditIcon } from 'react-icons/pi'; +import ButtonIcon from '../ButtonIcon'; +import Select from '../Select'; + +// Define file limits for the chat interface +const fileLimit: FileLimit = { + accept: { + doc: [ + '.csv', + '.doc', + '.docx', + '.html', + '.md', + '.pdf', + '.txt', + '.xls', + '.xlsx', + '.yaml', + '.json', + ], + image: ['.jpg', '.jpeg', '.png', '.gif', '.webp'], + video: [], + }, + maxFileCount: 5, + maxFileSizeMB: 10, + maxImageFileCount: 5, + maxImageFileSizeMB: 5, + maxVideoFileCount: 0, + maxVideoFileSizeMB: 0, +}; + +interface AgentChatProps { + agent: AgentConfiguration; + sessionId?: string; + className?: string; + showHeader?: boolean; + layout?: 'fullscreen' | 'card'; + showAgentInfo?: boolean; + showEditButton?: boolean; + onEdit?: () => void; + onBack?: () => void; + actions?: React.ReactNode; +} + +const AgentChatUnified: React.FC = ({ + agent, + sessionId: providedSessionId, + className = '', + showHeader = true, + layout = 'fullscreen', + showAgentInfo = true, + showEditButton = false, + onEdit, + actions, +}) => { + const { t } = useTranslation(); + + // Generate session ID if not provided + const { pathname } = useLocation(); + const [sessionId] = useState(() => providedSessionId || uuidv4()); + const { scrollableContainer, setFollowing } = useFollow(); + + // AgentCore for chat functionality + const { + messages: chatMessages, + isEmpty: chatIsEmpty, + clear: clearChat, + loading: chatLoading, + invokeAgentRuntime, + getGenericRuntime, + updateSystemContext, + getModelId, + setModelId, + } = useAgentCore(pathname); + + const [chatContent, setChatContent] = useState(''); + const [initialized, setInitialized] = useState(false); + const [isOver, setIsOver] = useState(false); + + // Get models from MODELS + const { modelIds: availableModels, modelDisplayName } = MODELS; + const modelId = getModelId(); + + // File handling + const { clear: clearFiles, uploadFiles, uploadedFiles } = useFiles(pathname); + + // Initialize model ID when agent is loaded + useEffect(() => { + if (agent && availableModels.length > 0) { + const agentModelId = agent.modelId || availableModels[0]; + const currentModelId = getModelId(); + if (currentModelId !== agentModelId) { + setModelId(agentModelId); + } + } + }, [agent, availableModels, getModelId, setModelId]); + + // Initialize system context when component mounts (only once per agent) + useEffect(() => { + if (!initialized && agent) { + console.log('Initializing agent chat:', agent.name); + + // Set the system context to the agent's system prompt + const systemPrompt = `${agent.systemPrompt || 'You are a helpful assistant.'} + +Agent Name: ${agent.name} +Agent Description: ${agent.description || 'No description provided'} + +Please respond as this agent with the specified behavior and personality.`; + + updateSystemContext(systemPrompt); + setInitialized(true); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [agent?.agentId, initialized]); + + // Update system context when agent data changes (for real-time updates) + useEffect(() => { + if (initialized && agent) { + console.log('Updating agent context:', agent.name); + + const systemPrompt = `${agent.systemPrompt || 'You are a helpful assistant.'} + +Agent Name: ${agent.name} +Agent Description: ${agent.description || 'No description provided'} + +Please respond as this agent with the specified behavior and personality.`; + + updateSystemContext(systemPrompt); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [agent?.name, agent?.description, agent?.systemPrompt, initialized]); + + // Accept file types based on model + const accept = useMemo(() => { + if (!modelId) return []; + const feature = MODELS.getModelMetadata(modelId); + return [ + ...(feature.flags.doc ? fileLimit.accept.doc : []), + ...(feature.flags.image ? fileLimit.accept.image : []), + ...(feature.flags.video ? fileLimit.accept.video : []), + ]; + }, [modelId]); + + // File upload enabled + const fileUpload = useMemo(() => { + return accept.length > 0; + }, [accept]); + + const handleSendMessage = useCallback(async () => { + if (!chatContent.trim() || chatLoading) return; + + setFollowing(true); + + try { + const genericRuntime = getGenericRuntime(); + if (!genericRuntime) { + throw new Error('No AgentCore runtime available'); + } + + console.log('Sending message with agent:', agent.name); + console.log('Using sessionId:', sessionId); + console.log('MCP servers count:', agent.mcpServers?.length || 0); + console.log('Code execution enabled:', agent.codeExecutionEnabled); + + // Get uploaded files from the useFiles hook + const uploadedFileObjects = uploadedFiles.filter( + (file) => !file.errorMessages.length && !file.uploading + ); + const filesToSend = + uploadedFileObjects.length > 0 + ? uploadedFileObjects.map((uploadedFile) => uploadedFile.file) + : undefined; + + // Use AgentCore's invokeAgentRuntime with MCP servers + invokeAgentRuntime( + genericRuntime.arn, + sessionId, + chatContent, + 'DEFAULT', + filesToSend, + 'current-user', + agent.mcpServers, + agent.agentId, + agent.modelId, + agent.codeExecutionEnabled ?? false + ); + + setChatContent(''); + clearFiles(); + } catch (error) { + console.error('Error sending message:', error); + alert( + `Error: ${error instanceof Error ? error.message : 'Unknown error occurred'}` + ); + } + }, [ + chatContent, + agent, + chatLoading, + setFollowing, + invokeAgentRuntime, + getGenericRuntime, + sessionId, + uploadedFiles, + clearFiles, + ]); + + const handleResetChat = useCallback(() => { + clearChat(); + setChatContent(''); + clearFiles(); + }, [clearChat, clearFiles]); + + // Handle drag and drop for files + const handleDragOver = (event: React.DragEvent) => { + event.preventDefault(); + setIsOver(true); + }; + + const handleDragLeave = (event: React.DragEvent) => { + event.preventDefault(); + setIsOver(false); + }; + + const handleDrop = (event: React.DragEvent) => { + event.preventDefault(); + setIsOver(false); + if (event.dataTransfer.files) { + uploadFiles(Array.from(event.dataTransfer.files), fileLimit, accept); + } + }; + + // Render unified header with all controls + const renderUnifiedHeader = () => ( +
+ {/* Header with title, description and actions */} +
+
+ {/* Agent Title */} +
+ {agent?.name || t('agent_builder.agent_chat')} +
+ {/* Agent Description */} + {agent?.description && ( +
+ {agent.description} +
+ )} +
+ {/* Actions */} +
+ {showEditButton && onEdit && ( + + + + )} + {actions} +
+
+ + {/* Controls - all stacked vertically for consistent layout */} + {showAgentInfo && ( +
+ {/* Model Selection */} +
+