├── src
├── react-app-env.d.ts
├── images
│ └── banner.jpg
├── App.test.js
├── index.css
├── reportWebVitals.js
├── index.js
├── components
│ ├── MyTextField.js
│ ├── MyFlexibleTable.js
│ ├── Header.js
│ ├── About.js
│ ├── ResponseCard.js
│ ├── Conversations.js
│ └── Interact.js
├── App.css
├── aws-exports.ts
├── App.js
└── graphql
│ ├── queries.js
│ ├── subscriptions.js
│ └── mutations.js
├── amplify
├── backend
│ ├── function
│ │ └── assistantFulfillment
│ │ │ ├── src
│ │ │ ├── src.egg-info
│ │ │ │ ├── top_level.txt
│ │ │ │ ├── dependency_links.txt
│ │ │ │ ├── SOURCES.txt
│ │ │ │ └── PKG-INFO
│ │ │ ├── event.json
│ │ │ ├── setup.py
│ │ │ └── index.py
│ │ │ ├── function-parameters.json
│ │ │ ├── custom-policies.json
│ │ │ ├── amplify.state
│ │ │ ├── Pipfile
│ │ │ ├── Pipfile.lock
│ │ │ └── assistantFulfillment-cloudformation-template.json
│ ├── api
│ │ └── awsAssistantBackend
│ │ │ ├── transform.conf.json
│ │ │ ├── parameters.json
│ │ │ ├── resolvers
│ │ │ └── README.md
│ │ │ ├── cli-inputs.json
│ │ │ ├── .migration-backup
│ │ │ └── schema.graphql
│ │ │ ├── schema.graphql
│ │ │ ├── .migration-config-backup
│ │ │ └── cli.json
│ │ │ └── stacks
│ │ │ └── CustomResources.json
│ ├── tags.json
│ ├── types
│ │ └── amplify-dependent-resources-ref.d.ts
│ ├── hosting
│ │ └── amplifyhosting
│ │ │ └── amplifyhosting-template.json
│ ├── auth
│ │ └── awsassistantfcd2b45d
│ │ │ └── cli-inputs.json
│ └── backend-config.json
├── README.md
├── hooks
│ └── README.md
├── .config
│ └── project-config.json
└── cli.json
├── bot
├── Manifest.json
└── cloud-assistant
│ ├── Bot.json
│ └── BotLocales
│ └── en_US
│ ├── BotLocale.json
│ ├── SlotTypes
│ ├── objName
│ │ └── SlotType.json
│ ├── bucketName
│ │ └── SlotType.json
│ ├── subnetType
│ │ └── SlotType.json
│ ├── ipAddress
│ │ └── SlotType.json
│ ├── region
│ │ └── SlotType.json
│ ├── ami
│ │ └── SlotType.json
│ └── instanceType
│ │ └── SlotType.json
│ └── Intents
│ ├── FallbackIntent
│ └── Intent.json
│ ├── s3-list-buckets
│ └── Intent.json
│ ├── ec2-terminate
│ └── Intent.json
│ ├── s3-copy-to-new-bucket
│ └── Intent.json
│ ├── set-region
│ ├── Intent.json
│ └── Slots
│ │ └── region
│ │ └── Slot.json
│ ├── get-help
│ └── Intent.json
│ ├── sg-rule-list
│ └── Intent.json
│ ├── s3-create-bucket
│ ├── Intent.json
│ └── Slots
│ │ └── bucketName
│ │ └── Slot.json
│ ├── ec2-create
│ ├── Intent.json
│ └── Slots
│ │ ├── count
│ │ └── Slot.json
│ │ ├── ami
│ │ └── Slot.json
│ │ └── instanceType
│ │ └── Slot.json
│ ├── sg-rule-replace
│ ├── Intent.json
│ └── Slots
│ │ └── ipAddress
│ │ └── Slot.json
│ ├── ec2-list
│ ├── Slots
│ │ ├── ami
│ │ │ └── Slot.json
│ │ ├── subnetType
│ │ │ └── Slot.json
│ │ └── instanceType
│ │ │ └── Slot.json
│ └── Intent.json
│ └── s3-search
│ ├── Intent.json
│ └── Slots
│ ├── bucketIndex
│ └── Slot.json
│ └── objName
│ └── Slot.json
├── public
├── robots.txt
├── manifest.json
└── index.html
├── static
└── images
│ └── architecture.png
├── CODE_OF_CONDUCT.md
├── .graphqlconfig.yml
├── tsconfig.json
├── .gitignore
├── LICENSE
├── package.json
├── CONTRIBUTING.md
└── README.md
/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/src/src.egg-info/top_level.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/src/event.json:
--------------------------------------------------------------------------------
1 | { "test": "event" }
2 |
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/src/src.egg-info/dependency_links.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bot/Manifest.json:
--------------------------------------------------------------------------------
1 | {"metaData":{"fileFormat":"LexJson","resourceType":"BOT","schemaVersion":"1"}}
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/function-parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "lambdaLayers": []
3 | }
--------------------------------------------------------------------------------
/src/images/banner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-amplify-cloud-assistant-app/HEAD/src/images/banner.jpg
--------------------------------------------------------------------------------
/amplify/backend/api/awsAssistantBackend/transform.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "Version": 5,
3 | "ElasticsearchWarning": true
4 | }
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/src/setup.py:
--------------------------------------------------------------------------------
1 | from distutils.core import setup
2 |
3 | setup(name='src', version='1.0')
4 |
--------------------------------------------------------------------------------
/static/images/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-amplify-cloud-assistant-app/HEAD/static/images/architecture.png
--------------------------------------------------------------------------------
/bot/cloud-assistant/Bot.json:
--------------------------------------------------------------------------------
1 | {"name":"cloud-assistant","version":"2","description":null,"identifier":"TOJAY8JVIP","dataPrivacy":{"childDirected":false},"idleSessionTTLInSeconds":60}
--------------------------------------------------------------------------------
/amplify/backend/tags.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "Key": "user:Stack",
4 | "Value": "{project-env}"
5 | },
6 | {
7 | "Key": "user:Application",
8 | "Value": "{project-name}"
9 | }
10 | ]
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/BotLocale.json:
--------------------------------------------------------------------------------
1 | {"name":"English (US)","identifier":"en_US","version":null,"description":null,"voiceSettings":{"engine":"standard","voiceId":"Joanna"},"nluConfidenceThreshold":0.4}
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/src/src.egg-info/SOURCES.txt:
--------------------------------------------------------------------------------
1 | index.py
2 | setup.py
3 | src.egg-info/PKG-INFO
4 | src.egg-info/SOURCES.txt
5 | src.egg-info/dependency_links.txt
6 | src.egg-info/top_level.txt
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/custom-policies.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "Action": ["ec2:*"],
4 | "Resource": ["*"]
5 | },
6 | {
7 | "Action": ["s3:*"],
8 | "Resource": ["*"]
9 | }
10 | ]
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/amplify.state:
--------------------------------------------------------------------------------
1 | {
2 | "pluginId": "amplify-python-function-runtime-provider",
3 | "functionRuntime": "python",
4 | "useLegacyBuild": false,
5 | "defaultEditorFile": "src/index.py"
6 | }
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/src/src.egg-info/PKG-INFO:
--------------------------------------------------------------------------------
1 | Metadata-Version: 2.1
2 | Name: src
3 | Version: 1.0
4 | Summary: UNKNOWN
5 | Home-page: UNKNOWN
6 | License: UNKNOWN
7 | Platform: UNKNOWN
8 |
9 | UNKNOWN
10 |
11 |
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 | name = "pypi"
3 | url = "https://pypi.org/simple"
4 | verify_ssl = true
5 |
6 | [dev-packages]
7 |
8 | [packages]
9 | src = {editable = true, path = "./src"}
10 |
11 | [requires]
12 | python_version = "3.8"
13 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import App from './App';
3 |
4 | test('renders learn react link', () => {
5 | render();
6 | const linkElement = screen.getByText(/learn react/i);
7 | expect(linkElement).toBeInTheDocument();
8 | });
9 |
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/SlotTypes/objName/SlotType.json:
--------------------------------------------------------------------------------
1 | {"name":"objName","identifier":"XKU9YIFF4Z","description":null,"slotTypeValues":null,"parentSlotTypeSignature":"AMAZON.AlphaNumeric","valueSelectionSetting":{"regexFilter":{"pattern":"[0-9][a-z]"},"resolutionStrategy":"ORIGINAL_VALUE"}}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/SlotTypes/bucketName/SlotType.json:
--------------------------------------------------------------------------------
1 | {"name":"bucketName","identifier":"FJEG6LWUY0","description":null,"slotTypeValues":null,"parentSlotTypeSignature":"AMAZON.AlphaNumeric","valueSelectionSetting":{"regexFilter":{"pattern":"[0-9][a-z]-"},"resolutionStrategy":"ORIGINAL_VALUE"}}
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
5 |
--------------------------------------------------------------------------------
/amplify/backend/api/awsAssistantBackend/parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "AppSyncApiName": "awsAssistantBackend",
3 | "DynamoDBBillingMode": "PAY_PER_REQUEST",
4 | "DynamoDBEnableServerSideEncryption": false,
5 | "AuthCognitoUserPoolId": {
6 | "Fn::GetAtt": [
7 | "authawsassistantfcd2b45d",
8 | "Outputs.UserPoolId"
9 | ]
10 | }
11 | }
--------------------------------------------------------------------------------
/amplify/backend/api/awsAssistantBackend/resolvers/README.md:
--------------------------------------------------------------------------------
1 | Any resolvers that you add in this directory will override the ones automatically generated by Amplify CLI and will be directly copied to the cloud.
2 | For more information, visit [https://docs.amplify.aws/cli/graphql-transformer/resolvers](https://docs.amplify.aws/cli/graphql-transformer/resolvers)
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/SlotTypes/subnetType/SlotType.json:
--------------------------------------------------------------------------------
1 | {"name":"subnetType","identifier":"XZZJY286HX","description":null,"slotTypeValues":[{"sampleValue":{"value":"private"},"synonyms":[{"value":"private"}]},{"sampleValue":{"value":"public"},"synonyms":[{"value":"public"}]}],"parentSlotTypeSignature":null,"valueSelectionSetting":{"regexFilter":null,"resolutionStrategy":"TOP_RESOLUTION"}}
--------------------------------------------------------------------------------
/.graphqlconfig.yml:
--------------------------------------------------------------------------------
1 | projects:
2 | awsAssistantBackend:
3 | schemaPath: src/graphql/schema.json
4 | includes:
5 | - src/graphql/**/*.js
6 | excludes:
7 | - ./amplify/**
8 | extensions:
9 | amplify:
10 | codeGenTarget: javascript
11 | generatedFileName: ''
12 | docsFilePath: src/graphql
13 | extensions:
14 | amplify:
15 | version: 3
16 |
--------------------------------------------------------------------------------
/amplify/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Amplify CLI
2 | This directory was generated by [Amplify CLI](https://docs.amplify.aws/cli).
3 |
4 | Helpful resources:
5 | - Amplify documentation: https://docs.amplify.aws
6 | - Amplify CLI documentation: https://docs.amplify.aws/cli
7 | - More details on this folder & generated files: https://docs.amplify.aws/cli/reference/files
8 | - Join Amplify's community: https://amplify.aws/community/
9 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/amplify/hooks/README.md:
--------------------------------------------------------------------------------
1 | # Command Hooks
2 |
3 | Command hooks can be used to run custom scripts upon Amplify CLI lifecycle events like pre-push, post-add-function, etc.
4 |
5 | To get started, add your script files based on the expected naming convention in this directory.
6 |
7 | Learn more about the script file naming convention, hook parameters, third party dependencies, and advanced configurations at https://docs.amplify.aws/cli/usage/command-hooks
8 |
--------------------------------------------------------------------------------
/amplify/.config/project-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "projectName": "awsassistant",
3 | "version": "3.1",
4 | "frontend": "javascript",
5 | "javascript": {
6 | "framework": "react",
7 | "config": {
8 | "SourceDir": "src",
9 | "DistributionDir": "build",
10 | "BuildCommand": "npm.cmd run-script build",
11 | "StartCommand": "npm.cmd run-script start"
12 | }
13 | },
14 | "providers": [
15 | "awscloudformation"
16 | ]
17 | }
--------------------------------------------------------------------------------
/amplify/backend/api/awsAssistantBackend/cli-inputs.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "serviceConfiguration": {
4 | "serviceName": "AppSync",
5 | "defaultAuthType": {
6 | "mode": "AMAZON_COGNITO_USER_POOLS",
7 | "cognitoUserPoolId": "authawsassistantfcd2b45d"
8 | },
9 | "conflictResolution": {},
10 | "apiName": "awsAssistantBackend",
11 | "gqlSchemaPath": "C:\\Users\\wbenhal\\Documents\\React Projects\\aws-assistant\\amplify\\backend\\api\\awsAssistantBackend\\schema.graphql"
12 | }
13 | }
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/SlotTypes/ipAddress/SlotType.json:
--------------------------------------------------------------------------------
1 | {"name":"ipAddress","identifier":"TYPH1224JI","description":null,"slotTypeValues":[{"sampleValue":{"value":"0.0.0.0"},"synonyms":null},{"sampleValue":{"value":"255.255.255.255"},"synonyms":null},{"sampleValue":{"value":"76.243.176.78"},"synonyms":null},{"sampleValue":{"value":"10.10.255.255"},"synonyms":null},{"sampleValue":{"value":"123.26.200.10"},"synonyms":null}],"parentSlotTypeSignature":null,"valueSelectionSetting":{"regexFilter":null,"resolutionStrategy":"ORIGINAL_VALUE"}}
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import reportWebVitals from './reportWebVitals';
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById('root')
12 | );
13 |
14 | // If you want to start measuring performance in your app, pass a function
15 | // to log results (for example: reportWebVitals(console.log))
16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
17 | reportWebVitals();
18 |
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/SlotTypes/region/SlotType.json:
--------------------------------------------------------------------------------
1 | {"name":"region","identifier":"YKF03KOAZE","description":null,"slotTypeValues":[{"sampleValue":{"value":"us-east-1"},"synonyms":[{"value":"us-east-1"},{"value":"virginia"}]},{"sampleValue":{"value":"us-east-2"},"synonyms":[{"value":"us-east-2"},{"value":"ohio"}]},{"sampleValue":{"value":"us-west-1"},"synonyms":[{"value":"us-west-1"},{"value":"california"}]},{"sampleValue":{"value":"us-west-2"},"synonyms":[{"value":"us-west-2"},{"value":"oregon"}]}],"parentSlotTypeSignature":null,"valueSelectionSetting":{"regexFilter":null,"resolutionStrategy":"TOP_RESOLUTION"}}
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/src/components/MyTextField.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { TextField } from '@mui/material'
3 |
4 | const MyTextField = ({newQuery, setNewQuery, handleKeyPress, SendButton}) => {
5 | return (
6 | }}
10 | autoComplete="off" value={newQuery}
11 | onChange={(e) => {setNewQuery(e.target.value)}}
12 | onKeyDown={handleKeyPress}>
13 | )
14 | }
15 |
16 | export default MyTextField
17 |
--------------------------------------------------------------------------------
/amplify/backend/api/awsAssistantBackend/.migration-backup/schema.graphql:
--------------------------------------------------------------------------------
1 | type Conversation @model
2 | @key(name: "conversationsByUser", fields: ["user", "createdAt"], queryField: "conversationsByUser"){
3 | id: ID!
4 | name: String!
5 | user: String!
6 | description: String
7 | createdAt: String!
8 | utterances: [Utterance] @connection(keyName: "byConversationId", fields: ["id"])
9 | }
10 |
11 |
12 | type Utterance @model
13 | @key(name: "byConversationId", fields: ["conversationId", "createdAt"]) {
14 | id: ID!
15 | text: String!
16 | author: String!
17 | conversationId: ID!
18 | data: String
19 | createdAt: String!
20 | }
21 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/amplify/backend/api/awsAssistantBackend/schema.graphql:
--------------------------------------------------------------------------------
1 | type Conversation @model @auth(rules: [{allow: owner}]) {
2 | id: ID!
3 | name: String!
4 | user: String! @index(name: "conversationsByUser", queryField: "conversationsByUser", sortKeyFields: ["createdAt"])
5 | description: String
6 | createdAt: String!
7 | utterances: [Utterance] @hasMany(indexName: "byConversationId", fields: ["id"])
8 | }
9 |
10 | type Utterance @model @auth(rules: [{allow: owner}]) {
11 | id: ID!
12 | text: String!
13 | author: String!
14 | conversationId: ID! @index(name: "byConversationId", sortKeyFields: ["createdAt"])
15 | data: String
16 | createdAt: String!
17 | }
18 |
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/Pipfile.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "hash": {
4 | "sha256": "20a5580e79d8b5a7a360dfdbab4ee3c05dce7388bd6c4f2e7c30c18288e02f68"
5 | },
6 | "pipfile-spec": 6,
7 | "requires": {
8 | "python_version": "3.8"
9 | },
10 | "sources": [
11 | {
12 | "name": "pypi",
13 | "url": "https://pypi.org/simple",
14 | "verify_ssl": true
15 | }
16 | ]
17 | },
18 | "default": {
19 | "src": {
20 | "editable": true,
21 | "path": "./src"
22 | }
23 | },
24 | "develop": {}
25 | }
26 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/amplify/backend/types/amplify-dependent-resources-ref.d.ts:
--------------------------------------------------------------------------------
1 | export type AmplifyDependentResourcesAttributes = {
2 | "api": {
3 | "awsAssistantBackend": {
4 | "GraphQLAPIEndpointOutput": "string",
5 | "GraphQLAPIIdOutput": "string"
6 | }
7 | },
8 | "auth": {
9 | "awsassistantfcd2b45d": {
10 | "AppClientID": "string",
11 | "AppClientIDWeb": "string",
12 | "IdentityPoolId": "string",
13 | "IdentityPoolName": "string",
14 | "UserPoolArn": "string",
15 | "UserPoolId": "string",
16 | "UserPoolName": "string"
17 | }
18 | },
19 | "function": {
20 | "assistantFulfillment": {
21 | "Arn": "string",
22 | "LambdaExecutionRole": "string",
23 | "Name": "string",
24 | "Region": "string"
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/SlotTypes/ami/SlotType.json:
--------------------------------------------------------------------------------
1 | {"name":"ami","identifier":"3SKZ8SGUHR","description":null,"slotTypeValues":[{"sampleValue":{"value":"ami-00c39f71452c08778"},"synonyms":[{"value":"Amazon linux 2"},{"value":"amazon linux"}]},{"sampleValue":{"value":"ami-0c9978668f8d55984"},"synonyms":[{"value":"red hat enterprise linux 8"},{"value":"red hat"}]},{"sampleValue":{"value":"ami-0557a15b87f6559cf"},"synonyms":[{"value":"ubuntu server 20.04"},{"value":" ubuntu server"},{"value":" ubuntu"}]},{"sampleValue":{"value":"ami-0e38fa17744b2f6a5"},"synonyms":[{"value":"Microsoft Windows Server 2019 Base"},{"value":"Microsoft Windows"},{"value":"Windows Server"},{"value":"windows"}]}],"parentSlotTypeSignature":null,"valueSelectionSetting":{"regexFilter":null,"resolutionStrategy":"TOP_RESOLUTION"}}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
25 | #amplify-do-not-edit-begin
26 | amplify/\#current-cloud-backend
27 | amplify/.config/local-*
28 | amplify/logs
29 | amplify/mock-data
30 | amplify/backend/amplify-meta.json
31 | amplify/backend/awscloudformation
32 | amplify/backend/.temp
33 | build/
34 | dist/
35 | node_modules/
36 | aws-exports.js
37 | awsconfiguration.json
38 | amplifyconfiguration.json
39 | amplifyconfiguration.dart
40 | amplify-build-config.json
41 | amplify-gradle-config.json
42 | amplifytools.xcconfig
43 | .secret-*
44 | **.sample
45 | #amplify-do-not-edit-end
46 |
47 | # IDE
48 | .vscode
--------------------------------------------------------------------------------
/amplify/backend/hosting/amplifyhosting/amplifyhosting-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "AWSTemplateFormatVersion": "2010-09-09",
3 | "Description": "{\"createdOn\":\"Windows\",\"createdBy\":\"Amplify\",\"createdWith\":\"8.0.2\",\"stackType\":\"hosting-amplifyhosting\",\"metadata\":{}}",
4 | "Parameters": {
5 | "env": {
6 | "Type": "String"
7 | },
8 | "appId": {
9 | "Type": "String"
10 | },
11 | "type": {
12 | "Type": "String"
13 | }
14 | },
15 | "Conditions": {
16 | "isManual": {
17 | "Fn::Equals": [
18 | {
19 | "Ref": "type"
20 | },
21 | "manual"
22 | ]
23 | }
24 | },
25 | "Resources": {
26 | "AmplifyBranch": {
27 | "Condition": "isManual",
28 | "Type": "AWS::Amplify::Branch",
29 | "Properties": {
30 | "BranchName": {
31 | "Ref": "env"
32 | },
33 | "AppId": {
34 | "Ref": "appId"
35 | }
36 | }
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT No Attribution
2 |
3 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
13 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
15 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 |
18 |
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/SlotTypes/instanceType/SlotType.json:
--------------------------------------------------------------------------------
1 | {"name":"instanceType","identifier":"NAEKHHXJ2F","description":null,"slotTypeValues":[{"sampleValue":{"value":"t2.micro"},"synonyms":[{"value":"t2 micro"},{"value":"micro t2"}]},{"sampleValue":{"value":"t2.small"},"synonyms":[{"value":"t2 small"},{"value":"small t2"}]},{"sampleValue":{"value":"t2.medium"},"synonyms":[{"value":"t2 medium"},{"value":"medium t2"}]},{"sampleValue":{"value":"t2.large"},"synonyms":[{"value":"t2 large"},{"value":"large t2"}]},{"sampleValue":{"value":"t2.xlarge"},"synonyms":[{"value":"t2 extra large"},{"value":"extra large t2"}]},{"sampleValue":{"value":"t3.micro"},"synonyms":[{"value":"t3 micro"},{"value":"micro t3"}]},{"sampleValue":{"value":"t3.small"},"synonyms":[{"value":"t3 small"},{"value":"small t3"}]},{"sampleValue":{"value":"t3.medium"},"synonyms":[{"value":"t3 medium"},{"value":"medium t3"}]},{"sampleValue":{"value":"t3.large"},"synonyms":[{"value":"t3 large"},{"value":"large t3"}]},{"sampleValue":{"value":"t3.xlarge"},"synonyms":[{"value":"t3 extra large"},{"value":"extra large t3"}]}],"parentSlotTypeSignature":null,"valueSelectionSetting":{"regexFilter":null,"resolutionStrategy":"TOP_RESOLUTION"}}
--------------------------------------------------------------------------------
/src/aws-exports.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.
3 |
4 | const awsmobile = {
5 | "aws_project_region": "us-east-1",
6 | "aws_cognito_identity_pool_id": "us-east-1:0b3fa6df-883a-4b25-aa47-bcc13fc2f013",
7 | "aws_cognito_region": "us-east-1",
8 | "aws_user_pools_id": "us-east-1_uRmkPZXXv",
9 | "aws_user_pools_web_client_id": "3b3i2nmqp4nk8lb7h60imh6que",
10 | "oauth": {},
11 | "aws_cognito_username_attributes": [
12 | "EMAIL"
13 | ],
14 | "aws_cognito_social_providers": [],
15 | "aws_cognito_signup_attributes": [
16 | "EMAIL"
17 | ],
18 | "aws_cognito_mfa_configuration": "OFF",
19 | "aws_cognito_mfa_types": [
20 | "SMS"
21 | ],
22 | "aws_cognito_password_protection_settings": {
23 | "passwordPolicyMinLength": 8,
24 | "passwordPolicyCharacters": []
25 | },
26 | "aws_cognito_verification_mechanisms": [
27 | "EMAIL"
28 | ],
29 | "aws_appsync_graphqlEndpoint": "https://qxwwlnpchfbqfmcq4kqo3didnu.appsync-api.us-east-1.amazonaws.com/graphql",
30 | "aws_appsync_region": "us-east-1",
31 | "aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS"
32 | };
33 |
34 |
35 | export default awsmobile;
36 |
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/FallbackIntent/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"FallbackIntent","identifier":"FALLBCKINT","description":"Default intent when no other intent matches","parentIntentSignature":"AMAZON.FallbackIntent","sampleUtterances":null,"intentConfirmationSetting":null,"intentClosingSetting":null,"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":null,"outputContexts":null,"kendraConfiguration":null,"dialogCodeHook":null,"fulfillmentCodeHook":null,"slotPriorities":[]}
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aws-assistant",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@aws-amplify/ui-react": "^1.2.20",
7 | "@emotion/react": "^11.4.1",
8 | "@emotion/styled": "^11.3.0",
9 | "@fontsource/roboto": "^4.5.1",
10 | "@mui/icons-material": "^5.0.1",
11 | "@mui/material": "^5.0.2",
12 | "@mui/x-data-grid": "^5.0.0-beta.5",
13 | "@testing-library/jest-dom": "^5.14.1",
14 | "@testing-library/react": "^11.2.7",
15 | "@testing-library/user-event": "^12.8.3",
16 | "@thefat32/aws-amplify-lex-provider-v2": "^1.0.3",
17 | "aws-amplify": "^4.3.2",
18 | "react": "^17.0.2",
19 | "react-dom": "^17.0.2",
20 | "react-router-dom": "^5.3.0",
21 | "react-scripts": "4.0.3",
22 | "web-vitals": "^1.1.2"
23 | },
24 | "scripts": {
25 | "start": "react-scripts start",
26 | "build": "react-scripts build",
27 | "test": "react-scripts test",
28 | "eject": "react-scripts eject"
29 | },
30 | "eslintConfig": {
31 | "extends": [
32 | "react-app",
33 | "react-app/jest"
34 | ]
35 | },
36 | "browserslist": {
37 | "production": [
38 | ">0.2%",
39 | "not dead",
40 | "not op_mini all"
41 | ],
42 | "development": [
43 | "last 1 chrome version",
44 | "last 1 firefox version",
45 | "last 1 safari version"
46 | ]
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/components/MyFlexibleTable.js:
--------------------------------------------------------------------------------
1 |
2 | // Material Imports
3 | import { TableContainer, Table, TableHead, TableRow, TableCell, TableBody } from "@mui/material";
4 | import { Paper } from "@mui/material";
5 |
6 | const MyFlexibleTable = ({rows, cols, rowIndex}) => {
7 |
8 | return (
9 |
10 |
11 |
12 |
13 | {cols.map((col, index) => (
14 | index === 0 ? {col} : {col}
15 | ))}
16 |
17 |
18 |
19 | {rows.map((row) => (
20 |
21 | {row.map((attribute, index) => (
22 | index === 0 ? {attribute} : {attribute}
23 | ))}
24 |
25 | ))}
26 |
27 |
28 |
29 | )
30 | }
31 |
32 | export default MyFlexibleTable
33 |
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/s3-list-buckets/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"s3-list-buckets","identifier":"IFLU5J6MAP","description":null,"parentIntentSignature":null,"sampleUtterances":[{"utterance":"list all S3 buckets"},{"utterance":"show me all my buckets"},{"utterance":"show all s3 buckets"},{"utterance":"how many S3 buckets do I have?"},{"utterance":"show a list of all S3 buckets"}],"intentConfirmationSetting":null,"intentClosingSetting":null,"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":null,"outputContexts":[{"name":"buckets-listed","timeToLiveInSeconds":3600,"turnsToLive":5}],"kendraConfiguration":null,"dialogCodeHook":{"enabled":true},"fulfillmentCodeHook":null,"slotPriorities":[]}
--------------------------------------------------------------------------------
/amplify/backend/api/awsAssistantBackend/.migration-config-backup/cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "features": {
3 | "graphqltransformer": {
4 | "addmissingownerfields": true,
5 | "improvepluralization": false,
6 | "validatetypenamereservedwords": true,
7 | "useexperimentalpipelinedtransformer": false,
8 | "enableiterativegsiupdates": true,
9 | "secondarykeyasgsi": true,
10 | "skipoverridemutationinputtypes": true,
11 | "securityEnhancementNotification": false,
12 | "showfieldauthnotification": false
13 | },
14 | "frontend-ios": {
15 | "enablexcodeintegration": true
16 | },
17 | "auth": {
18 | "enablecaseinsensitivity": true,
19 | "useinclusiveterminology": true,
20 | "breakcirculardependency": true,
21 | "forcealiasattributes": false
22 | },
23 | "codegen": {
24 | "useappsyncmodelgenplugin": true,
25 | "usedocsgeneratorplugin": true,
26 | "usetypesgeneratorplugin": true,
27 | "cleangeneratedmodelsdirectory": true,
28 | "retaincasestyle": true,
29 | "addtimestampfields": true,
30 | "handlelistnullabilitytransparently": true,
31 | "emitauthprovider": true,
32 | "generateindexrules": true,
33 | "enabledartnullsafety": true
34 | },
35 | "appsync": {
36 | "generategraphqlpermissions": true
37 | },
38 | "latestregionsupport": {
39 | "pinpoint": 1,
40 | "translate": 1,
41 | "transcribe": 1,
42 | "rekognition": 1,
43 | "textract": 1,
44 | "comprehend": 1
45 | },
46 | "project": {
47 | "overrides": true
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/amplify/backend/auth/awsassistantfcd2b45d/cli-inputs.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1",
3 | "cognitoConfig": {
4 | "authSelections": "identityPoolAndUserPool",
5 | "requiredAttributes": [
6 | "email"
7 | ],
8 | "resourceName": "awsassistantfcd2b45d",
9 | "serviceName": "Cognito",
10 | "useDefault": "default",
11 | "userpoolClientReadAttributes": [
12 | "email"
13 | ],
14 | "userpoolClientWriteAttributes": [
15 | "email"
16 | ],
17 | "aliasAttributes": [],
18 | "resourceNameTruncated": "awsassfcd2b45d",
19 | "sharedId": "fcd2b45d",
20 | "userPoolGroupList": [],
21 | "userPoolName": "awsassistantfcd2b45d_userpool_fcd2b45d",
22 | "usernameAttributes": [
23 | "email"
24 | ],
25 | "usernameCaseSensitive": false,
26 | "userpoolClientRefreshTokenValidity": 30,
27 | "userpoolClientSetAttributes": false,
28 | "userpoolClientGenerateSecret": false,
29 | "userpoolClientLambdaRole": "awsassfcd2b45d_userpoolclient_lambda_role",
30 | "passwordPolicyCharacters": [],
31 | "passwordPolicyMinLength": 8,
32 | "mfaConfiguration": "OFF",
33 | "mfaTypes": [
34 | "SMS Text Message"
35 | ],
36 | "smsAuthenticationMessage": "Your authentication code is {####}",
37 | "emailVerificationMessage": "Your verification code is {####}",
38 | "emailVerificationSubject": "Your verification code",
39 | "smsVerificationMessage": "Your verification code is {####}",
40 | "autoVerifiedAttributes": [],
41 | "identityPoolName": "awsassistantfcd2b45d_identitypool_fcd2b45d",
42 | "allowUnauthenticatedIdentities": true
43 | }
44 | }
--------------------------------------------------------------------------------
/amplify/cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "features": {
3 | "graphqltransformer": {
4 | "addmissingownerfields": true,
5 | "improvepluralization": false,
6 | "validatetypenamereservedwords": true,
7 | "useexperimentalpipelinedtransformer": true,
8 | "enableiterativegsiupdates": true,
9 | "secondarykeyasgsi": true,
10 | "skipoverridemutationinputtypes": true,
11 | "securityEnhancementNotification": false,
12 | "showfieldauthnotification": false,
13 | "transformerversion": 2,
14 | "suppressschemamigrationprompt": true
15 | },
16 | "frontend-ios": {
17 | "enablexcodeintegration": true
18 | },
19 | "auth": {
20 | "enablecaseinsensitivity": true,
21 | "useinclusiveterminology": true,
22 | "breakcirculardependency": true,
23 | "forcealiasattributes": false
24 | },
25 | "codegen": {
26 | "useappsyncmodelgenplugin": true,
27 | "usedocsgeneratorplugin": true,
28 | "usetypesgeneratorplugin": true,
29 | "cleangeneratedmodelsdirectory": true,
30 | "retaincasestyle": true,
31 | "addtimestampfields": true,
32 | "handlelistnullabilitytransparently": true,
33 | "emitauthprovider": true,
34 | "generateindexrules": true,
35 | "enabledartnullsafety": true
36 | },
37 | "appsync": {
38 | "generategraphqlpermissions": true
39 | },
40 | "latestregionsupport": {
41 | "pinpoint": 1,
42 | "translate": 1,
43 | "transcribe": 1,
44 | "rekognition": 1,
45 | "textract": 1,
46 | "comprehend": 1
47 | },
48 | "project": {
49 | "overrides": true
50 | }
51 | },
52 | "debug": {
53 | "shareProjectConfig": false
54 | }
55 | }
--------------------------------------------------------------------------------
/amplify/backend/api/awsAssistantBackend/stacks/CustomResources.json:
--------------------------------------------------------------------------------
1 | {
2 | "AWSTemplateFormatVersion": "2010-09-09",
3 | "Description": "An auto-generated nested stack.",
4 | "Metadata": {},
5 | "Parameters": {
6 | "AppSyncApiId": {
7 | "Type": "String",
8 | "Description": "The id of the AppSync API associated with this project."
9 | },
10 | "AppSyncApiName": {
11 | "Type": "String",
12 | "Description": "The name of the AppSync API",
13 | "Default": "AppSyncSimpleTransform"
14 | },
15 | "env": {
16 | "Type": "String",
17 | "Description": "The environment name. e.g. Dev, Test, or Production",
18 | "Default": "NONE"
19 | },
20 | "S3DeploymentBucket": {
21 | "Type": "String",
22 | "Description": "The S3 bucket containing all deployment assets for the project."
23 | },
24 | "S3DeploymentRootKey": {
25 | "Type": "String",
26 | "Description": "An S3 key relative to the S3DeploymentBucket that points to the root\nof the deployment directory."
27 | }
28 | },
29 | "Resources": {
30 | "EmptyResource": {
31 | "Type": "Custom::EmptyResource",
32 | "Condition": "AlwaysFalse"
33 | }
34 | },
35 | "Conditions": {
36 | "HasEnvironmentParameter": {
37 | "Fn::Not": [
38 | {
39 | "Fn::Equals": [
40 | {
41 | "Ref": "env"
42 | },
43 | "NONE"
44 | ]
45 | }
46 | ]
47 | },
48 | "AlwaysFalse": {
49 | "Fn::Equals": ["true", "false"]
50 | }
51 | },
52 | "Outputs": {
53 | "EmptyOutput": {
54 | "Description": "An empty output. You may delete this if you have at least one resource above.",
55 | "Value": ""
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 |
2 | import './App.css';
3 |
4 | // React router components - test 3
5 | import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
6 |
7 | // Import ROBOTO
8 | import '@fontsource/roboto/300.css';
9 | import '@fontsource/roboto/400.css';
10 | import '@fontsource/roboto/500.css';
11 | import '@fontsource/roboto/700.css';
12 |
13 | // Import key components
14 | import Interact from './components/Interact'
15 | import Conversations from './components/Conversations';
16 | import About from './components/About';
17 | import Header from './components/Header';
18 |
19 | // Bot related imports
20 | import { Interactions } from 'aws-amplify';
21 | import AWSLex2Provider from '@thefat32/aws-amplify-lex-provider-v2';
22 |
23 | // Amplify components section
24 | import Amplify from 'aws-amplify';
25 | import awsmobile from './aws-exports';
26 | import {withAuthenticator} from '@aws-amplify/ui-react'
27 |
28 |
29 | // Start of body
30 | Interactions.addPluggable(new AWSLex2Provider())
31 |
32 | Amplify.configure({
33 | ...awsmobile,
34 | bots: {
35 | "AWS-Configurator": {
36 | botId: "FJZEEWWPBU",
37 | botAliasId: "G0UH3YLBPS",
38 | localeId: "en_US",
39 | region: "us-east-1",
40 | providerName: "AWSLex2Provider"
41 | }
42 | }
43 | })
44 |
45 | function App() {
46 | return (
47 |
48 | {/* Header Component */}
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | );
58 | }
59 |
60 | export default withAuthenticator(App);
61 | // export default App;
62 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/ec2-terminate/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"ec2-terminate","identifier":"MTCLLOJKJP","description":null,"parentIntentSignature":null,"sampleUtterances":[{"utterance":"Terminate these instances"},{"utterance":"Terminate selected instances"}],"intentConfirmationSetting":null,"intentClosingSetting":null,"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"FulfillIntent","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":[{"name":"selected-instances","timeToLiveInSeconds":null,"turnsToLive":null}],"outputContexts":null,"kendraConfiguration":null,"dialogCodeHook":null,"fulfillmentCodeHook":{"postFulfillmentStatusSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null},"fulfillmentUpdatesSpecification":null,"enabled":true},"slotPriorities":[]}
--------------------------------------------------------------------------------
/src/components/Header.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | // React imports
4 | import { useHistory } from 'react-router';
5 |
6 | // Material UI components
7 | import { Button, IconButton } from '@mui/material';
8 | import { AppBar, Box, Toolbar, Typography} from '@mui/material';
9 | import { Link } from 'react-router-dom';
10 | import { Menu as MenuIcon } from '@mui/icons-material';
11 |
12 | // Amplify imports
13 | import Auth from '@aws-amplify/auth';
14 | import { Hub } from '@aws-amplify/core';
15 |
16 |
17 | const Header = () => {
18 |
19 | let history = useHistory()
20 | const signout = async () => {
21 | try {
22 | await Auth.signOut();
23 | Hub.dispatch('UI Auth', { // channel must be 'UI Auth'
24 | event: 'AuthStateChange', // event must be 'AuthStateChange'
25 | message: 'signedout' // message must be 'signedout'
26 | });
27 | } catch (error) {
28 | console.log('error signing out: ', error);
29 | }
30 | }
31 |
32 | return (
33 |
34 | theme.zIndex.drawer + 1}}>
35 |
36 |
37 |
38 |
39 | Cloud Assistant
40 |
41 | {/* */}
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | )
50 | }
51 |
52 | export default Header
53 |
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/s3-copy-to-new-bucket/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"s3-copy-to-new-bucket","identifier":"GNOURKBS0J","description":null,"parentIntentSignature":null,"sampleUtterances":[{"utterance":"copy files to new S3 bucket"},{"utterance":"copy files to new bucket"},{"utterance":"copy search results to new S3 bucket"},{"utterance":"copy search results to new bucket"}],"intentConfirmationSetting":null,"intentClosingSetting":null,"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"FulfillIntent","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":null,"outputContexts":null,"kendraConfiguration":null,"dialogCodeHook":null,"fulfillmentCodeHook":{"postFulfillmentStatusSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null},"fulfillmentUpdatesSpecification":null,"enabled":true},"slotPriorities":[]}
--------------------------------------------------------------------------------
/amplify/backend/backend-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "api": {
3 | "awsAssistantBackend": {
4 | "output": {
5 | "authConfig": {
6 | "additionalAuthenticationProviders": [],
7 | "defaultAuthentication": {
8 | "authenticationType": "AMAZON_COGNITO_USER_POOLS",
9 | "userPoolConfig": {
10 | "userPoolId": "authawsassistantfcd2b45d"
11 | }
12 | }
13 | }
14 | },
15 | "providerPlugin": "awscloudformation",
16 | "service": "AppSync"
17 | }
18 | },
19 | "auth": {
20 | "awsassistantfcd2b45d": {
21 | "customAuth": false,
22 | "dependsOn": [],
23 | "frontendAuthConfig": {
24 | "loginMechanisms": [
25 | "EMAIL"
26 | ],
27 | "mfaConfiguration": "OFF",
28 | "mfaTypes": [
29 | "SMS"
30 | ],
31 | "passwordProtectionSettings": {
32 | "passwordPolicyCharacters": [],
33 | "passwordPolicyMinLength": 8
34 | },
35 | "signupAttributes": [
36 | "EMAIL"
37 | ],
38 | "verificationMechanisms": [
39 | "EMAIL"
40 | ]
41 | },
42 | "providerPlugin": "awscloudformation",
43 | "service": "Cognito"
44 | }
45 | },
46 | "function": {
47 | "assistantFulfillment": {
48 | "build": true,
49 | "providerPlugin": "awscloudformation",
50 | "service": "Lambda"
51 | }
52 | },
53 | "hosting": {
54 | "amplifyhosting": {
55 | "providerPlugin": "awscloudformation",
56 | "service": "amplifyhosting",
57 | "type": "manual"
58 | }
59 | },
60 | "parameters": {
61 | "AMPLIFY_hosting_amplifyhosting_appId": {
62 | "usedBy": [
63 | {
64 | "category": "hosting",
65 | "resourceName": "amplifyhosting"
66 | }
67 | ]
68 | },
69 | "AMPLIFY_hosting_amplifyhosting_type": {
70 | "usedBy": [
71 | {
72 | "category": "hosting",
73 | "resourceName": "amplifyhosting"
74 | }
75 | ]
76 | }
77 | }
78 | }
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/set-region/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"set-region","identifier":"LGDQ1GV02P","description":"Used to change the region in which the chatbot will operate. Does this through context variable.","parentIntentSignature":null,"sampleUtterances":[{"utterance":"Change region to {region}"},{"utterance":"set the primary region to {region}"},{"utterance":"use the {region} region"}],"intentConfirmationSetting":null,"intentClosingSetting":null,"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"ElicitSlot","suppressNextMessage":null,"slotToElicit":"region"}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":null,"outputContexts":null,"kendraConfiguration":null,"dialogCodeHook":null,"fulfillmentCodeHook":{"postFulfillmentStatusSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null},"fulfillmentUpdatesSpecification":null,"enabled":true},"slotPriorities":[{"priority":1,"slotName":"region"}]}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/get-help/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"get-help","identifier":"1WNHGFB5PE","description":null,"parentIntentSignature":"AMAZON.HelpIntent","sampleUtterances":null,"intentConfirmationSetting":null,"intentClosingSetting":{"isActive":true,"closingResponse":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"I can help you configure various AWS services by relying solely on your natural language input. "},"imageResponseCard":null},"variations":[{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"I can help you perform various types of operations on resources like instances, buckets, security group rules..."},"imageResponseCard":null},{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"Here are a few example requests you can try: \"show me all my instances\", \"find all instances running on t2 micro\", \"Launch a windows instance\", \"list all my S3 buckets\"..."},"imageResponseCard":null}]}],"allowInterrupt":true},"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}}},"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"CloseIntent","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":null,"outputContexts":null,"kendraConfiguration":null,"dialogCodeHook":null,"fulfillmentCodeHook":null,"slotPriorities":[]}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/sg-rule-list/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"sg-rule-list","identifier":"XRWX0WJ0BQ","description":null,"parentIntentSignature":null,"sampleUtterances":[{"utterance":"are there any wide open rules in my security group?"},{"utterance":"is all inbound traffic allowed through my security group?"},{"utterance":"what ports are open to everyone from the internet in my security group?"},{"utterance":"list unrestricted security group rules"}],"intentConfirmationSetting":null,"intentClosingSetting":null,"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"FulfillIntent","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":null,"outputContexts":[{"name":"selected-sg-rules","timeToLiveInSeconds":3600,"turnsToLive":5}],"kendraConfiguration":null,"dialogCodeHook":null,"fulfillmentCodeHook":{"postFulfillmentStatusSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null},"fulfillmentUpdatesSpecification":null,"enabled":true},"slotPriorities":[]}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/s3-create-bucket/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"s3-create-bucket","identifier":"WXAVI2MATO","description":null,"parentIntentSignature":null,"sampleUtterances":[{"utterance":"Create a bucket named {bucketName} "},{"utterance":"Create a bucket with the following name: {bucketName} "},{"utterance":"Create an S3 bucket named {bucketName} "},{"utterance":"Create an S3 bucket"},{"utterance":"Create a new S3 bucket named {bucketName}"}],"intentConfirmationSetting":null,"intentClosingSetting":null,"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"ElicitSlot","suppressNextMessage":null,"slotToElicit":"bucketName"}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":null,"outputContexts":[{"name":"s3-bucket-created","timeToLiveInSeconds":3600,"turnsToLive":5}],"kendraConfiguration":null,"dialogCodeHook":null,"fulfillmentCodeHook":{"postFulfillmentStatusSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null},"fulfillmentUpdatesSpecification":null,"enabled":true},"slotPriorities":[{"priority":1,"slotName":"bucketName"}]}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/ec2-create/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"ec2-create","identifier":"KACQBIDTL5","description":null,"parentIntentSignature":null,"sampleUtterances":[{"utterance":"Create {count} {ami} instances on {instanceType} instance class"},{"utterance":"Launch {count} {instanceType} instances using {ami} image"},{"utterance":"Start {count} {ami} instances using the {instanceType} instance type"},{"utterance":"launch {count} {ami} instances"},{"utterance":"launch a {ami} instance"},{"utterance":"launch a {instanceType} instance"}],"intentConfirmationSetting":null,"intentClosingSetting":null,"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"ElicitSlot","suppressNextMessage":null,"slotToElicit":"instanceType"}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":null,"outputContexts":[{"name":"selected-instances","timeToLiveInSeconds":90,"turnsToLive":5}],"kendraConfiguration":null,"dialogCodeHook":null,"fulfillmentCodeHook":{"postFulfillmentStatusSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null},"fulfillmentUpdatesSpecification":null,"enabled":true},"slotPriorities":[{"priority":3,"slotName":"ami"},{"priority":1,"slotName":"count"},{"priority":2,"slotName":"instanceType"}]}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/sg-rule-replace/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"sg-rule-replace","identifier":"Q9UC9PRMEV","description":null,"parentIntentSignature":null,"sampleUtterances":[{"utterance":"Restrict source traffic for selected rules to my ip address only"},{"utterance":"Modify selected security group rules to allow traffic from my ip address only"},{"utterance":"Replace source traffic in selected rules with jump box ip address"},{"utterance":"restrict source traffic for selected rules to {ipAddress} only"},{"utterance":"Modify selected security group rules to allow traffic from {ipAddress} only"}],"intentConfirmationSetting":null,"intentClosingSetting":null,"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"FulfillIntent","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":[{"name":"selected-sg-rules","timeToLiveInSeconds":null,"turnsToLive":null}],"outputContexts":null,"kendraConfiguration":null,"dialogCodeHook":{"enabled":false},"fulfillmentCodeHook":{"postFulfillmentStatusSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null},"fulfillmentUpdatesSpecification":null,"enabled":true},"slotPriorities":[{"priority":1,"slotName":"ipAddress"}]}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/ec2-list/Slots/ami/Slot.json:
--------------------------------------------------------------------------------
1 | {"name":"ami","identifier":"PHNFHUT0YR","description":null,"slotTypeName":"ami","obfuscationSetting":null,"valueElicitationSetting":{"slotCaptureSetting":{"codeHook":null,"captureResponse":null,"captureNextStep":null,"captureConditional":null,"failureResponse":null,"failureNextStep":null,"failureConditional":null,"elicitationCodeHook":{"enableCodeHookInvocation":true,"invocationLabel":null}},"promptSpecification":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"what AMI would you like to filter by?"},"imageResponseCard":null},"variations":null}],"maxRetries":4,"allowInterrupt":true,"messageSelectionStrategy":"Random","promptAttemptsSpecification":{"Retry2":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry3":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Initial":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry1":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry4":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}}}},"slotConstraint":"Optional","defaultValueSpecification":null,"sampleUtterances":null,"waitAndContinueSpecification":null},"multipleValuesSetting":null}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/ec2-list/Slots/subnetType/Slot.json:
--------------------------------------------------------------------------------
1 | {"name":"subnetType","identifier":"JEUR57U2KJ","description":null,"slotTypeName":"subnetType","obfuscationSetting":null,"valueElicitationSetting":{"slotCaptureSetting":{"codeHook":null,"captureResponse":null,"captureNextStep":null,"captureConditional":null,"failureResponse":null,"failureNextStep":null,"failureConditional":null,"elicitationCodeHook":{"enableCodeHookInvocation":true,"invocationLabel":null}},"promptSpecification":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"what type of subnet? private or public?"},"imageResponseCard":null},"variations":null}],"maxRetries":4,"allowInterrupt":true,"messageSelectionStrategy":"Random","promptAttemptsSpecification":{"Retry2":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry3":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Initial":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry1":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry4":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}}}},"slotConstraint":"Optional","defaultValueSpecification":null,"sampleUtterances":null,"waitAndContinueSpecification":null},"multipleValuesSetting":null}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/sg-rule-replace/Slots/ipAddress/Slot.json:
--------------------------------------------------------------------------------
1 | {"name":"ipAddress","identifier":"MPXNSWPEXY","description":null,"slotTypeName":"ipAddress","obfuscationSetting":null,"valueElicitationSetting":{"slotCaptureSetting":{"codeHook":null,"captureResponse":null,"captureNextStep":null,"captureConditional":null,"failureResponse":null,"failureNextStep":null,"failureConditional":null,"elicitationCodeHook":{"enableCodeHookInvocation":true,"invocationLabel":null}},"promptSpecification":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"What ip address would you like to use?"},"imageResponseCard":null},"variations":null}],"maxRetries":4,"allowInterrupt":true,"messageSelectionStrategy":"Random","promptAttemptsSpecification":{"Retry2":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry3":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Initial":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry1":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry4":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}}}},"slotConstraint":"Optional","defaultValueSpecification":null,"sampleUtterances":null,"waitAndContinueSpecification":null},"multipleValuesSetting":null}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/ec2-list/Slots/instanceType/Slot.json:
--------------------------------------------------------------------------------
1 | {"name":"instanceType","identifier":"AUE1VX4VWG","description":null,"slotTypeName":"instanceType","obfuscationSetting":null,"valueElicitationSetting":{"slotCaptureSetting":{"codeHook":null,"captureResponse":null,"captureNextStep":null,"captureConditional":null,"failureResponse":null,"failureNextStep":null,"failureConditional":null,"elicitationCodeHook":{"enableCodeHookInvocation":true,"invocationLabel":null}},"promptSpecification":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"what instance type would you like to filter by?"},"imageResponseCard":null},"variations":null}],"maxRetries":4,"allowInterrupt":true,"messageSelectionStrategy":"Random","promptAttemptsSpecification":{"Retry2":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry3":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Initial":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry1":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry4":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}}}},"slotConstraint":"Optional","defaultValueSpecification":null,"sampleUtterances":null,"waitAndContinueSpecification":null},"multipleValuesSetting":null}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/ec2-create/Slots/count/Slot.json:
--------------------------------------------------------------------------------
1 | {"name":"count","identifier":"LQNOCFUSWT","description":null,"slotTypeName":"AMAZON.Number","obfuscationSetting":null,"valueElicitationSetting":{"slotCaptureSetting":{"codeHook":null,"captureResponse":null,"captureNextStep":null,"captureConditional":null,"failureResponse":null,"failureNextStep":null,"failureConditional":null,"elicitationCodeHook":{"enableCodeHookInvocation":true,"invocationLabel":null}},"promptSpecification":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"how many instances would you like to launch?"},"imageResponseCard":null},"variations":null}],"maxRetries":4,"allowInterrupt":true,"messageSelectionStrategy":"Random","promptAttemptsSpecification":{"Retry2":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry3":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Initial":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry1":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry4":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}}}},"slotConstraint":"Optional","defaultValueSpecification":{"defaultValueList":[{"defaultValue":"1"}]},"sampleUtterances":null,"waitAndContinueSpecification":null},"multipleValuesSetting":null}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/s3-search/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"s3-search","identifier":"DBES2PYJL2","description":null,"parentIntentSignature":null,"sampleUtterances":[{"utterance":"search for {objName} in all s3 buckets"},{"utterance":"search for files named {objName} in S3"},{"utterance":"Search for {objName} in S3"},{"utterance":"search for s3 objects containing {objName}"},{"utterance":"search for {objName} in bucket {bucketIndex}"},{"utterance":"search for files named {objName} in bucket {bucketIndex}"},{"utterance":"Search for {objName} in S3 bucket {bucketIndex}"},{"utterance":"search for s3 objects containing {objName} in bucket {bucketIndex}"},{"utterance":"search for objects containing {objName} across all buckets"},{"utterance":"search for {objName} across all buckets?"},{"utterance":"search for objects containing the keyword {objName} in S3"},{"utterance":"search for objects containing the keyword {objName} in bucket {bucketIndex}"}],"intentConfirmationSetting":null,"intentClosingSetting":null,"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"ElicitSlot","suppressNextMessage":null,"slotToElicit":"objName"}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":null,"outputContexts":[{"name":"s3-search-results","timeToLiveInSeconds":3600,"turnsToLive":5}],"kendraConfiguration":null,"dialogCodeHook":{"enabled":false},"fulfillmentCodeHook":{"postFulfillmentStatusSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null},"fulfillmentUpdatesSpecification":null,"enabled":true},"slotPriorities":[{"priority":1,"slotName":"bucketIndex"},{"priority":2,"slotName":"objName"}]}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/s3-search/Slots/bucketIndex/Slot.json:
--------------------------------------------------------------------------------
1 | {"name":"bucketIndex","identifier":"NNKVS4BM9K","description":null,"slotTypeName":"AMAZON.Number","obfuscationSetting":null,"valueElicitationSetting":{"slotCaptureSetting":{"codeHook":null,"captureResponse":null,"captureNextStep":null,"captureConditional":null,"failureResponse":null,"failureNextStep":null,"failureConditional":null,"elicitationCodeHook":{"enableCodeHookInvocation":true,"invocationLabel":null}},"promptSpecification":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"Please specify the index of the bucket where the search should be performed."},"imageResponseCard":null},"variations":null}],"maxRetries":4,"allowInterrupt":true,"messageSelectionStrategy":"Random","promptAttemptsSpecification":{"Retry2":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry3":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Initial":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry1":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry4":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}}}},"slotConstraint":"Optional","defaultValueSpecification":null,"sampleUtterances":null,"waitAndContinueSpecification":null},"multipleValuesSetting":null}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/ec2-list/Intent.json:
--------------------------------------------------------------------------------
1 | {"name":"ec2-list","identifier":"DX3WYFGOTL","description":null,"parentIntentSignature":null,"sampleUtterances":[{"utterance":"List all EC2 instances"},{"utterance":"what instances are in my account? "},{"utterance":"show my instances"},{"utterance":"list all instances with a {ami} image"},{"utterance":"list all instances of type {instanceType}"},{"utterance":"list all {instanceType} instances"},{"utterance":"list my {ami} instances"},{"utterance":"do I have any instances in a {subnetType} subnet?"},{"utterance":"are there any instances deployed to a {subnetType} subnet?"}],"intentConfirmationSetting":null,"intentClosingSetting":{"isActive":true,"closingResponse":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"Requested instances have been listed."},"imageResponseCard":null},"variations":null}],"allowInterrupt":true},"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}}},"initialResponseSetting":{"codeHook":{"isActive":true,"enableCodeHookInvocation":true,"invocationLabel":null,"postCodeHookSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"successConditional":null,"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutConditional":null,"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"FulfillIntent","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null}},"conditional":null,"nextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"InvokeDialogCodeHook","suppressNextMessage":null,"slotToElicit":null}},"initialResponse":null},"inputContexts":null,"outputContexts":[{"name":"selected-instances","timeToLiveInSeconds":3600,"turnsToLive":5}],"kendraConfiguration":null,"dialogCodeHook":null,"fulfillmentCodeHook":{"postFulfillmentStatusSpecification":{"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"timeoutResponse":null,"timeoutNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"EndConversation","suppressNextMessage":null,"slotToElicit":null}},"successNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"CloseIntent","suppressNextMessage":null,"slotToElicit":null}},"successResponse":null},"fulfillmentUpdatesSpecification":null,"enabled":true},"slotPriorities":[{"priority":2,"slotName":"instanceType"},{"priority":3,"slotName":"subnetType"},{"priority":1,"slotName":"ami"}]}
--------------------------------------------------------------------------------
/src/graphql/queries.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // this is an auto generated file. This will be overwritten
3 |
4 | export const getConversation = /* GraphQL */ `
5 | query GetConversation($id: ID!) {
6 | getConversation(id: $id) {
7 | id
8 | name
9 | user
10 | description
11 | createdAt
12 | utterances {
13 | items {
14 | id
15 | text
16 | author
17 | conversationId
18 | data
19 | createdAt
20 | updatedAt
21 | owner
22 | }
23 | nextToken
24 | }
25 | updatedAt
26 | owner
27 | }
28 | }
29 | `;
30 | export const listConversations = /* GraphQL */ `
31 | query ListConversations(
32 | $filter: ModelConversationFilterInput
33 | $limit: Int
34 | $nextToken: String
35 | ) {
36 | listConversations(filter: $filter, limit: $limit, nextToken: $nextToken) {
37 | items {
38 | id
39 | name
40 | user
41 | description
42 | createdAt
43 | utterances {
44 | nextToken
45 | }
46 | updatedAt
47 | owner
48 | }
49 | nextToken
50 | }
51 | }
52 | `;
53 | export const getUtterance = /* GraphQL */ `
54 | query GetUtterance($id: ID!) {
55 | getUtterance(id: $id) {
56 | id
57 | text
58 | author
59 | conversationId
60 | data
61 | createdAt
62 | updatedAt
63 | owner
64 | }
65 | }
66 | `;
67 | export const listUtterances = /* GraphQL */ `
68 | query ListUtterances(
69 | $filter: ModelUtteranceFilterInput
70 | $limit: Int
71 | $nextToken: String
72 | ) {
73 | listUtterances(filter: $filter, limit: $limit, nextToken: $nextToken) {
74 | items {
75 | id
76 | text
77 | author
78 | conversationId
79 | data
80 | createdAt
81 | updatedAt
82 | owner
83 | }
84 | nextToken
85 | }
86 | }
87 | `;
88 | export const conversationsByUser = /* GraphQL */ `
89 | query ConversationsByUser(
90 | $user: String!
91 | $createdAt: ModelStringKeyConditionInput
92 | $sortDirection: ModelSortDirection
93 | $filter: ModelConversationFilterInput
94 | $limit: Int
95 | $nextToken: String
96 | ) {
97 | conversationsByUser(
98 | user: $user
99 | createdAt: $createdAt
100 | sortDirection: $sortDirection
101 | filter: $filter
102 | limit: $limit
103 | nextToken: $nextToken
104 | ) {
105 | items {
106 | id
107 | name
108 | user
109 | description
110 | createdAt
111 | utterances {
112 | nextToken
113 | }
114 | updatedAt
115 | owner
116 | }
117 | nextToken
118 | }
119 | }
120 | `;
121 |
--------------------------------------------------------------------------------
/src/graphql/subscriptions.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // this is an auto generated file. This will be overwritten
3 |
4 | export const onCreateConversation = /* GraphQL */ `
5 | subscription OnCreateConversation($owner: String) {
6 | onCreateConversation(owner: $owner) {
7 | id
8 | name
9 | user
10 | description
11 | createdAt
12 | utterances {
13 | items {
14 | id
15 | text
16 | author
17 | conversationId
18 | data
19 | createdAt
20 | updatedAt
21 | owner
22 | }
23 | nextToken
24 | }
25 | updatedAt
26 | owner
27 | }
28 | }
29 | `;
30 | export const onUpdateConversation = /* GraphQL */ `
31 | subscription OnUpdateConversation($owner: String) {
32 | onUpdateConversation(owner: $owner) {
33 | id
34 | name
35 | user
36 | description
37 | createdAt
38 | utterances {
39 | items {
40 | id
41 | text
42 | author
43 | conversationId
44 | data
45 | createdAt
46 | updatedAt
47 | owner
48 | }
49 | nextToken
50 | }
51 | updatedAt
52 | owner
53 | }
54 | }
55 | `;
56 | export const onDeleteConversation = /* GraphQL */ `
57 | subscription OnDeleteConversation($owner: String) {
58 | onDeleteConversation(owner: $owner) {
59 | id
60 | name
61 | user
62 | description
63 | createdAt
64 | utterances {
65 | items {
66 | id
67 | text
68 | author
69 | conversationId
70 | data
71 | createdAt
72 | updatedAt
73 | owner
74 | }
75 | nextToken
76 | }
77 | updatedAt
78 | owner
79 | }
80 | }
81 | `;
82 | export const onCreateUtterance = /* GraphQL */ `
83 | subscription OnCreateUtterance($owner: String) {
84 | onCreateUtterance(owner: $owner) {
85 | id
86 | text
87 | author
88 | conversationId
89 | data
90 | createdAt
91 | updatedAt
92 | owner
93 | }
94 | }
95 | `;
96 | export const onUpdateUtterance = /* GraphQL */ `
97 | subscription OnUpdateUtterance($owner: String) {
98 | onUpdateUtterance(owner: $owner) {
99 | id
100 | text
101 | author
102 | conversationId
103 | data
104 | createdAt
105 | updatedAt
106 | owner
107 | }
108 | }
109 | `;
110 | export const onDeleteUtterance = /* GraphQL */ `
111 | subscription OnDeleteUtterance($owner: String) {
112 | onDeleteUtterance(owner: $owner) {
113 | id
114 | text
115 | author
116 | conversationId
117 | data
118 | createdAt
119 | updatedAt
120 | owner
121 | }
122 | }
123 | `;
124 |
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/ec2-create/Slots/ami/Slot.json:
--------------------------------------------------------------------------------
1 | {"name":"ami","identifier":"IZ0MEJG2WX","description":null,"slotTypeName":"ami","obfuscationSetting":null,"valueElicitationSetting":{"slotCaptureSetting":{"codeHook":null,"captureResponse":null,"captureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"FulfillIntent","suppressNextMessage":null,"slotToElicit":null}},"captureConditional":null,"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":{"name":"FallbackIntent","slots":null},"dialogAction":{"type":"StartIntent","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"elicitationCodeHook":{"enableCodeHookInvocation":true,"invocationLabel":null}},"promptSpecification":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"what AMI would you like to use?"},"imageResponseCard":null},"variations":null}],"maxRetries":4,"allowInterrupt":true,"messageSelectionStrategy":"Random","promptAttemptsSpecification":{"Retry2":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry3":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Initial":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry1":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry4":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}}}},"slotConstraint":"Required","defaultValueSpecification":null,"sampleUtterances":null,"waitAndContinueSpecification":null},"multipleValuesSetting":null}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/set-region/Slots/region/Slot.json:
--------------------------------------------------------------------------------
1 | {"name":"region","identifier":"HIYSFNM8II","description":null,"slotTypeName":"region","obfuscationSetting":null,"valueElicitationSetting":{"slotCaptureSetting":{"codeHook":null,"captureResponse":null,"captureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"FulfillIntent","suppressNextMessage":null,"slotToElicit":null}},"captureConditional":null,"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":{"name":"FallbackIntent","slots":null},"dialogAction":{"type":"StartIntent","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"elicitationCodeHook":{"enableCodeHookInvocation":true,"invocationLabel":null}},"promptSpecification":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"what AWS region would you like to use?"},"imageResponseCard":null},"variations":null}],"maxRetries":4,"allowInterrupt":true,"messageSelectionStrategy":"Random","promptAttemptsSpecification":{"Retry2":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry3":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Initial":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry1":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry4":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}}}},"slotConstraint":"Required","defaultValueSpecification":null,"sampleUtterances":null,"waitAndContinueSpecification":null},"multipleValuesSetting":null}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/s3-search/Slots/objName/Slot.json:
--------------------------------------------------------------------------------
1 | {"name":"objName","identifier":"YBVCG8SQ0Q","description":null,"slotTypeName":"AMAZON.AlphaNumeric","obfuscationSetting":null,"valueElicitationSetting":{"slotCaptureSetting":{"codeHook":null,"captureResponse":null,"captureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"FulfillIntent","suppressNextMessage":null,"slotToElicit":null}},"captureConditional":null,"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":{"name":"FallbackIntent","slots":null},"dialogAction":{"type":"StartIntent","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"elicitationCodeHook":{"enableCodeHookInvocation":true,"invocationLabel":null}},"promptSpecification":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"what string are you searching for?"},"imageResponseCard":null},"variations":null}],"maxRetries":4,"allowInterrupt":true,"messageSelectionStrategy":"Random","promptAttemptsSpecification":{"Retry2":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry3":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Initial":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry1":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry4":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}}}},"slotConstraint":"Required","defaultValueSpecification":null,"sampleUtterances":null,"waitAndContinueSpecification":null},"multipleValuesSetting":null}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/ec2-create/Slots/instanceType/Slot.json:
--------------------------------------------------------------------------------
1 | {"name":"instanceType","identifier":"MRE0NEMBUU","description":null,"slotTypeName":"instanceType","obfuscationSetting":null,"valueElicitationSetting":{"slotCaptureSetting":{"codeHook":null,"captureResponse":null,"captureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"ElicitSlot","suppressNextMessage":null,"slotToElicit":"ami"}},"captureConditional":null,"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":{"name":"FallbackIntent","slots":null},"dialogAction":{"type":"StartIntent","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"elicitationCodeHook":{"enableCodeHookInvocation":true,"invocationLabel":null}},"promptSpecification":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"what type of instance would you like to use?"},"imageResponseCard":null},"variations":null}],"maxRetries":4,"allowInterrupt":true,"messageSelectionStrategy":"Random","promptAttemptsSpecification":{"Retry2":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry3":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Initial":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry1":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry4":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}}}},"slotConstraint":"Required","defaultValueSpecification":null,"sampleUtterances":null,"waitAndContinueSpecification":null},"multipleValuesSetting":null}
--------------------------------------------------------------------------------
/bot/cloud-assistant/BotLocales/en_US/Intents/s3-create-bucket/Slots/bucketName/Slot.json:
--------------------------------------------------------------------------------
1 | {"name":"bucketName","identifier":"M7WIPBBW1F","description":null,"slotTypeName":"AMAZON.AlphaNumeric","obfuscationSetting":null,"valueElicitationSetting":{"slotCaptureSetting":{"codeHook":null,"captureResponse":null,"captureNextStep":{"sessionAttributes":null,"intent":null,"dialogAction":{"type":"FulfillIntent","suppressNextMessage":null,"slotToElicit":null}},"captureConditional":null,"failureResponse":null,"failureNextStep":{"sessionAttributes":null,"intent":{"name":"FallbackIntent","slots":null},"dialogAction":{"type":"StartIntent","suppressNextMessage":null,"slotToElicit":null}},"failureConditional":null,"elicitationCodeHook":{"enableCodeHookInvocation":true,"invocationLabel":null}},"promptSpecification":{"messageGroupsList":[{"message":{"ssmlMessage":null,"customPayload":null,"plainTextMessage":{"value":"what would you like to name your bucket?"},"imageResponseCard":null},"variations":null}],"maxRetries":4,"allowInterrupt":true,"messageSelectionStrategy":"Random","promptAttemptsSpecification":{"Retry2":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry3":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Initial":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry1":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}},"Retry4":{"allowedInputTypes":{"allowAudioInput":true,"allowDTMFInput":true},"audioAndDTMFInputSpecification":{"dtmfSpecification":{"maxLength":513,"deletionCharacter":"*","endCharacter":"#","endTimeoutMs":5000},"startTimeoutMs":4000,"audioSpecification":{"maxLengthMs":15000,"endTimeoutMs":640}},"allowInterrupt":true,"textInputSpecification":{"startTimeoutMs":30000}}}},"slotConstraint":"Required","defaultValueSpecification":null,"sampleUtterances":null,"waitAndContinueSpecification":null},"multipleValuesSetting":null}
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4 | documentation, we greatly value feedback and contributions from our community.
5 |
6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7 | information to effectively respond to your bug report or contribution.
8 |
9 |
10 | ## Reporting Bugs/Feature Requests
11 |
12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features.
13 |
14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already
15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
16 |
17 | * A reproducible test case or series of steps
18 | * The version of our code being used
19 | * Any modifications you've made relevant to the bug
20 | * Anything unusual about your environment or deployment
21 |
22 |
23 | ## Contributing via Pull Requests
24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
25 |
26 | 1. You are working against the latest source on the *main* branch.
27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
29 |
30 | To send us a pull request, please:
31 |
32 | 1. Fork the repository.
33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
34 | 3. Ensure local tests pass.
35 | 4. Commit to your fork using clear commit messages.
36 | 5. Send us a pull request, answering any default questions in the pull request interface.
37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
38 |
39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
41 |
42 |
43 | ## Finding contributions to work on
44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
45 |
46 |
47 | ## Code of Conduct
48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
50 | opensource-codeofconduct@amazon.com with any additional questions or comments.
51 |
52 |
53 | ## Security issue notifications
54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
55 |
56 |
57 | ## Licensing
58 |
59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
60 |
--------------------------------------------------------------------------------
/src/graphql/mutations.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // this is an auto generated file. This will be overwritten
3 |
4 | export const createConversation = /* GraphQL */ `
5 | mutation CreateConversation(
6 | $input: CreateConversationInput!
7 | $condition: ModelConversationConditionInput
8 | ) {
9 | createConversation(input: $input, condition: $condition) {
10 | id
11 | name
12 | user
13 | description
14 | createdAt
15 | utterances {
16 | items {
17 | id
18 | text
19 | author
20 | conversationId
21 | data
22 | createdAt
23 | updatedAt
24 | owner
25 | }
26 | nextToken
27 | }
28 | updatedAt
29 | owner
30 | }
31 | }
32 | `;
33 | export const updateConversation = /* GraphQL */ `
34 | mutation UpdateConversation(
35 | $input: UpdateConversationInput!
36 | $condition: ModelConversationConditionInput
37 | ) {
38 | updateConversation(input: $input, condition: $condition) {
39 | id
40 | name
41 | user
42 | description
43 | createdAt
44 | utterances {
45 | items {
46 | id
47 | text
48 | author
49 | conversationId
50 | data
51 | createdAt
52 | updatedAt
53 | owner
54 | }
55 | nextToken
56 | }
57 | updatedAt
58 | owner
59 | }
60 | }
61 | `;
62 | export const deleteConversation = /* GraphQL */ `
63 | mutation DeleteConversation(
64 | $input: DeleteConversationInput!
65 | $condition: ModelConversationConditionInput
66 | ) {
67 | deleteConversation(input: $input, condition: $condition) {
68 | id
69 | name
70 | user
71 | description
72 | createdAt
73 | utterances {
74 | items {
75 | id
76 | text
77 | author
78 | conversationId
79 | data
80 | createdAt
81 | updatedAt
82 | owner
83 | }
84 | nextToken
85 | }
86 | updatedAt
87 | owner
88 | }
89 | }
90 | `;
91 | export const createUtterance = /* GraphQL */ `
92 | mutation CreateUtterance(
93 | $input: CreateUtteranceInput!
94 | $condition: ModelUtteranceConditionInput
95 | ) {
96 | createUtterance(input: $input, condition: $condition) {
97 | id
98 | text
99 | author
100 | conversationId
101 | data
102 | createdAt
103 | updatedAt
104 | owner
105 | }
106 | }
107 | `;
108 | export const updateUtterance = /* GraphQL */ `
109 | mutation UpdateUtterance(
110 | $input: UpdateUtteranceInput!
111 | $condition: ModelUtteranceConditionInput
112 | ) {
113 | updateUtterance(input: $input, condition: $condition) {
114 | id
115 | text
116 | author
117 | conversationId
118 | data
119 | createdAt
120 | updatedAt
121 | owner
122 | }
123 | }
124 | `;
125 | export const deleteUtterance = /* GraphQL */ `
126 | mutation DeleteUtterance(
127 | $input: DeleteUtteranceInput!
128 | $condition: ModelUtteranceConditionInput
129 | ) {
130 | deleteUtterance(input: $input, condition: $condition) {
131 | id
132 | text
133 | author
134 | conversationId
135 | data
136 | createdAt
137 | updatedAt
138 | owner
139 | }
140 | }
141 | `;
142 |
--------------------------------------------------------------------------------
/src/components/About.js:
--------------------------------------------------------------------------------
1 | import { Card, CardContent, Grid, Typography, List, ListItem } from '@mui/material'
2 | import React from 'react'
3 |
4 | const About = () => {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 | About the Cloud Assistant
13 |
14 |
15 | The Cloud assistant provides users with a conversational
16 | interface leveraging Natural Language Understanding (NLU) to interact with various AWS services and
17 | automates/performs all sorts of simple or advanced operations on behalf of users. It allows users to
18 | manage their AWS accounts using natural language thus reducing time spent navigating the AWS
19 | console or figuring out the proper CLI commands.
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | Example EC2 Queries
31 |
32 | * Can you show me all my ec2 instances?
33 | * Launch 1 linux instance on t2 micro
34 | * Launch 2 windows instances on t3 micro
35 | * List ec2 instances
36 | * Find all windows instances
37 | * Find all instances running on t2 micro
38 | * Are there instances deployed to a public subnet?
39 | * Terminate these instances
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | Example S3 Queries
48 |
49 | * Show me all my S3 buckets
50 | * Search for "py" in bucket 7
51 | * Search for "ppt" in bucket 7
52 | * Search for "ppt" across all buckets
53 | * Create a new S3 bucket
54 | * Copy found files to new bucket
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | Other Example Queries
65 |
66 | * Switch region to ohio
67 | * Switch back region to Virginia
68 | * Are there any wide open security group rules?
69 | * Modify security group rules to allow traffic from 10.11.12.13
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | )
79 | }
80 |
81 | export default About
82 |
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/assistantFulfillment-cloudformation-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "AWSTemplateFormatVersion": "2010-09-09",
3 | "Description": "{\"createdOn\":\"Windows\",\"createdBy\":\"Amplify\",\"createdWith\":\"8.0.2\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
4 | "Parameters": {
5 | "CloudWatchRule": {
6 | "Type": "String",
7 | "Default": "NONE",
8 | "Description": " Schedule Expression"
9 | },
10 | "deploymentBucketName": {
11 | "Type": "String"
12 | },
13 | "env": {
14 | "Type": "String"
15 | },
16 | "s3Key": {
17 | "Type": "String"
18 | }
19 | },
20 | "Conditions": {
21 | "ShouldNotCreateEnvResources": {
22 | "Fn::Equals": [
23 | {
24 | "Ref": "env"
25 | },
26 | "NONE"
27 | ]
28 | }
29 | },
30 | "Resources": {
31 | "LambdaFunction": {
32 | "Type": "AWS::Lambda::Function",
33 | "Metadata": {
34 | "aws:asset:path": "./src",
35 | "aws:asset:property": "Code"
36 | },
37 | "Properties": {
38 | "Code": {
39 | "S3Bucket": {
40 | "Ref": "deploymentBucketName"
41 | },
42 | "S3Key": {
43 | "Ref": "s3Key"
44 | }
45 | },
46 | "Handler": "index.handler",
47 | "FunctionName": {
48 | "Fn::If": [
49 | "ShouldNotCreateEnvResources",
50 | "assistantFulfillment",
51 | {
52 | "Fn::Join": [
53 | "",
54 | [
55 | "assistantFulfillment",
56 | "-",
57 | {
58 | "Ref": "env"
59 | }
60 | ]
61 | ]
62 | }
63 | ]
64 | },
65 | "Environment": {
66 | "Variables": {
67 | "ENV": {
68 | "Ref": "env"
69 | },
70 | "REGION": {
71 | "Ref": "AWS::Region"
72 | }
73 | }
74 | },
75 | "Role": {
76 | "Fn::GetAtt": [
77 | "LambdaExecutionRole",
78 | "Arn"
79 | ]
80 | },
81 | "Runtime": "python3.8",
82 | "Layers": [],
83 | "Timeout": 60
84 | }
85 | },
86 | "LambdaExecutionRole": {
87 | "Type": "AWS::IAM::Role",
88 | "Properties": {
89 | "RoleName": {
90 | "Fn::If": [
91 | "ShouldNotCreateEnvResources",
92 | "awsassistantLambdaRole70d4ed92",
93 | {
94 | "Fn::Join": [
95 | "",
96 | [
97 | "awsassistantLambdaRole70d4ed92",
98 | "-",
99 | {
100 | "Ref": "env"
101 | }
102 | ]
103 | ]
104 | }
105 | ]
106 | },
107 | "AssumeRolePolicyDocument": {
108 | "Version": "2012-10-17",
109 | "Statement": [
110 | {
111 | "Effect": "Allow",
112 | "Principal": {
113 | "Service": [
114 | "lambda.amazonaws.com"
115 | ]
116 | },
117 | "Action": [
118 | "sts:AssumeRole"
119 | ]
120 | }
121 | ]
122 | }
123 | }
124 | },
125 | "lambdaexecutionpolicy": {
126 | "DependsOn": [
127 | "LambdaExecutionRole"
128 | ],
129 | "Type": "AWS::IAM::Policy",
130 | "Properties": {
131 | "PolicyName": "lambda-execution-policy",
132 | "Roles": [
133 | {
134 | "Ref": "LambdaExecutionRole"
135 | }
136 | ],
137 | "PolicyDocument": {
138 | "Version": "2012-10-17",
139 | "Statement": [
140 | {
141 | "Effect": "Allow",
142 | "Action": [
143 | "logs:CreateLogGroup",
144 | "logs:CreateLogStream",
145 | "logs:PutLogEvents"
146 | ],
147 | "Resource": {
148 | "Fn::Sub": [
149 | "arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:*",
150 | {
151 | "region": {
152 | "Ref": "AWS::Region"
153 | },
154 | "account": {
155 | "Ref": "AWS::AccountId"
156 | },
157 | "lambda": {
158 | "Ref": "LambdaFunction"
159 | }
160 | }
161 | ]
162 | }
163 | }
164 | ]
165 | }
166 | }
167 | },
168 | "CustomLambdaExecutionPolicy": {
169 | "Type": "AWS::IAM::Policy",
170 | "Properties": {
171 | "PolicyName": "custom-lambda-execution-policy",
172 | "PolicyDocument": {
173 | "Version": "2012-10-17",
174 | "Statement": [
175 | {
176 | "Action": [
177 | "ec2:*"
178 | ],
179 | "Resource": [
180 | "*"
181 | ],
182 | "Effect": "Allow"
183 | },
184 | {
185 | "Action": [
186 | "s3:*"
187 | ],
188 | "Resource": [
189 | "*"
190 | ],
191 | "Effect": "Allow"
192 | }
193 | ]
194 | },
195 | "Roles": [
196 | {
197 | "Ref": "LambdaExecutionRole"
198 | }
199 | ]
200 | },
201 | "DependsOn": "LambdaExecutionRole"
202 | }
203 | },
204 | "Outputs": {
205 | "Name": {
206 | "Value": {
207 | "Ref": "LambdaFunction"
208 | }
209 | },
210 | "Arn": {
211 | "Value": {
212 | "Fn::GetAtt": [
213 | "LambdaFunction",
214 | "Arn"
215 | ]
216 | }
217 | },
218 | "Region": {
219 | "Value": {
220 | "Ref": "AWS::Region"
221 | }
222 | },
223 | "LambdaExecutionRole": {
224 | "Value": {
225 | "Ref": "LambdaExecutionRole"
226 | }
227 | }
228 | }
229 | }
--------------------------------------------------------------------------------
/src/components/ResponseCard.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | // Material Imports
4 | import { Grid, Card, Typography, CardContent, CardActions, Button } from "@mui/material"
5 | import { Alert } from "@mui/material";
6 | import { Stack } from "@mui/material";
7 | import LaunchIcon from "@mui/icons-material/Launch"
8 |
9 | // My components
10 | import MyFlexibleTable from './MyFlexibleTable'
11 |
12 |
13 |
14 | const ResponseCard = ({intent, cardDescription, data}) => {
15 |
16 | const getCardTitle = () => {
17 | console.log('Getting card title')
18 | let cardTitle = ""
19 | switch(intent){
20 | case 'ec2-list':
21 | cardTitle = 'EC2 Instance List'
22 | break
23 | case 'ec2-create':
24 | cardTitle = 'New EC2 Instance'
25 | break
26 | case 'ec2-terminate':
27 | cardTitle = 'Terminated EC2 Instance'
28 | break
29 | case 's3-copy-to-new-bucket':
30 | cardTitle = 'S3 Object Copy'
31 | break
32 | case 's3-create-bucket':
33 | cardTitle = 'New S3 Bucket'
34 | break
35 | case 's3-list-buckets':
36 | cardTitle = 'S3 Bucket List'
37 | break
38 | case 's3-search':
39 | cardTitle = 'S3 Search Results'
40 | break
41 | case 'set-region':
42 | cardTitle = 'Region Switch'
43 | break
44 | case 'sg-rule-list':
45 | cardTitle = 'Security Group Rules'
46 | break
47 | default:
48 | cardTitle = intent
49 | }
50 | return cardTitle
51 | }
52 |
53 |
54 | const getVisual = () => {
55 | const visual = ""
56 |
57 | let rows = []
58 | let cols = []
59 | switch(intent){
60 |
61 | case 'ec2-list':
62 | // console.log("Building visual for instance list")
63 | // console.log(data)
64 | const allInstanceData = JSON.parse(data.sessionAttributes.instances)
65 | if(allInstanceData.length === 0) return (null)
66 |
67 | allInstanceData.forEach(instance => {
68 | const AZ = instance.Placement.AvailabilityZone
69 | const state = instance.State.Name
70 | delete instance.Placement
71 | delete instance.State
72 | delete instance.KeyName
73 | instance.AZ = AZ
74 | instance.State = state
75 |
76 | if (!("PublicIpAddress" in instance)){
77 | instance.PublicIpAddress = "N/A";
78 | }else{
79 | const publicIp = instance.PublicIpAddress
80 | delete instance.PublicIpAddress
81 | instance.PublicIpAddress = publicIp
82 | }
83 | // console.log(instance)
84 | rows.push(Object.values(instance))
85 | })
86 | cols = Object.keys(allInstanceData[0])
87 | const rowIndex = cols.indexOf('InstanceId')
88 | return
89 |
90 | case 'ec2-create':
91 | const newInstancesData = JSON.parse(data.sessionAttributes.instances)
92 | return (
93 |
94 | {newInstancesData.map((instanceData) => (
95 | Instance {instanceData.InstanceId} was launched successfully with the following private IP: {instanceData.PrivateIpAddress}
96 | ))}
97 |
98 | )
99 |
100 | case 'ec2-terminate':
101 | const terminatedInstancesData = JSON.parse(data.sessionAttributes.instances)
102 | return (
103 |
104 | {terminatedInstancesData.map((instanceData) => (
105 | Instance {instanceData.InstanceId} was successfully terminated
106 | ))}
107 |
108 |
109 | )
110 |
111 | case 's3-copy-to-new-bucket':
112 | break
113 |
114 | case 's3-create-bucket':
115 | break
116 |
117 | case 's3-list-buckets':
118 | // console.log("Building visual for bucket list")
119 | const allBucketData = JSON.parse(data.sessionAttributes['s3-bucket-list'])
120 | // console.log(allBucketData)
121 | if(allBucketData.length === 0) return (null)
122 | cols = ['Index', 'Bucket Name', 'Creation Date', 'Versioning']
123 | for (let i=0; i < allBucketData.length; i++){
124 | rows.push([i+1, allBucketData[i].Name, allBucketData[i].CreationDate, allBucketData[i].Versioning.toString()])
125 | }
126 | return
127 |
128 | case 's3-search':
129 | const searchResultsData = JSON.parse(data.sessionAttributes['s3-found-objects'])
130 | console.log(searchResultsData)
131 | if(searchResultsData.length === 0) return (null)
132 | cols = ['Object Key', 'Bucket Name', 'Last Modified', 'Size', 'Storage Class']
133 | for (let i=0; i < searchResultsData.length; i++){
134 | rows.push([searchResultsData[i].Key, searchResultsData[i].Bucket, searchResultsData[i].LastModified, searchResultsData[i]['Size'], searchResultsData[i].StorageClass])
135 | }
136 | return
137 |
138 | case 'set-region':
139 | break
140 |
141 | case 'sg-rule-list':
142 | break
143 |
144 | default:
145 | return visual
146 | }
147 | return visual
148 | }
149 |
150 |
151 | return (
152 |
153 |
154 |
155 |
156 | {getCardTitle()}
157 |
158 |
159 | {cardDescription}
160 |
161 | {getVisual()}
162 |
163 | {Object.keys(data).length > 0 &&
164 |
165 |
166 |
167 |
168 | }
169 |
170 |
171 |
172 | )
173 | }
174 |
175 | export default React.memo(ResponseCard)
176 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # The Cloud Assistant
2 |
3 | This application demonstrates how AWS Amplify can be used to build and deploy an automated AWS account management web application powered by a conversational AI built with Amazon Lex (Figure 1). This application (hereinafter referred to as the cloud assistant) provides users with a conversational interface leveraging Natural Language Understanding (NLU) to interact with various AWS services and automates/performs all sorts of simple or advanced operations on behalf of users. It allows users to manage their AWS accounts using natural language thus reducing time spent navigating the AWS console or figuring out the proper CLI commands. You can use this sample application as an example of how Amplify in combination with other AWS services can be used to build any other kind of assistant-powered web application.
4 |
5 | For more information, please read the associated AWS blog post here.
6 |
7 | *Figure 1: Application Architecture*
8 |
9 | This project uses React framework and leverages AWS Amplify. This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
10 |
11 | [[_TOC_]]
12 |
13 | ## Pre-Requisites
14 | - AWS Account
15 | - Install NodeJS and NPM
16 | - Install and configure AWS Amplify CLI
17 | - Install Amplify CLI using: ```npm install -g @aws-amplify/cli```
18 | - Configure Amplify profile using: ```amplify configure```
19 | - Prepare Python Environment
20 | - Install Python 3.8
21 | - Create virtualenv using: ```python -m venv pathToEnv```
22 | - Activate python virtualenv using: ```source pathToEnv/Scripts/activate```
23 | - Install pipenv in virtual environment with ```pip3 install pipenv```
24 |
25 | > Important: make sure to run all subsequent Amplify commands with the python virtual environment activated!
26 |
27 |
28 | ## Step I - Initialize and deploy Amplify backend
29 | Initialize the Amplify project with: ```amplify init --app https://github.com/aws-samples/aws-amplify-cloud-assistant-app.git```. The command will:
30 | - Clone the repository into local directory (i.e., where command is run)
31 | - Initialize Amplify project: Make sure to select Amplify profile created during ```amplify configure``` step.
32 | - Deploy the application backend (Auth, Api, Lambda, Hosting)
33 | - Configure the frontend to use the backend
34 | - Start the application on a local development server
35 |
36 | After the command has completed, open the repository directory in your favorite code editor (e.g. Visual Studio Code)
37 |
38 | ## Step II - Create the assistant bot using Amazon Lex
39 | 1. Create a zip file containing the contents of “bot” directory
40 | 2. Navigate to the Amazon Lex console and click "Get Started"
41 | - Select "Import" from the "Action" dropdown to import the bot
42 | - Name the bot and upload the zip file created in step 1
43 | - Select Create a role with basic Amazon Lex permissions
44 | - Choose "No" under the Children's Online Privacy Protection Act (COPPA)
45 | - Set the session timeout to 5 minutes
46 | 3. Build the draft version of the bot
47 | - Select the newly created bot, and navigate to the "Intents" section of the "Draft version"
48 | - Select the "Build" button at the top and wait for the build to finish
49 | 4. Create a new bot version
50 | - Navigate to the "Bot versions" section from the left-hand menu
51 | - Click "Create version", and push the "Create" button
52 | 5. Create a new Alias for the bot to be used by the application
53 | - Navigate to the "Aliases" section of the menu and select "Create alias"
54 | - Name the alias "AliasForApp" Choose the newly created version (i.e. Version 1)
55 | - Navigate to the newly created alias, click on "English (US)" to choose the backend lambda
56 | - Choose the assistantFulfillment-{envName} lambda with "$LATEST" version, and save
57 |
58 |
59 |
60 | ## Step III - Integrate bot with application front-end
61 | 1. Take note of key bot information from the Lex console
62 | - Locate the Bot ID from the bot page
63 | - Locate the Bot Alias ID from the Alias page
64 | 2. Edit the App.js under the src folder of the repository
65 | - Update the bot ID (line 36)
66 | - Update the bot alias ID (line 37)
67 | - Update the region if bot was not deployed to us-east-1
68 | 3. Allow the Cognito Auth role access to the Lex bot
69 | - Navigate to the "Roles" section of the IAM console
70 | - Search for the "authRole". Select role matching this format: amplify-awsassistant-sampledev-{number}-authRole
71 | - Select "Attach Policies" from the "Add permissions" drop down.
72 | - Search for this policy "AmazonLexRunBotsOnly", select it, and click "Attach policies"
73 |
74 |
75 | ## Step IV - Publish and test application
76 | 1. Publish the application front-end using ```amplify publish```
77 | 2. Navigate to the Amplify console, select the "awsassistant" app
78 | 3. Select the "Hosting environments" tab, and copy the Domain URL
79 | 4. Open a new web browser tab, and navigate to the copied URL
80 | 5. Select "Create account" to create a new account and login
81 | - Provide a username (should be an email), password, email, and phone number. Click "Create Account"
82 | - Due to the privileges given to authenticated users, a confirmation code will not be sent
83 | - Click "Back to Sign In", and follow next step to confirm user
84 | 6. To confirm the user, navigate to the Cognito service on the AWS console
85 | - Select "User Pools", and select the assistant user pool
86 | - Navigate to "Users" tab, and select the new user (should have an "Unconfirmed" status)
87 | - Click on "Actions" button at the top of the page, then "Confirm account", and confirm
88 | 7. Sign in to the application
89 | - Sign in with your previously created username and password
90 | - You can choose to configure account recovery or skip it
91 | 8. Select "NEW CONVERSATION" to create a new conversation with the assistant
92 | - Provide a title and description for the conversation, and click "Create"
93 | 9. Navigate to the newly created conversation
94 | - Click on "GO TO CONVERSATION" on your newly created conversation card
95 | - Try out the example commands below (e.g. "Launch 1 linux instance on t2 micro")
96 |
97 | ## Example Commands
98 |
99 | #### EC2 Instance Commands
100 | ```
101 | > Can you show me all my ec2 instances?
102 | > Launch 1 linux instance on t2 micro
103 | > Launch 2 red hat instances on t3 micro
104 | > List ec2 instances
105 | > Find all red hat instances
106 | > Find all instances running on t2 micro
107 | > Are there any instances deployed to a public subnet?
108 | > Terminate these instances (Note: Make sure to run this command AFTER a previous command has already identified some instances such as any of the commands above)
109 | ```
110 |
116 | #### Security Group Rules Commands
117 | ```
118 | > Are there any wide open security group rules? (Note: if this command returns no rules, edit the default security group through the AWS console, and introduce some rules with access from 0.0.0.0 on a couple of ports (e.g. HTTP or SSH), then try the command again)
119 | > Modify security group rules to allow traffic from 10.11.12.13
120 | ```
121 |
122 | #### S3 Commands
123 | ```
124 | > Show me all my S3 buckets
125 | > Search for "py" in bucket 7 (Note: replace number with bucket index from the "list S3 buckets" command)
126 | > Search for "ppt" in bucket 7 (Note: replace number with bucket index from the "list S3 buckets" command)
127 | > Search for "ppt" across all buckets
128 | > Create a new S3 bucket (Note: the assistant will follow-up to ask you for a bucket name. Do not include any spaces in the bucket name)
129 | > Copy found files to new bucket
130 | ```
131 |
132 |
133 |
134 | ## Cleanup
135 | To cleanup all created resources, perform the following:
136 | - Navigate to the Amplify console, select the “awsassistant” app, click the Actions dropdown and select “Delete App”
137 | - Navigate to the Amazon Lex console, select the assistant bot, click the Actions dropdown, and select “Delete”
138 |
139 |
140 |
--------------------------------------------------------------------------------
/src/components/Conversations.js:
--------------------------------------------------------------------------------
1 |
2 | // React imports
3 | import React, { useEffect } from 'react'
4 | import { useState } from 'react'
5 | import { Link } from 'react-router-dom'
6 |
7 | // Material UI Imports
8 | import { Box } from '@mui/system'
9 | import { Stack } from '@mui/material'
10 | import { Button, Card, CardMedia, CardContent, CardActions, Typography, Grid } from '@mui/material'
11 | // import { createTheme } from '@mui/system'
12 | import { TextField } from '@mui/material'
13 | import {Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from '@mui/material'
14 |
15 | // Amplify imports
16 | import {API, graphqlOperation} from 'aws-amplify'
17 | import Auth from '@aws-amplify/auth'
18 |
19 | // GraphQL code imports
20 | import { createConversation, deleteConversation } from '../graphql/mutations'
21 | import { conversationsByUser } from '../graphql/queries'
22 |
23 | // Other imports
24 | import image from '../images/banner.jpg'
25 |
26 | // // Create theme
27 | // const theme = createTheme({
28 | // status: {
29 | // danger: '#e53e3e',
30 | // },
31 | // palette: {
32 | // primary: {
33 | // main: '#0971f1',
34 | // darker: '#053e85',
35 | // },
36 | // neutral: {
37 | // main: '#64748B',
38 | // contrastText: '#fff',
39 | // },
40 | // },
41 | // });
42 |
43 |
44 | const createConversationHandler = async(handleCreateDialog, name, description, userConversations, setUserConversations) => {
45 | console.log('Create conversation wil happen here...')
46 |
47 | // Close dialog
48 | handleCreateDialog(false)
49 |
50 | // Create conversation
51 | let conversation = {
52 | name: name,
53 | description: description,
54 | user: Auth.user.attributes.email
55 | }
56 | console.log(conversation)
57 | console.log(Auth.user)
58 |
59 | // Call mutation
60 | let result = await API.graphql(graphqlOperation(createConversation, {input: conversation}))
61 | let newConversationObj = result.data.createConversation
62 | console.log(newConversationObj)
63 |
64 | // Update state information
65 | setUserConversations(userConversations => [...userConversations, newConversationObj])
66 | }
67 |
68 | const fetchUserConversations = async() => {
69 | // Get username
70 | const userId = Auth.user.attributes.email
71 |
72 | // Call query
73 | let result = await API.graphql(graphqlOperation(conversationsByUser, {user: userId, sortDirection: "DESC"}))
74 | return result
75 | }
76 |
77 | const deleteConversationHandler = async(handleDeleteDialog, conversationToRemove, userConversations, setUserConversations) => {
78 |
79 | // Close dialog
80 | handleDeleteDialog(false)
81 |
82 | // API call
83 | console.log("Removing conversation: ", conversationToRemove.id)
84 | let result = await API.graphql(graphqlOperation(deleteConversation, {input: {id: conversationToRemove.id}}))
85 |
86 | // Remove from list
87 | setUserConversations(userConversations.filter((conversation) => conversation.id !== conversationToRemove.id))
88 |
89 | }
90 |
91 | const Conversations = () => {
92 |
93 | // create conversation dialog state
94 | const [createDialogOpen, setCreateDialogOpen] = useState(false)
95 | const [deleteDialogOpen, setDeleteDialogOpen] = useState(false)
96 | const [conversationToDelete, setConversationToDelete] = useState(null)
97 | const [conversationName, setConversationName] = useState("")
98 | const [conversationDescription, setConversationDescription] = useState("")
99 | const [userConversations, setUserConversations] = useState([])
100 |
101 | // Effect to initialize conversations
102 | useEffect(() => {
103 | async function loadUserConversations() {
104 | const result = await fetchUserConversations()
105 | const userConversations = result.data.conversationsByUser.items
106 | console.log(userConversations)
107 | setUserConversations(userConversations)
108 |
109 | }
110 | loadUserConversations()
111 | }, [])
112 |
113 |
114 | // Create Dialog handler
115 | const handleCreateDialog = (desiredState) => {
116 | setCreateDialogOpen(desiredState)
117 |
118 | if(desiredState === false){
119 | setConversationName("")
120 | setConversationDescription("")
121 | }
122 | }
123 | // Delete Dialog handler
124 | const handleDeleteDialog = (desiredState, conversation) => {
125 | setDeleteDialogOpen(desiredState)
126 |
127 | if(desiredState === true){
128 | setConversationToDelete(conversation)
129 | }
130 | }
131 |
132 | return (
133 |
134 |
135 |
136 |
143 |
144 |
145 |
181 |
201 |
202 |
203 |
204 | Previous Conversations
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 | {userConversations.map((conversation) => (
213 |
214 | {/* */}
215 |
216 |
217 |
218 |
219 | {conversation.name}
220 |
221 |
222 | Description - {conversation.description}
223 |
224 |
225 |
226 |
227 | Created On: {conversation.createdAt}
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 | {/* */}
245 |
246 |
247 |
248 | ))}
249 |
250 |
251 | {/*
252 |
253 | */}
254 |
255 |
256 | )
257 | }
258 |
259 | export default Conversations
260 |
--------------------------------------------------------------------------------
/src/components/Interact.js:
--------------------------------------------------------------------------------
1 | // React Components
2 | import * as React from 'react';
3 | import { useState, useEffect, useRef } from 'react';
4 | import { useParams } from 'react-router';
5 |
6 | // Material Components
7 | import { Grid, Divider} from '@mui/material';
8 | import { Typography } from '@mui/material';
9 | import { Box, Drawer, Toolbar, List, ListItem, ListItemText } from '@mui/material';
10 | import SendIcon from '@mui/icons-material/Send'
11 | import { IconButton } from '@mui/material';
12 | import { ListItemAvatar, Avatar } from '@mui/material';
13 | import { blue, orange } from '@mui/material/colors';
14 | import ResponseCard from './ResponseCard';
15 | import MyTextField from './MyTextField';
16 | import { LinearProgress } from '@mui/material';
17 |
18 | // Amplify Imports
19 | import Interactions from '@aws-amplify/interactions';
20 | import Auth from '@aws-amplify/auth';
21 |
22 | // GraphQL imports
23 | import {API, graphqlOperation} from 'aws-amplify'
24 | import { getConversation } from '../graphql/queries';
25 | import { createUtterance } from '../graphql/mutations';
26 |
27 |
28 | // Initial values for state variables
29 | const chatWidth = 360
30 | const initialDialogs = [
31 | {
32 | text: "Hello, How can I help you today?",
33 | author: "AWS"
34 | },
35 | ]
36 | const initialAnswers = [
37 | {
38 | intent: "Introducing the Cloud Assistant",
39 | description: "The Cloud Assistant is an AI designed to help you configure your AWS account using natural language. The assistant leverages advanced NLU (Natural Language Understanding) models as well as a flexible fullfillment serverless backend to perform all sorts of simple or advanced configurations in your AWS account on your behalf.",
40 | data: {}
41 | },
42 | ]
43 |
44 |
45 | // Component for AWS dialog item
46 | const AwsDialogItem = ({text}) => {
47 | return (
48 |
49 |
50 | AWS
51 |
52 | {text}
55 | }
56 | />
57 |
58 | )
59 | }
60 |
61 | // Component for user dialog item
62 | const MeDialogItem = ({text, reusePreviousDialog, userInitials}) => (
63 |
64 | {text}
67 | }
68 | />
69 |
70 | {userInitials}
71 |
72 |
73 | )
74 |
75 | const fetchConversationDetails = async(conversationId) => {
76 |
77 | // Make API call
78 | console.log('Fetching conversation: ', conversationId)
79 | let result = await API.graphql(graphqlOperation(getConversation, {id: conversationId}))
80 | return result
81 |
82 | }
83 |
84 | const Interact = () => {
85 |
86 | // Get parameters
87 | let { conversationId } = useParams()
88 |
89 | // Define state variables here
90 | const [dialogs, setDialogs] = useState(initialDialogs)
91 | const [newQuery, setNewQuery] = useState("")
92 | const [answers, setAnswers] = useState(initialAnswers)
93 | const [loading, setLoading] = useState(false)
94 | const [userInitials, setUserInitials] = useState("")
95 | const [conversation, setConversation] = useState(null)
96 |
97 | // References
98 | const scrollRef = useRef(null)
99 | const dialogScrollRef = useRef(null)
100 |
101 | // Effects
102 | useEffect(() => {
103 | if (scrollRef.current) {
104 | scrollRef.current.scrollIntoView({behaviour: "smooth"})
105 | }
106 | }, [answers])
107 |
108 | useEffect(() => {
109 | if (dialogScrollRef.current) {
110 | dialogScrollRef.current.scrollIntoView({behaviour: "smooth"})
111 | }
112 | }, [dialogs])
113 |
114 | // Effect for loading user
115 | useEffect(() => {
116 | let username = Auth.user.attributes.email
117 | console.log('Logged username: ', username)
118 | const userInitials = username.substring(0, 2).toUpperCase()
119 | console.log('Logged user initials: ', userInitials)
120 | setUserInitials(userInitials)
121 | }, [])
122 |
123 | // Effect for loading conversation
124 | useEffect(() => {
125 | async function loadConversationDetails(){
126 | let result = await fetchConversationDetails(conversationId)
127 |
128 | // set conversation state
129 | if(result) {
130 | let conversation = result.data.getConversation
131 | setConversation(conversation)
132 | console.log(conversation)
133 |
134 | // Get utterances
135 | const utterances = conversation.utterances.items
136 |
137 | // Set dialogs state
138 | let dialogsArray = initialDialogs.concat(utterances)
139 | setDialogs(dialogsArray)
140 |
141 | // Set answers state
142 | let answersArray = []
143 | utterances.forEach((utterance) => {
144 | if (utterance.author !== "AWS") return
145 | if (utterance.data === "{}") return
146 | const responseData = JSON.parse(utterance.data)
147 | console.log(responseData)
148 | answersArray.push({
149 | intent: responseData.sessionState.intent.name,
150 | description: responseData.messages[0].content,
151 | data: responseData.sessionState
152 | })
153 | })
154 | console.log('Cards will be built from the answers below')
155 | console.log(answersArray)
156 |
157 | // Set the answers state
158 | answersArray.unshift(initialAnswers[0])
159 | setAnswers(answersArray)
160 |
161 | }
162 |
163 | }
164 | loadConversationDetails()
165 | }, [])
166 |
167 |
168 | // Define function for creating dialog item
169 | const createDialogEntry = async(author, text, data, conversationId) => {
170 |
171 | // Create dialog object
172 | const newDialog = {
173 | author: author,
174 | text: text
175 | }
176 |
177 | // Add dialog object to dialogs state
178 | setDialogs(prevDialogs => [...prevDialogs, newDialog])
179 | console.log('New dialog was created and added to state:' + newDialog)
180 |
181 | // API call to persist in DB
182 | let conversation = {
183 | author: author,
184 | text: text,
185 | data: data,
186 | conversationId
187 | }
188 | let result = await API.graphql(graphqlOperation(createUtterance, {input: conversation}))
189 | console.log("Create utterance in this conversation")
190 | console.log(result)
191 |
192 | }
193 |
194 | // Define functions that update state
195 | const sendQuery = async () => {
196 |
197 | // Create dialog entry
198 | await createDialogEntry(userInitials, newQuery, {}, conversationId)
199 |
200 | // Reset the query field and show loader
201 | setNewQuery("")
202 | setLoading(true)
203 |
204 | // Send query to assistant
205 | const response = await Interactions.send("AWS-Configurator", newQuery)
206 |
207 | // // Get IP address
208 | // const res = await axios.get('https://geolocation-db.com/json/')
209 | // console.log(res.data);
210 |
211 |
212 | // Remove load and log response
213 | setLoading(false)
214 | console.log(response)
215 |
216 | // Check if messages exist
217 | if(response.messages) {
218 |
219 | // Add answer to answer state if dialog is closed
220 | if (response.sessionState.dialogAction.type === "Close") {
221 | const newAnswer = {intent: response.sessionState.intent.name, description: response.messages[0].content, data: response.sessionState}
222 | setAnswers(prevAnswers => [...prevAnswers, newAnswer])
223 | console.log(answers)
224 | await createDialogEntry('AWS', response.messages[0].content, JSON.stringify({messages: response.messages, sessionState: response.sessionState}), conversationId)
225 | }else{
226 | await createDialogEntry('AWS', response.messages[0].content, {}, conversationId)
227 | }
228 | }
229 | // Fall back intent
230 | else{
231 | const fallbackText = "Sorry, can you say that again?"
232 | await createDialogEntry('AWS', fallbackText, {}, conversationId)
233 | }
234 |
235 | }
236 |
237 | // Send query if users clicks on the ENTER key
238 | const handleKeyPress = (e) => {
239 | // console.log('--->A key was pressed', e.keyCode)
240 | if(e.keyCode === 13){
241 | console.log('value', e.target.value);
242 | sendQuery()
243 | }
244 | }
245 |
246 | // Send button component
247 | const SendButton = () => (
248 |
249 |
250 |
251 | )
252 |
253 | // Initialize query text with previous query
254 | const reusePreviousDialog = (e) => {
255 | console.log(e)
256 | setNewQuery(e.target.textContent)
257 | }
258 |
259 | return (
260 |
261 |
262 | {/* DRAWER SECTION - DIALOG SECTION */}
263 |
274 |
275 |
276 |
277 | {dialogs.map((dialog, index) => (
278 |
279 | {dialog.author === "AWS" ? : }
280 |
281 |
282 | ))}
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 | {/* MAIN CONTENT SECTION FOR SHOWING ASSISTANT RESPONSE DATA */}
291 |
292 | {/*
293 | {conversation.name}
294 |
*/}
295 |
296 | {answers.map((answer, index) => (
297 | <>
298 |
299 | >
300 | ))}
301 |
302 | {loading && }
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 | )
311 | }
312 |
313 | export default Interact
314 |
315 |
--------------------------------------------------------------------------------
/amplify/backend/function/assistantFulfillment/src/index.py:
--------------------------------------------------------------------------------
1 | """
2 | This code sample demonstrates an implementation of the Lex Code Hook Interface
3 | in order to serve a bot which manages dentist appointments.
4 | Bot, Intent, and Slot models which are compatible with this sample can be found in the Lex Console
5 | as part of the 'MakeAppointment' template.
6 |
7 | For instructions on how to set up and test this bot, as well as additional samples,
8 | visit the Lex Getting Started documentation http://docs.aws.amazon.com/lex/latest/dg/getting-started.html.
9 | """
10 |
11 | import json
12 | import dateutil.parser
13 | import datetime
14 | import time
15 | import os
16 | import math
17 | import random
18 | import logging
19 | import boto3
20 | import copy
21 | from botocore.config import Config
22 | from botocore.exceptions import ClientError
23 |
24 | logger = logging.getLogger()
25 | logger.setLevel(logging.INFO)
26 |
27 |
28 |
29 | """ --- Helpers to build responses which match the structure of the necessary dialog actions --- """
30 |
31 |
32 | def elicit_slot(session_attributes, intent_name, slots, slot_to_elicit, message, response_card):
33 | return {
34 | 'sessionAttributes': session_attributes,
35 | 'dialogAction': {
36 | 'type': 'ElicitSlot',
37 | 'intentName': intent_name,
38 | 'slots': slots,
39 | 'slotToElicit': slot_to_elicit,
40 | 'message': message,
41 | 'responseCard': response_card
42 | }
43 | }
44 |
45 |
46 | def confirm_intent(session_attributes, intent_name, slots, message, response_card):
47 | return {
48 | 'sessionAttributes': session_attributes,
49 | 'dialogAction': {
50 | 'type': 'ConfirmIntent',
51 | 'intentName': intent_name,
52 | 'slots': slots,
53 | 'message': message,
54 | 'responseCard': response_card
55 | }
56 | }
57 |
58 |
59 | def close(session_attributes, fulfillment_state, message):
60 | response = {
61 | 'sessionAttributes': session_attributes,
62 | 'dialogAction': {
63 | 'type': 'Close',
64 | 'fulfillmentState': fulfillment_state,
65 | 'message': message
66 | }
67 | }
68 |
69 | return response
70 |
71 |
72 | def delegate(session_attributes, slots):
73 | return {
74 | 'sessionAttributes': session_attributes,
75 | 'dialogAction': {
76 | 'type': 'Delegate',
77 | 'slots': slots
78 | }
79 | }
80 |
81 |
82 | def build_response_card(title, subtitle, options):
83 | """
84 | Build a responseCard with a title, subtitle, and an optional set of options which should be displayed as buttons.
85 | """
86 | buttons = None
87 | if options is not None:
88 | buttons = []
89 | for i in range(min(5, len(options))):
90 | buttons.append(options[i])
91 |
92 | return {
93 | 'contentType': 'application/vnd.amazonaws.card.generic',
94 | 'version': 1,
95 | 'genericAttachments': [{
96 | 'title': title,
97 | 'subTitle': subtitle,
98 | 'buttons': buttons
99 | }]
100 | }
101 |
102 |
103 |
104 | def buildConfig(intent_request):
105 |
106 | # Get session attributes
107 | sessionAttributes = intent_request['sessionState'].get('sessionAttributes')
108 |
109 | # Set region to virginia if no session attributes or region variable
110 | if not sessionAttributes or sessionAttributes.get('region') is None:
111 | region = 'us-east-1'
112 | else:
113 | region = sessionAttributes['region']
114 |
115 | # Create dict config
116 | my_config = Config(
117 | region_name = region,
118 | signature_version = 'v4',
119 | retries = {
120 | 'max_attempts': 10,
121 | 'mode': 'standard'
122 | }
123 | )
124 |
125 | # Return config
126 | return my_config
127 |
128 |
129 | """ --- Intents --- """
130 | def listInstances(intent_request):
131 | logger.info('Received a request to list EC2 instances')
132 |
133 | # Build config
134 | config = buildConfig(intent_request)
135 |
136 | # Create client
137 | ec2 = boto3.client('ec2', config = config)
138 |
139 | # Get optional filter variables
140 | slots = intent_request['sessionState']['intent']['slots']
141 | instanceAmi = slots['ami']
142 | instanceType = slots['instanceType']
143 | subnetType = slots['subnetType']
144 |
145 | # Build list of filters
146 | filters = []
147 | if instanceAmi is not None:
148 | filters.append({
149 | 'Name': 'image-id',
150 | 'Values': [instanceAmi['value']['interpretedValue']]
151 | })
152 |
153 | if instanceType is not None:
154 | filters.append({
155 | 'Name': 'instance-type',
156 | 'Values': [instanceType['value']['interpretedValue']]
157 | })
158 |
159 |
160 |
161 | # Describe instances
162 | response = ec2.describe_instances(Filters = filters)
163 | instancesFilteredAttributes = filterInstanceAttributes(response)
164 |
165 | # Additional filtering (for filters that requires additional API calls)
166 | if subnetType is not None:
167 | instancesFilteredAttributes = filterInstancesBySubnetType(ec2, instancesFilteredAttributes, subnetType['value']['interpretedValue'])
168 |
169 | # Extract instance Ids
170 | instanceIds = [instance['InstanceId'] for instance in instancesFilteredAttributes]
171 | logger.info(instancesFilteredAttributes)
172 |
173 | # Add instance to session attributes
174 | sessionAttributes = updateSessionAttributes(intent_request, 'instances', json.dumps(instancesFilteredAttributes, default=str))
175 |
176 | # Prepare resulting message
177 | if len(filters) > 0 or subnetType is not None:
178 | # message = "You have a total of {} instances based on your filters. InstanceIds are: {}. Additional information is attached.".format(len(instancesFilteredAttributes), instanceIds)
179 | message = "You have a total of {} instances based on your filters. Additional information is attached".format(len(instancesFilteredAttributes))
180 | else:
181 | # message = "You have a total of {} instances. InstanceIds are: {}. Additional information is attached.".format(len(instancesFilteredAttributes), instanceIds)
182 | message = "You have a total of {} instances. Additional information is attached.".format(len(instancesFilteredAttributes))
183 |
184 |
185 |
186 | # Add selected-instances context
187 | # contexts = [{
188 | # 'name': 'selected-instances',
189 | # 'contextAttributes': {},
190 | # 'timeToLive': {
191 | # 'timeToLiveInSeconds': 3600,
192 | # 'turnsToLive': 5
193 | # }
194 | # }]
195 |
196 |
197 | # Return response
198 | intentName = intent_request['sessionState']['intent']['name']
199 | return prepareResponse(intentName, sessionAttributes, message, [])
200 |
201 |
202 |
203 | def filterInstanceAttributes(ec2DescribeResponse):
204 |
205 | # Aggregate instances
206 | instances = []
207 | for reservation in ec2DescribeResponse.get('Reservations'):
208 | reservationInstances = reservation.get('Instances')
209 | instances += reservationInstances
210 |
211 | # Filter instance attributes
212 | desiredAttributes = ['ImageId', 'InstanceId', 'InstanceType', 'State', 'KeyName', 'LaunchTime', 'Placement', 'PrivateIpAddress', 'PublicIpAddress', 'SubnetId']
213 | instancesFilteredAttributes = [{attribute:value for attribute, value in instance.items() if attribute in desiredAttributes} for instance in instances]
214 |
215 | # Eliminate terminated instances
216 | instancesFilteredAttributes = [instance for instance in instancesFilteredAttributes if instance['State']['Name'] != 'terminated']
217 |
218 | # Return
219 | return instancesFilteredAttributes
220 |
221 |
222 | def filterInstancesBySubnetType(ec2, instances, targetSubnetType):
223 |
224 | # Initialize results
225 | filteredInstances = []
226 |
227 | # Loop through instances
228 | for instance in instances:
229 |
230 | # Get subnet type for instance
231 | subnetType = getSubnetType(ec2, instance['SubnetId'])
232 | print(subnetType, targetSubnetType)
233 | if subnetType != targetSubnetType: continue
234 |
235 | # Store in filtered instances
236 | instance['SubnetType'] = subnetType
237 | filteredInstances.append(instance)
238 |
239 | # Return instances
240 | return filteredInstances
241 |
242 |
243 | def getSubnetType(ec2, subnetId):
244 |
245 | # Get subnet's route table
246 | response = ec2.describe_route_tables(Filters = [{'Name': 'association.subnet-id', 'Values': [subnetId]}])
247 | RouteTable = response['RouteTables']
248 |
249 | # Check if subnet is associated with main table
250 | if not RouteTable:
251 | # print('Subnet is associated with main route table')
252 |
253 | # Get main route table
254 | response2 = ec2.describe_route_tables(Filters = [{'Name': 'association.main', 'Values': ['true']}])
255 | routes = response2['RouteTables'][0]['Routes']
256 |
257 | # Check if routes include igw
258 | isPublic = any([route['GatewayId'].startswith('igw-') for route in routes])
259 |
260 | else:
261 |
262 | # Get route table routes
263 | routes = RouteTable[0]['Routes']
264 |
265 | # Check if routes include igw
266 | isPublic = any([route['GatewayId'].startswith('igw-') for route in routes])
267 |
268 |
269 | return 'public' if isPublic else 'private'
270 |
271 | def createInstance(intent_request):
272 | logger.info('Received a request to create an EC2 instance')
273 |
274 | # Build config and create ec2 resource
275 | config = buildConfig(intent_request)
276 | ec2Res = boto3.resource('ec2', config = config)
277 | ec2 = boto3.client('ec2', config = config)
278 |
279 | # Extract slot variables
280 | slots = intent_request['sessionState']['intent']['slots']
281 | instanceAmi = slots['ami']['value']['interpretedValue']
282 | instanceType = slots['instanceType']['value']['interpretedValue']
283 | instanceCount = int(slots['count']['value']['interpretedValue'])
284 |
285 | # Get default security group id
286 | securityGroupId = [group['GroupId'] for group in ec2.describe_security_groups()['SecurityGroups'] if group['GroupName'] == 'default'][0]
287 |
288 | # Create the instance
289 | response = ec2Res.create_instances(ImageId = instanceAmi, \
290 | InstanceType = instanceType, SecurityGroupIds = [securityGroupId], \
291 | MinCount = instanceCount, MaxCount = instanceCount)
292 | newInstanceIds = [instance.instance_id for instance in response]
293 | time.sleep(0.5)
294 |
295 | # Describe newly created instances & extract subset of attributes
296 | describeResponse = ec2.describe_instances(InstanceIds = [instance.instance_id for instance in response])
297 | instancesFilteredAttributes = filterInstanceAttributes(describeResponse)
298 |
299 | # Store created instances in session attriubtes
300 | sessionAttributes = updateSessionAttributes(intent_request, 'instances', json.dumps(instancesFilteredAttributes, default=str))
301 |
302 | # Return response
303 | intentName = intent_request['sessionState']['intent']['name']
304 | message = '{} instances were launched with the following ids: {}'.format(instanceCount, newInstanceIds)
305 |
306 | logger.info(message)
307 | return prepareResponse(intentName, sessionAttributes, message)
308 |
309 |
310 |
311 | def terminateInstances(intent_request):
312 | logger.info('Received a request to terminate an EC2 instance')
313 |
314 | # Build config and create ec2 resource
315 | config = buildConfig(intent_request)
316 | ec2 = boto3.client('ec2', config = config)
317 |
318 |
319 | # Extract selected instances from session attributes
320 | sessionAttributes = intent_request['sessionState'].get('sessionAttributes')
321 | logger.info(sessionAttributes)
322 | selectedInstances = json.loads(sessionAttributes['instances'])
323 | instanceIds = [instance['InstanceId'] for instance in selectedInstances]
324 |
325 | # Create the instance
326 | response = ec2.terminate_instances(InstanceIds = instanceIds)
327 |
328 | # Create message
329 | message = 'These instances were terminated: {}'.format(instanceIds)
330 | logger.info(message)
331 |
332 | # Return response
333 | intentName = intent_request['sessionState']['intent']['name']
334 | sessionAttributes = intent_request['sessionState'].get('sessionAttributes')
335 | return prepareResponse(intentName, sessionAttributes, message)
336 |
337 |
338 |
339 | def changeRegion(intent_request):
340 | logger.info('Received a request to change the region')
341 |
342 | # Get region slot
343 | slots = intent_request['sessionState']['intent']['slots']
344 | region = slots['region']['value']['interpretedValue']
345 |
346 | # Change region in session attributes
347 | sessionAttributes = updateSessionAttributes(intent_request, 'region', region)
348 |
349 | # Prepare resulting message
350 | message = "Assistant is now operating in the {} region".format(region)
351 | intentName = intent_request['sessionState']['intent']['name']
352 |
353 | return prepareResponse(intentName, sessionAttributes, message)
354 |
355 |
356 |
357 | def isOpenRule(rule):
358 |
359 | # Get ip ranges
360 | ipRanges = rule['IpRanges']
361 | if not ipRanges: return False
362 |
363 | # Check ip
364 | if ipRanges[0]['CidrIp'] == '0.0.0.0/0': return True
365 | return False
366 |
367 | def listRules(intent_request):
368 | logger.info('Received a request to list security group rules')
369 |
370 | # Build config and create ec2 resource
371 | config = buildConfig(intent_request)
372 | ec2Res = boto3.resource('ec2', config = config)
373 | ec2 = boto3.client('ec2', config = config)
374 |
375 | # Get default security group id
376 | securityGroupId = [group['GroupId'] for group in ec2.describe_security_groups()['SecurityGroups'] if group['GroupName'] == 'default'][0]
377 |
378 | # Find security group resource & get inbound rules
379 | sg = ec2Res.SecurityGroup(securityGroupId)
380 | inboundRules = sg.ip_permissions
381 | logger.info(inboundRules)
382 |
383 | # Identify open rules
384 | openRules = [rule for rule in inboundRules if isOpenRule(rule)]
385 | openPorts = [rule['ToPort'] for rule in openRules]
386 |
387 | # Update session attributes
388 | sessionAttributes = updateSessionAttributes(intent_request, 'sg-open-rules', json.dumps(openRules, default=str))
389 |
390 | # Create message
391 | message = 'There are {} security group rules with unrestricted inbound traffic to the following ports: {}'.format(len(openRules), openPorts)
392 | logger.info(message)
393 |
394 | # Return response
395 | intentName = intent_request['sessionState']['intent']['name']
396 | return prepareResponse(intentName, sessionAttributes, message)
397 |
398 |
399 | def listS3Buckets(intent_request):
400 | logger.info('Received a request to list all S3 buckets')
401 |
402 | # Build config and create s3 resource dfg
403 | config = buildConfig(intent_request)
404 | s3 = boto3.client('s3')
405 |
406 | # List all buckets
407 | buckets = s3.list_buckets()['Buckets']
408 | bucketNames = [bucket['Name'] for bucket in buckets]
409 | bucketList = [str(idx+1) + ') ' + bucket['Name'] for idx, bucket in enumerate(buckets)]
410 | bucketList = '\n'.join(bucketList)
411 |
412 | # Store versioning information
413 | for i in range(len(buckets)):
414 | buckets[i]['Versioning'] = True if s3.get_bucket_versioning(Bucket=buckets[i]['Name']).get('Status') == 'Enabled' else False
415 |
416 | # Update session attributes
417 | sessionAttributes = updateSessionAttributes(intent_request, 's3-bucket-list', json.dumps(buckets, default=str))
418 |
419 | # Create message
420 | # message = 'There are {} S3 buckets. They are listed below: \n'.format(len(bucketNames)) + bucketList
421 | message = 'There are {} S3 buckets. Bucket names and other information is attached.'.format(len(bucketNames))
422 | logger.info(message)
423 |
424 | # Return response
425 | intentName = intent_request['sessionState']['intent']['name']
426 | return prepareResponse(intentName, sessionAttributes, message)
427 |
428 |
429 |
430 | def searchS3(intent_request):
431 | logger.info('Received a request to search in S3')
432 |
433 | # Build config and create s3 resource
434 | config = buildConfig(intent_request)
435 | s3 = boto3.client('s3')
436 |
437 | # List all buckets
438 | buckets = s3.list_buckets()['Buckets']
439 | bucketNames = [bucket['Name'] for bucket in buckets]
440 |
441 | # Get available slots
442 | slots = intent_request['sessionState']['intent']['slots']
443 | pattern = slots['objName']['value']['originalValue']
444 | bucketIndex = None
445 | if slots['bucketIndex'] is not None: bucketIndex = slots['bucketIndex']['value']['interpretedValue']
446 |
447 | # Initialize results
448 | items = []
449 | maxPerBucket = 10
450 | printableItems = ''
451 |
452 | # Search in specific bucket
453 | if bucketIndex is not None:
454 |
455 | # Get bucket name
456 | logger.info('Search in single bucket')
457 | bucketIndex = int(bucketIndex) - 1
458 | bucketName = bucketNames[bucketIndex]
459 |
460 | # Search bucket
461 | items = searchBucket(s3, bucketName, pattern)
462 | itemKeys = [str(idx+1) + ') ' + item['Key'] for idx, item in enumerate(items)]
463 |
464 | logger.info(items)
465 | if items: printableItems = '\n'.join(itemKeys)
466 |
467 | # Create message
468 | logger.info(items)
469 | # message = '{} objects were found containing the keyword "{}" in bucket {}. Items are listed below: {}'.format(len(items), pattern, bucketName, printableItems)
470 | message = '{} objects were found containing the keyword "{}" in bucket {}. Search results are attached.'.format(len(items), pattern, bucketName)
471 |
472 |
473 | # Search across all buckets (powerful)
474 | else:
475 |
476 | # Loop through buckets
477 | logger.info('Search in all buckets')
478 | for bucketName in bucketNames:
479 |
480 | # Skip admin buckets
481 | if 'isengard' in bucketName.lower(): continue
482 |
483 | # Search in bucket
484 | logger.info('Searching in bucket {}'.format(bucketName))
485 | bucketItems = searchBucket(s3, bucketName, pattern)
486 | if not bucketItems: continue
487 |
488 | # Append items
489 | items += bucketItems[:maxPerBucket]
490 |
491 |
492 | # Create message
493 | itemKeys = [str(idx+1) + ') ' + item['Key'] for idx, item in enumerate(items)]
494 | if items: printableItems = '\n'.join(itemKeys)
495 | # message = '{} objects were found containing the keyword "{}" across all buckets. Items are listed below: {}'.format(len(items), pattern, printableItems)
496 | message = '{} objects were found containing the keyword "{}" across all buckets. Search results are attached.'.format(len(items), pattern)
497 |
498 | #Update session attributes
499 | sessionAttributes = updateSessionAttributes(intent_request, 's3-found-objects', json.dumps(items, default=str))
500 |
501 | # Log message
502 | logger.info(message)
503 |
504 | # Return response
505 | intentName = intent_request['sessionState']['intent']['name']
506 | return prepareResponse(intentName, sessionAttributes, message)
507 |
508 |
509 | def searchBucket(client, bucketName, pattern):
510 |
511 | # Get paginator
512 | paginator = client.get_paginator('list_objects_v2')
513 | page_iterator = paginator.paginate(Bucket=bucketName)
514 |
515 | # Search for pattern
516 | items = []
517 | objects = page_iterator.search("Contents[?contains(Key, `{}`) || contains(Key, `{}`)][]".format(pattern, pattern.capitalize()))
518 | for item in objects:
519 | if item is None: continue # here
520 | item['Bucket'] = bucketName
521 | items.append(item)
522 |
523 | # Return items
524 | return items
525 |
526 |
527 | def createS3Bucket(intent_request):
528 | logger.info('Received a request to create an S3 bucket')
529 |
530 | # Build config and create s3 resource
531 | config = buildConfig(intent_request)
532 | s3Res = boto3.resource('s3')
533 |
534 | # Define parameters
535 | acl = 'private'
536 |
537 | # Read bucket name from slots
538 | slots = intent_request['sessionState']['intent']['slots']
539 | bucketName = slots['bucketName']['value']['originalValue']
540 | bucketName = bucketName.lower()
541 |
542 | # Create bucket
543 | try:
544 | bucket = s3Res.create_bucket(ACL=acl, Bucket=bucketName) #CreateBucketConfiguration= {'LocationConstraint': config.region_name}
545 | except ClientError as err:
546 | logger.info(err.response)
547 | # if err.response['Error']['Code'] == 'BucketAlreadyExists':
548 | try:
549 | logger.info('Retrying bucket creation with a random bucket suffix...')
550 | timeSuffix = datetime.datetime.now().strftime('-%m-%d-%Y-%H-%M-%S')
551 | bucket = s3Res.create_bucket(ACL=acl, Bucket=bucketName + timeSuffix)
552 | except Exception as ex:
553 | logger.info(ex)
554 | logger.info('Some other error happened...exiting')
555 | return
556 |
557 | # Update session attributes
558 | sessionAttributes = updateSessionAttributes(intent_request, 's3-new-bucket', bucket.name)
559 |
560 | # Create message
561 | message = 'A new S3 bucket was created with the following name: {}'.format(bucket.name)
562 | logger.info(message)
563 |
564 | # Return response
565 | intentName = intent_request['sessionState']['intent']['name']
566 | return prepareResponse(intentName, sessionAttributes, message)
567 |
568 |
569 | def copyToNewBucket(intent_request):
570 | logger.info('Received a request to copy files to a new S3 bucket')
571 |
572 | # Build config and create s3 resource
573 | config = buildConfig(intent_request)
574 | s3Res = boto3.resource('s3')
575 |
576 | # Retrive new bucket and search results from session attributes
577 | sessionAttributes = intent_request['sessionState'].get('sessionAttributes')
578 | logger.info(sessionAttributes)
579 | newBucketName = sessionAttributes['s3-new-bucket']
580 | s3Objects = json.loads(sessionAttributes['s3-found-objects'])
581 |
582 | # Get new bucket resource
583 | newbucket = s3Res.Bucket(newBucketName)
584 |
585 |
586 | # Copy files to new bucket
587 | for obj in s3Objects:
588 |
589 | # create source copy
590 | copy_source = {
591 | 'Bucket': obj['Bucket'],
592 | 'Key': obj['Key']
593 | }
594 |
595 | # Copy to bucket
596 | newbucket.copy(copy_source, obj['Key'])
597 |
598 |
599 | # Create message
600 | message = '{} target files/objects were successfully copied to new bucket {}'.format(len(s3Objects), newBucketName)
601 | logger.info(message)
602 |
603 | # Return response
604 | intentName = intent_request['sessionState']['intent']['name']
605 | return prepareResponse(intentName, sessionAttributes, message)
606 |
607 |
608 |
609 | def replaceRules(intent_request):
610 | logger.info('Received a request to modify security group rules')
611 | myIpAddress = '76.243.176.78/32'
612 |
613 | # Build config and create ec2 resource
614 | config = buildConfig(intent_request)
615 | ec2Res = boto3.resource('ec2', config = config)
616 | ec2 = boto3.client('ec2', config = config)
617 |
618 | # Get default security group id
619 | securityGroupId = [group['GroupId'] for group in ec2.describe_security_groups()['SecurityGroups'] if group['GroupName'] == 'default'][0]
620 |
621 | # Extract slot values
622 | slots = intent_request['sessionState']['intent']['slots']
623 | allowedIpAddress = myIpAddress if slots['ipAddress'] is None else slots['ipAddress']['value']['originalValue'] + '/32'
624 |
625 |
626 | # Extract selected SG rules from session attributes
627 | sessionAttributes = intent_request['sessionState'].get('sessionAttributes')
628 | logger.info(sessionAttributes)
629 | selectedRules = json.loads(sessionAttributes['sg-open-rules'])
630 | logger.info(selectedRules)
631 |
632 | # Modify rules
633 | modifiedRules = []
634 | for rule in selectedRules:
635 | modifiedRule = copy.deepcopy(rule)
636 | modifiedRule['IpRanges'][0]['CidrIp'] = allowedIpAddress
637 | modifiedRules.append(modifiedRule)
638 |
639 | # Revoke previous rules, and authorize modified rules
640 | sg = ec2Res.SecurityGroup(securityGroupId)
641 | sg.revoke_ingress(IpPermissions = selectedRules)
642 | sg.authorize_ingress(IpPermissions = modifiedRules)
643 |
644 |
645 | # Create message
646 | message = 'Selected security group rules have been modified to allow traffic from: {}'.format(allowedIpAddress)
647 | logger.info(message)
648 |
649 | # Return response
650 | intentName = intent_request['sessionState']['intent']['name']
651 | return prepareResponse(intentName, sessionAttributes, message)
652 |
653 |
654 |
655 | def updateSessionAttributes(intent_request, paramName, paramValue):
656 |
657 | sessionAttributes = intent_request['sessionState'].get('sessionAttributes')
658 | if not sessionAttributes: sessionAttributes = {}
659 | sessionAttributes[paramName] = paramValue
660 | return sessionAttributes
661 |
662 |
663 |
664 |
665 | def prepareResponse(intentName, sessionAttributes, message, contexts = []):
666 |
667 | return {
668 | 'sessionState': {
669 | 'activeContexts': contexts,
670 | 'dialogAction': {'type': 'Close'},
671 | 'intent': {
672 | 'name': intentName,
673 | 'state': 'Fulfilled'
674 | },
675 | 'sessionAttributes': sessionAttributes,
676 | },
677 |
678 | 'messages': [
679 | {
680 | 'contentType': 'PlainText',
681 | 'content': message
682 | },
683 | # {
684 | # 'contentType': 'PlainText',
685 | # 'content': "A secondary message"
686 | # }
687 | ]
688 | }
689 |
690 |
691 | def dispatch(intent_request):
692 |
693 | # Log request
694 | # logger.debug('dispatch userId={}, intentName={}'.format(intent_request['userId'], intent_request['currentIntent']['name']))
695 |
696 | # Get intent name
697 | # intent_name = intent_request['currentIntent']['name']
698 | intent_name = intent_request['sessionState']['intent']['name']
699 |
700 | # Dispatch ec2-list intent
701 | if intent_name == 'ec2-list':
702 | return listInstances(intent_request)
703 |
704 | # Dispatch ec2-create intent
705 | if intent_name == 'ec2-create':
706 | return createInstance(intent_request)
707 |
708 | # Dispatch ec2-terminate intent
709 | if intent_name == 'ec2-terminate':
710 | return terminateInstances(intent_request)
711 |
712 | # Dispatch set-region intent
713 | if intent_name == 'set-region':
714 | return changeRegion(intent_request)
715 |
716 | # Dispatch sg-rule-list intent
717 | if intent_name == 'sg-rule-list':
718 | return listRules(intent_request)
719 |
720 | # Dispatch sg-rule-list intent
721 | if intent_name == 'sg-rule-replace':
722 | return replaceRules(intent_request)
723 |
724 | # Dispatch s3-list-buckets intent
725 | if intent_name == 's3-list-buckets':
726 | return listS3Buckets(intent_request)
727 |
728 | # Dispatch s3-search intent
729 | if intent_name == 's3-search':
730 | return searchS3(intent_request)
731 |
732 | # Dispatch s3-create bucket intent
733 | if intent_name == 's3-create-bucket':
734 | return createS3Bucket(intent_request)
735 |
736 | # Dispatch s3-copy-to-new-bucket bucket intent
737 | if intent_name == 's3-copy-to-new-bucket':
738 | return copyToNewBucket(intent_request)
739 |
740 | # Raise exception if intent is not recognized
741 | raise Exception('Intent with name ' + intent_name + ' not supported')
742 |
743 |
744 | """ --- Main handler --- """
745 | def handler(event, context):
746 |
747 | # Log event and context
748 | logger.info(event)
749 | logger.info(context)
750 |
751 | # By default, treat the user request as coming from the America/New_York time zone.
752 | os.environ['TZ'] = 'America/New_York'
753 | time.tzset()
754 | logger.debug('event.bot.name={}'.format(event['bot']['name']))
755 |
756 | # dispatch event and return
757 | return dispatch(event)
758 |
--------------------------------------------------------------------------------