├── .gactionsrc.yaml ├── .gitignore ├── sdk ├── webhooks │ ├── ActionsOnGoogleFulfillment │ │ ├── .eslintrc.json │ │ ├── package.json │ │ └── index.js │ └── ActionsOnGoogleFulfillment.yaml ├── manifest.yaml ├── custom │ ├── types │ │ └── prompt_option.yaml │ ├── global │ │ ├── actions.intent.MAIN.yaml │ │ ├── actions.intent.NO_INPUT_1.yaml │ │ ├── actions.intent.NO_INPUT_2.yaml │ │ ├── actions.intent.NO_MATCH_1.yaml │ │ ├── actions.intent.NO_MATCH_2.yaml │ │ ├── actions.intent.NO_INPUT_FINAL.yaml │ │ └── actions.intent.NO_MATCH_FINAL.yaml │ ├── intents │ │ ├── image.yaml │ │ ├── simple.yaml │ │ ├── media_playlist.yaml │ │ ├── media_repeat.yaml │ │ ├── collection.yaml │ │ ├── card.yaml │ │ ├── table.yaml │ │ ├── list.yaml │ │ └── media.yaml │ └── scenes │ │ ├── ListPrompt.yaml │ │ ├── CollectionPrompt.yaml │ │ └── Prompts.yaml ├── actions │ └── actions.yaml └── settings │ └── settings.yaml ├── package.json ├── CONTRIBUTING.md ├── README.md ├── test └── test.ts └── LICENSE /.gactionsrc.yaml: -------------------------------------------------------------------------------- 1 | sdkPath: "sdk" # value is a filepath to where your SDK files are located (can be relative or absolute) 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .firebaserc 4 | package-lock.json 5 | yarn.lock 6 | .firebase 7 | *.log 8 | service_account.json 9 | -------------------------------------------------------------------------------- /sdk/webhooks/ActionsOnGoogleFulfillment/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 8, 4 | "sourceType": "script" 5 | }, 6 | "extends": ["google"], 7 | "env": { 8 | "node": true 9 | } 10 | } -------------------------------------------------------------------------------- /sdk/manifest.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | version: "1.0" 15 | -------------------------------------------------------------------------------- /sdk/custom/types/prompt_option.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | {} 15 | -------------------------------------------------------------------------------- /sdk/actions/actions.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | custom: 15 | actions.intent.MAIN: {} 16 | -------------------------------------------------------------------------------- /sdk/custom/global/actions.intent.MAIN.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | transitionToScene: Prompts 15 | -------------------------------------------------------------------------------- /sdk/custom/intents/image.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | trainingPhrases: 15 | - Image prompt 16 | - Image response 17 | - Image 18 | -------------------------------------------------------------------------------- /sdk/webhooks/ActionsOnGoogleFulfillment/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "actions-builder-conversation-components", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "An Action that demonstrates the various available types of conversation components.", 6 | "main": "index.js", 7 | "engines": { 8 | "node": "10" 9 | }, 10 | "scripts": { 11 | "lint": "eslint \"**/*.js\"", 12 | "lint:fix": "eslint --fix \"**/*.js\"" 13 | }, 14 | "dependencies": { 15 | "@assistant/conversation": "^3.5.0", 16 | "firebase-admin": "~8.12.1", 17 | "firebase-functions": "^3.6.2" 18 | }, 19 | "devDependencies": { 20 | "eslint": "^5.2.0", 21 | "eslint-config-google": "^0.9.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sdk/custom/intents/simple.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | trainingPhrases: 15 | - Simple prompt 16 | - Simple response 17 | - Simple 18 | -------------------------------------------------------------------------------- /sdk/custom/intents/media_playlist.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | trainingPhrases: 15 | - playlist 16 | - audio playlist 17 | - media playlist 18 | - list of music -------------------------------------------------------------------------------- /sdk/custom/intents/media_repeat.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | trainingPhrases: 15 | - repeated music 16 | - repeated audio 17 | - loop 18 | - loop of audio 19 | -------------------------------------------------------------------------------- /sdk/custom/intents/collection.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | trainingPhrases: 15 | - select collection 16 | - collection select 17 | - collection 18 | - Collection 19 | -------------------------------------------------------------------------------- /sdk/custom/intents/card.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | trainingPhrases: 15 | - Card 16 | - ($prompts1 'BasicCard' auto=true) 17 | - ($prompts1 'card' auto=true) 18 | - ($prompts1 'Basic Card' auto=true) 19 | -------------------------------------------------------------------------------- /sdk/custom/intents/table.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | trainingPhrases: 15 | - TableCard 16 | - ($prompts1 'Table' auto=true) card 17 | - ($prompts1 'table' auto=true) 18 | - ($prompts1 'Table' auto=true) 19 | -------------------------------------------------------------------------------- /sdk/custom/intents/list.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | trainingPhrases: 15 | - select ($prompts1 'list' auto=true) 16 | - ($prompts1 'list' auto=true) select 17 | - ($prompts1 'list' auto=true) 18 | - ($prompts1 'List' auto=true) 19 | -------------------------------------------------------------------------------- /sdk/custom/intents/media.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | trainingPhrases: 15 | - audio response 16 | - audioresponse 17 | - mediaresponse 18 | - media response 19 | - ($prompts1 'audio' auto=true) 20 | - ($prompts1 'media' auto=true) 21 | - ($prompts1 'Audio' auto=true) 22 | - ($prompts1 'Media' auto=true) 23 | -------------------------------------------------------------------------------- /sdk/webhooks/ActionsOnGoogleFulfillment.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | handlers: 15 | - name: card 16 | - name: media 17 | - name: table 18 | - name: simple 19 | - name: image 20 | - name: media_status 21 | - name: option 22 | - name: list 23 | - name: collection 24 | inlineCloudFunction: 25 | executeFunction: ActionsOnGoogleFulfillment 26 | -------------------------------------------------------------------------------- /sdk/custom/global/actions.intent.NO_INPUT_1.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | handler: 15 | staticPrompt: 16 | candidates: 17 | - promptResponse: 18 | firstSimple: 19 | variants: 20 | - speech: Sorry, I didn't catch that. Can you try again? 21 | text: Sorry, I didn't catch that. Can you try again? 22 | -------------------------------------------------------------------------------- /sdk/custom/global/actions.intent.NO_INPUT_2.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | handler: 15 | staticPrompt: 16 | candidates: 17 | - promptResponse: 18 | firstSimple: 19 | variants: 20 | - speech: Sorry, I didn't catch that. Can you try again? 21 | text: Sorry, I didn't catch that. Can you try again? 22 | -------------------------------------------------------------------------------- /sdk/custom/global/actions.intent.NO_MATCH_1.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | handler: 15 | staticPrompt: 16 | candidates: 17 | - promptResponse: 18 | firstSimple: 19 | variants: 20 | - speech: Sorry, I didn't catch that. Can you try again? 21 | text: Sorry, I didn't catch that. Can you try again? 22 | -------------------------------------------------------------------------------- /sdk/custom/global/actions.intent.NO_MATCH_2.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | handler: 15 | staticPrompt: 16 | candidates: 17 | - promptResponse: 18 | firstSimple: 19 | variants: 20 | - speech: Sorry, I didn't catch that. Can you try again? 21 | text: Sorry, I didn't catch that. Can you try again? 22 | -------------------------------------------------------------------------------- /sdk/settings/settings.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | defaultLocale: en 15 | localizedSettings: 16 | developerEmail: 17 | developerName: 18 | displayName: Conversation components sample 19 | fullDescription: 20 | privacyPolicyUrl: 21 | pronunciation: Conversation components sample 22 | shortDescription: 23 | smallLogoImage: 24 | termsOfServiceUrl: 25 | projectId: 26 | -------------------------------------------------------------------------------- /sdk/custom/scenes/ListPrompt.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | conditionalEvents: 15 | - condition: scene.slots.status == "FINAL" 16 | handler: 17 | webhookHandler: option 18 | transitionToScene: Prompts 19 | slots: 20 | - commitBehavior: 21 | writeSessionParam: prompt_option 22 | name: prompt_option 23 | promptSettings: 24 | initialPrompt: 25 | webhookHandler: list 26 | required: true 27 | type: 28 | name: prompt_option 29 | -------------------------------------------------------------------------------- /sdk/custom/scenes/CollectionPrompt.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | conditionalEvents: 15 | - condition: scene.slots.status == "FINAL" 16 | handler: 17 | webhookHandler: option 18 | transitionToScene: Prompts 19 | slots: 20 | - commitBehavior: 21 | writeSessionParam: prompt_option 22 | name: prompt_option 23 | promptSettings: 24 | initialPrompt: 25 | webhookHandler: collection 26 | required: true 27 | type: 28 | name: prompt_option 29 | -------------------------------------------------------------------------------- /sdk/custom/global/actions.intent.NO_INPUT_FINAL.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | handler: 15 | staticPrompt: 16 | candidates: 17 | - promptResponse: 18 | firstSimple: 19 | variants: 20 | - speech: Sorry, I still didn't catch that. The app will now quit. Please 21 | try the app again. 22 | text: Sorry, I still didn't catch that. The app will now quit. Please 23 | try the app again. 24 | transitionToScene: actions.scene.END_CONVERSATION 25 | -------------------------------------------------------------------------------- /sdk/custom/global/actions.intent.NO_MATCH_FINAL.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | handler: 15 | staticPrompt: 16 | candidates: 17 | - promptResponse: 18 | firstSimple: 19 | variants: 20 | - speech: Sorry, I still didn't catch that. The app will now quit. Please 21 | try the app again. 22 | text: Sorry, I still didn't catch that. The app will now quit. Please 23 | try the app again. 24 | transitionToScene: actions.scene.END_CONVERSATION 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "actions-builder-conversation-components", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "An Action that demonstrates the various available types of conversation components.", 6 | "engines": { 7 | "node": "10" 8 | }, 9 | "scripts": { 10 | "lint": "eslint \"**/*.js\"", 11 | "lint:fix": "eslint --fix \"**/*.js\"", 12 | "enable-activity-controls": "env GOOGLE_APPLICATION_CREDENTIALS=$PWD/service_account.json web-and-app-activity-controls", 13 | "test": "npm run lint && env GOOGLE_APPLICATION_CREDENTIALS=$PWD/service_account.json mocha --recursive --require ts-node/register test/*.ts", 14 | "serve": "firebase serve", 15 | "deploy": "firebase deploy" 16 | }, 17 | "devDependencies": { 18 | "@assistant/conversation-testing": "1.0.0", 19 | "@types/mocha": "^8.0.0", 20 | "@types/node": "^10.0.0", 21 | "chai": "^4.2.0", 22 | "eslint": "^5.2.0", 23 | "eslint-config-google": "^0.9.1", 24 | "mocha": "^8.0.1", 25 | "ts-node": "^7.0.1", 26 | "typescript": "^3.8.3" 27 | }, 28 | "dependencies": { 29 | "google-auth-library": "^6.1.3", 30 | "js-yaml": "^3.14.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to become a contributor and submit your own code 2 | 3 | ## Contributor License Agreements 4 | 5 | We'd love to accept your sample apps and patches! Before we can take them, we 6 | have to jump a couple of legal hurdles. 7 | 8 | Please fill out either the individual or corporate Contributor License Agreement 9 | (CLA). 10 | 11 | * If you are an individual writing original source code and you're sure you 12 | own the intellectual property, then you'll need to sign an [individual CLA](https://developers.google.com/open-source/cla/individual). 13 | * If you work for a company that wants to allow you to contribute your work, 14 | then you'll need to sign a [corporate CLA](https://developers.google.com/open-source/cla/corporate). 15 | 16 | Follow either of the two links above to access the appropriate CLA and 17 | instructions for how to sign and return it. Once we receive it, we'll be able to 18 | accept your pull requests. 19 | 20 | ## Contributing A Patch 21 | 22 | 1. Submit an issue describing your proposed change to the repo in question. 23 | 1. The repo owner will respond to your issue promptly. 24 | 1. If your proposed change is accepted, and you haven't already done so, sign a 25 | Contributor License Agreement (see details above). 26 | 1. Fork the desired repo, develop and test your code changes. 27 | 1. Ensure that your code adheres to the existing style in the sample to which 28 | you are contributing. 29 | 1. Ensure that your code has an appropriate set of unit tests which all pass. 30 | 1. Submit a pull request. 31 | -------------------------------------------------------------------------------- /sdk/custom/scenes/Prompts.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | intentEvents: 15 | - handler: 16 | webhookHandler: card 17 | intent: card 18 | transitionToScene: Prompts 19 | - intent: collection 20 | transitionToScene: CollectionPrompt 21 | - intent: list 22 | transitionToScene: ListPrompt 23 | - handler: 24 | webhookHandler: media 25 | intent: media 26 | transitionToScene: Prompts 27 | - handler: 28 | webhookHandler: media_playlist 29 | intent: media_playlist 30 | transitionToScene: Prompts 31 | - handler: 32 | webhookHandler: media_repeat 33 | intent: media_repeat 34 | transitionToScene: Prompts 35 | - handler: 36 | webhookHandler: table 37 | intent: table 38 | transitionToScene: Prompts 39 | - handler: 40 | webhookHandler: simple 41 | intent: simple 42 | transitionToScene: Prompts 43 | - handler: 44 | webhookHandler: image 45 | intent: image 46 | transitionToScene: Prompts 47 | - handler: 48 | webhookHandler: media_status 49 | intent: actions.intent.MEDIA_STATUS_FINISHED 50 | transitionToScene: Prompts 51 | - handler: 52 | webhookHandler: media_status 53 | intent: actions.intent.MEDIA_STATUS_PAUSED 54 | transitionToScene: Prompts 55 | - handler: 56 | webhookHandler: media_status 57 | intent: actions.intent.MEDIA_STATUS_STOPPED 58 | transitionToScene: Prompts 59 | - handler: 60 | webhookHandler: media_status 61 | intent: actions.intent.MEDIA_STATUS_FAILED 62 | transitionToScene: Prompts 63 | - intent: actions.intent.CANCEL 64 | transitionToScene: actions.scene.END_CONVERSATION 65 | onEnter: 66 | staticPrompt: 67 | candidates: 68 | - promptResponse: 69 | lastSimple: 70 | variants: 71 | - speech: I can show you basic cards, lists, and more on your phone and 72 | smart display. What would you like to see? 73 | suggestions: 74 | - title: Simple 75 | - title: Image 76 | - title: Card 77 | - title: Table 78 | - title: List 79 | - title: Collection 80 | - title: Media 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Actions on Google: Conversation Components Sample 2 | 3 | *:warning: Warning: Conversational Actions will be deprecated on June 13, 2023. For more information, see [Conversational Actions Sunset](https://goo.gle/ca-sunset).* 4 | 5 | 6 | ### Prerequisites 7 | 1. Node.js and NPM 8 | + We recommend installing using [nvm for Linux/Mac](https://github.com/creationix/nvm) and [nvm-windows for Windows](https://github.com/coreybutler/nvm-windows) 9 | 1. Install the [Firebase CLI](https://developers.google.com/assistant/actions/dialogflow/deploy-fulfillment) 10 | + We recommend using MAJOR version `8` , `npm install -g firebase-tools@^8.0.0` 11 | + Run `firebase login` with your Google account 12 | 13 | ### Setup 14 | #### Actions Console 15 | 1. From the [Actions on Google Console](https://console.actions.google.com/), **New project** > **Create project** > under **What kind of Action do you want to build?** > **Custom** > **Blank project** 16 | 17 | #### Actions CLI 18 | 1. Install the [Actions CLI](https://developers.google.com/assistant/actionssdk/gactions) 19 | 1. Navigate to `sdk/settings/settings.yaml`, and replace `` with your project ID 20 | 1. Run `gactions login` to login to your account. 21 | 1. Run `gactions push` to push your project. 22 | 1. Run `gactions deploy preview` to deploy your project. 23 | 24 | ### Running this Sample 25 | + You can test your Action on any Google Assistant-enabled device on which the Assistant is signed into the same account used to create this project. Just say or type, “OK Google, talk to my test app”. 26 | + You can also use the Actions on Google Console simulator to test most features and preview on-device behavior. 27 | 28 | ### Running tests 29 | 30 | This Action uses the [Assistant conversation testing library](https://github.com/actions-on-google/assistant-conversation-testing-nodejs) for testing. Follow the steps below to run the tests for this project: 31 | 32 | 1. Enable the Actions API for your project (The Actions API is enabled by default for newly created projects): 33 | 1. Visit the [Google API console](https://console.developers.google.com/apis/library) and select your project from the **Select a project** dropdown. 34 | 1. If the Action API is not enabled, search for *"Actions API"* and click **Enable**. 35 | 1. Create a Service Account key: 36 | 1. Visit the [Google Cloud console credentials page](https://console.developers.google.com/apis/credentials) and select your project from the **Select a project** dropdown. 37 | 1. In the "Service Accounts" click on the "App Engine default service account" service account. 38 | 1. Enter a service account name and click **Create**. 39 | 1. From the **Select a role** dropdown, select **Project > Owner**. 40 | 1. Click **Continue**. 41 | 1. Click **ADD KEY**, then select **Create new key**, then press **CREATE** 42 | to download the service account JSON file. 43 | 1. Rename the service account file to `service_account.json`, and place it in the root folder of the project. 44 | 1. Enable [Web and App Activity Controls](https://support.google.com/websearch/answer/54068) for the service account. It is necessary to have this setting enabled in order to call the Actions API. 45 | + `npm run enable-activity-controls` 46 | 1. Run tests 47 | + `npm run test` 48 | 49 | ## References & Issues 50 | + Questions? Go to [StackOverflow](https://stackoverflow.com/questions/tagged/actions-on-google) or the [Assistant Developer Community on Reddit](https://www.reddit.com/r/GoogleAssistantDev/). 51 | + For bugs, please report an issue on Github. 52 | + Actions on Google [Documentation](https://developers.google.com/assistant) 53 | + Actions on Google [Codelabs](https://codelabs.developers.google.com/?cat=Assistant) 54 | 55 | ## Contributing 56 | Please read and follow the steps in the [CONTRIBUTING.md](CONTRIBUTING.md). 57 | 58 | ## License 59 | See [LICENSE](LICENSE). 60 | -------------------------------------------------------------------------------- /test/test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import 'mocha'; 18 | import {ActionsOnGoogleTestManager} from '@assistant/conversation-testing'; 19 | import {resolve} from 'path'; 20 | import {readFileSync} from 'fs'; 21 | import {safeLoad} from 'js-yaml'; 22 | 23 | const DEFAULT_LOCALE = 'en-US'; 24 | const DEFAULT_SURFACE = 'PHONE'; 25 | const CONTINUE_CONVO_PROMPT = 26 | 'I can show you basic cards, lists, and more on your phone and smart display. What would you like to see?'; 27 | 28 | let PROJECT_ID; 29 | let TRIGGER_PHRASE; 30 | 31 | // tslint:disable:only-arrow-functions 32 | 33 | describe('My Action Test Suite', function() { 34 | // Set the timeout for each test run to 60s. 35 | this.timeout(60000); 36 | let test: ActionsOnGoogleTestManager; 37 | 38 | async function startConversation() { 39 | await test.sendQuery(TRIGGER_PHRASE); 40 | test.assertSpeech(CONTINUE_CONVO_PROMPT); 41 | test.assertText(CONTINUE_CONVO_PROMPT); 42 | test.assertIntent('actions.intent.MAIN'); 43 | test.assertScene('Prompts'); 44 | } 45 | 46 | // Load project ID and sample display name from project settings. 47 | function loadProjectSettings() { 48 | try { 49 | let fileContents = readFileSync( 50 | resolve(__dirname, '../sdk/settings/settings.yaml'), 'utf8'); 51 | let data = safeLoad(fileContents) as any; 52 | PROJECT_ID = data.projectId; 53 | TRIGGER_PHRASE = `Talk to ${data.localizedSettings.displayName}`; 54 | } catch (e) { 55 | console.log(e); 56 | } 57 | } 58 | 59 | before('before all', async function() { 60 | // Load project settings to read project ID and trigger phrase. 61 | loadProjectSettings(); 62 | test = new ActionsOnGoogleTestManager({ projectId: PROJECT_ID }); 63 | await test.writePreviewFromDraft(); 64 | test.setSuiteLocale(DEFAULT_LOCALE); 65 | test.setSuiteSurface(DEFAULT_SURFACE); 66 | }); 67 | 68 | afterEach('post test cleans', async function() { 69 | test.cleanUpAfterTest(); 70 | }); 71 | 72 | it('trigger only', async function() { 73 | test.setTestSurface('SMART_DISPLAY'); 74 | await startConversation(); 75 | await test.sendStop(); 76 | test.assertConversationEnded(); 77 | }); 78 | 79 | it('display simple', async function() { 80 | await startConversation(); 81 | await test.sendQuery('Simple'); 82 | const expectedExact = 83 | `This is the first simple response.This is the last simple response. ${ 84 | CONTINUE_CONVO_PROMPT}`; 85 | const expectedRegex = 86 | `This is .* ${CONTINUE_CONVO_PROMPT}`; 87 | // Assert speech is exact match using `isExact` argument. 88 | test.assertSpeech(expectedExact, {isExact: true}); 89 | // Assert text with regex using `isRegex` argument. 90 | test.assertText(expectedRegex, {isRegexp: true}); 91 | test.assertIntent('simple'); 92 | await test.sendStop(); 93 | test.assertConversationEnded(); 94 | }); 95 | 96 | it('display image', async function() { 97 | await startConversation(); 98 | await test.sendQuery('Image'); 99 | const expected = `This is an image prompt!${CONTINUE_CONVO_PROMPT}`; 100 | test.assertSpeech(expected); 101 | test.assertText(expected); 102 | test.assertIntent('image'); 103 | test.assertImage({ 104 | url: 'https://developers.google.com/assistant/assistant_96.png', 105 | alt: 'Google Assistant logo' 106 | }); 107 | await test.sendStop(); 108 | test.assertConversationEnded(); 109 | }); 110 | 111 | it('display card', async function() { 112 | await startConversation(); 113 | await test.sendQuery('Card'); 114 | const expected = `This is a card.${CONTINUE_CONVO_PROMPT}`; 115 | test.assertSpeech(expected); 116 | test.assertText(expected); 117 | test.assertIntent('card'); 118 | test.assertCard({ 119 | title: 'Card Title', 120 | subtitle: 'Card Subtitle', 121 | text: 'Card Content', 122 | image: { 123 | url: 'https://developers.google.com/assistant/assistant_96.png', 124 | alt: 'Google Assistant logo', 125 | height: 0, 126 | width: 0 127 | } 128 | }); 129 | await test.sendStop(); 130 | test.assertConversationEnded(); 131 | }); 132 | 133 | it('display table', async function() { 134 | await startConversation(); 135 | await test.sendQuery('Table'); 136 | const expected = `This is a table.${CONTINUE_CONVO_PROMPT}`; 137 | test.assertSpeech(expected); 138 | test.assertText(expected); 139 | test.assertIntent('table'); 140 | 141 | test.assertTable({ 142 | title: 'Table Title', 143 | subtitle: 'Table Subtitle', 144 | image: { 145 | url: 'https://developers.google.com/assistant/assistant_96.png', 146 | alt: 'Google Assistant logo', 147 | height: 0, 148 | width: 0 149 | }, 150 | columns: [ 151 | {align: 'UNSPECIFIED', header: 'Column A'}, 152 | {align: 'UNSPECIFIED', header: 'Column B'}, 153 | {align: 'UNSPECIFIED', header: 'Column C'} 154 | ], 155 | rows: [ 156 | {cells: [{text: 'A1'}, {text: 'B1'}, {text: 'C1'}], divider: false}, 157 | {cells: [{text: 'A2'}, {text: 'B2'}, {text: 'C2'}], divider: false}, 158 | {cells: [{text: 'A3'}, {text: 'B3'}, {text: 'C3'}], divider: false} 159 | ], 160 | }); 161 | await test.sendStop(); 162 | test.assertConversationEnded(); 163 | }); 164 | 165 | it('display list', async function() { 166 | await startConversation(); 167 | await test.sendQuery('List'); 168 | const expected = `This is a list.`; 169 | test.assertSpeech(expected); 170 | test.assertText(expected); 171 | test.assertIntent('list'); 172 | test.assertList({ 173 | title: 'List title', 174 | subtitle: 'List subtitle', 175 | items: 176 | [{key: 'ITEM_1'}, {key: 'ITEM_2'}, {key: 'ITEM_3'}, {key: 'ITEM_4'}] 177 | }); 178 | await test.sendStop(); 179 | test.assertConversationEnded(); 180 | }); 181 | 182 | it('display collection', async function() { 183 | await startConversation(); 184 | await test.sendQuery('Collection'); 185 | const expected = `This is a collection.`; 186 | test.assertSpeech(expected); 187 | test.assertText(expected); 188 | test.assertIntent('collection'); 189 | test.assertCollection({ 190 | title: 'Collection Title', 191 | subtitle: 'Collection subtitle', 192 | items: 193 | [{key: 'ITEM_1'}, {key: 'ITEM_2'}, {key: 'ITEM_3'}, {key: 'ITEM_4'}] 194 | }); 195 | await test.sendStop(); 196 | test.assertConversationEnded(); 197 | }); 198 | 199 | it('display media', async function() { 200 | await startConversation(); 201 | await test.sendQuery('Media'); 202 | const expected = `This is a media response${CONTINUE_CONVO_PROMPT}`; 203 | test.assertSpeech(expected); 204 | test.assertText(expected); 205 | test.assertIntent('media'); 206 | test.assertMedia({ 207 | optionalMediaControls: ['PAUSED', 'STOPPED'] as any, 208 | mediaObjects: [{ 209 | name: 'Media name', 210 | description: 'Media description', 211 | url: 212 | 'https://actions.google.com/sounds/v1/cartoon/cartoon_boing.ogg', 213 | image: { 214 | image: 'large', 215 | large: { 216 | url: 'https://developers.google.com/assistant/assistant_96.png', 217 | alt: 'Google Assistant logo', 218 | height: 0, 219 | width: 0 220 | } 221 | } as any 222 | }], 223 | mediaType: 'AUDIO' 224 | }); 225 | await test.sendStop(); 226 | test.assertConversationEnded(); 227 | }); 228 | 229 | it('select list item', async function() { 230 | await startConversation(); 231 | await test.sendQuery('List'); 232 | let expected = `This is a list.`; 233 | test.assertSpeech(expected); 234 | test.assertText(expected); 235 | test.assertIntent('list'); 236 | test.assertConversationNotEnded(); 237 | 238 | await test.sendQuery('Item #1'); 239 | expected = `You selected item #1.${CONTINUE_CONVO_PROMPT}`; 240 | test.assertSpeech(expected); 241 | test.assertText(expected); 242 | test.assertScene('Prompts'); 243 | await test.sendStop(); 244 | test.assertConversationEnded(); 245 | }); 246 | 247 | it('select collection item', async function() { 248 | await startConversation(); 249 | await test.sendQuery('Collection'); 250 | let expected = `This is a collection.`; 251 | test.assertSpeech(expected); 252 | test.assertText(expected); 253 | test.assertIntent('collection'); 254 | test.assertConversationNotEnded(); 255 | 256 | await test.sendQuery('Item #1'); 257 | expected = `You selected item #1.${CONTINUE_CONVO_PROMPT}`; 258 | test.assertSpeech(expected); 259 | test.assertText(expected); 260 | test.assertScene('Prompts'); 261 | await test.sendStop(); 262 | test.assertConversationEnded(); 263 | }); 264 | }); 265 | -------------------------------------------------------------------------------- /sdk/webhooks/ActionsOnGoogleFulfillment/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const { 18 | conversation, 19 | Card, 20 | Collection, 21 | Simple, 22 | List, 23 | Media, 24 | Image, 25 | Table, 26 | } = require('@assistant/conversation'); 27 | const functions = require('firebase-functions'); 28 | 29 | const app = conversation({debug: true}); 30 | 31 | const ASSISTANT_LOGO_IMAGE = new Image({ 32 | url: 'https://developers.google.com/assistant/assistant_96.png', 33 | alt: 'Google Assistant logo', 34 | }); 35 | 36 | // Simple 37 | app.handle('simple', (conv) => { 38 | conv.add(new Simple({ 39 | speech: 'This is the first simple response.', 40 | text: 'This is the 1st simple response.', 41 | })); 42 | conv.add(new Simple({ 43 | speech: 'This is the last simple response.', 44 | text: 'This is the last simple response.', 45 | })); 46 | }); 47 | 48 | // Image 49 | app.handle('image', (conv) => { 50 | conv.add('This is an image prompt!'); 51 | conv.add(ASSISTANT_LOGO_IMAGE); 52 | }); 53 | 54 | // Card 55 | app.handle('card', (conv) => { 56 | conv.add('This is a card.'); 57 | conv.add(new Card({ 58 | 'title': 'Card Title', 59 | 'subtitle': 'Card Subtitle', 60 | 'text': 'Card Content', 61 | 'image': ASSISTANT_LOGO_IMAGE, 62 | })); 63 | }); 64 | 65 | // Table 66 | app.handle('table', (conv) => { 67 | conv.add('This is a table.'); 68 | conv.add(new Table({ 69 | 'title': 'Table Title', 70 | 'subtitle': 'Table Subtitle', 71 | 'image': ASSISTANT_LOGO_IMAGE, 72 | 'columns': [{ 73 | 'header': 'Column A', 74 | }, { 75 | 'header': 'Column B', 76 | }, { 77 | 'header': 'Column C', 78 | }], 79 | 'rows': [{ 80 | 'cells': [{ 81 | 'text': 'A1', 82 | }, { 83 | 'text': 'B1', 84 | }, { 85 | 'text': 'C1', 86 | }], 87 | }, { 88 | 'cells': [{ 89 | 'text': 'A2', 90 | }, { 91 | 'text': 'B2', 92 | }, { 93 | 'text': 'C2', 94 | }], 95 | }, { 96 | 'cells': [{ 97 | 'text': 'A3', 98 | }, { 99 | 'text': 'B3', 100 | }, { 101 | 'text': 'C3', 102 | }], 103 | }], 104 | })); 105 | }); 106 | 107 | // Collection 108 | app.handle('collection', (conv) => { 109 | conv.add('This is a collection.'); 110 | // Override prompt_option Type with display 111 | // information for Collection items. 112 | conv.session.typeOverrides = [{ 113 | name: 'prompt_option', 114 | mode: 'TYPE_REPLACE', 115 | synonym: { 116 | entries: [ 117 | { 118 | name: 'ITEM_1', 119 | synonyms: ['Item 1', 'First item'], 120 | display: { 121 | title: 'Item #1', 122 | description: 'Description of Item #1', 123 | image: ASSISTANT_LOGO_IMAGE, 124 | }, 125 | }, 126 | { 127 | name: 'ITEM_2', 128 | synonyms: ['Item 2', 'Second item'], 129 | display: { 130 | title: 'Item #2', 131 | description: 'Description of Item #2', 132 | image: ASSISTANT_LOGO_IMAGE, 133 | }, 134 | }, 135 | { 136 | name: 'ITEM_3', 137 | synonyms: ['Item 3', 'Third item'], 138 | display: { 139 | title: 'Item #3', 140 | description: 'Description of Item #3', 141 | image: ASSISTANT_LOGO_IMAGE, 142 | }, 143 | }, 144 | { 145 | name: 'ITEM_4', 146 | synonyms: ['Item 4', 'Fourth item'], 147 | display: { 148 | title: 'Item #4', 149 | description: 'Description of Item #4', 150 | image: ASSISTANT_LOGO_IMAGE, 151 | }, 152 | }, 153 | ], 154 | }, 155 | }]; 156 | conv.add(new Collection({ 157 | title: 'Collection Title', 158 | subtitle: 'Collection subtitle', 159 | items: [ 160 | { 161 | key: 'ITEM_1', 162 | }, 163 | { 164 | key: 'ITEM_2', 165 | }, 166 | { 167 | key: 'ITEM_3', 168 | }, 169 | { 170 | key: 'ITEM_4', 171 | }, 172 | ], 173 | })); 174 | }); 175 | 176 | // List 177 | app.handle('list', (conv) => { 178 | conv.add('This is a list.'); 179 | // Override prompt_option Type with display 180 | // information for List items. 181 | conv.session.typeOverrides = [{ 182 | name: 'prompt_option', 183 | mode: 'TYPE_REPLACE', 184 | synonym: { 185 | entries: [ 186 | { 187 | name: 'ITEM_1', 188 | synonyms: ['Item 1', 'First item'], 189 | display: { 190 | title: 'Item #1', 191 | description: 'Description of Item #1', 192 | image: ASSISTANT_LOGO_IMAGE, 193 | }, 194 | }, 195 | { 196 | name: 'ITEM_2', 197 | synonyms: ['Item 2', 'Second item'], 198 | display: { 199 | title: 'Item #2', 200 | description: 'Description of Item #2', 201 | image: ASSISTANT_LOGO_IMAGE, 202 | }, 203 | }, 204 | { 205 | name: 'ITEM_3', 206 | synonyms: ['Item 3', 'Third item'], 207 | display: { 208 | title: 'Item #3', 209 | description: 'Description of Item #3', 210 | image: ASSISTANT_LOGO_IMAGE, 211 | }, 212 | }, 213 | { 214 | name: 'ITEM_4', 215 | synonyms: ['Item 4', 'Fourth item'], 216 | display: { 217 | title: 'Item #4', 218 | description: 'Description of Item #4', 219 | image: ASSISTANT_LOGO_IMAGE, 220 | }, 221 | }, 222 | ], 223 | }, 224 | }]; 225 | conv.add(new List({ 226 | title: 'List title', 227 | subtitle: 'List subtitle', 228 | items: [ 229 | { 230 | key: 'ITEM_1', 231 | }, 232 | { 233 | key: 'ITEM_2', 234 | }, 235 | { 236 | key: 'ITEM_3', 237 | }, 238 | { 239 | key: 'ITEM_4', 240 | }, 241 | ], 242 | })); 243 | }); 244 | 245 | // Option 246 | app.handle('option', (conv) => { 247 | const selectedOption = conv.session.params.prompt_option 248 | .toLowerCase() 249 | .replace(/_/g, ' #'); 250 | conv.add(`You selected ${selectedOption}.`); 251 | }); 252 | 253 | // Media 254 | app.handle('media', (conv) => { 255 | conv.add('This is a media response'); 256 | conv.add(new Media({ 257 | mediaObjects: [ 258 | { 259 | name: 'Media name', 260 | description: 'Media description', 261 | url: 'https://actions.google.com/sounds/v1/cartoon/cartoon_boing.ogg', 262 | image: { 263 | large: ASSISTANT_LOGO_IMAGE, 264 | }, 265 | }, 266 | ], 267 | mediaType: 'AUDIO', 268 | optionalMediaControls: ['PAUSED', 'STOPPED'], 269 | })); 270 | }); 271 | 272 | app.handle('media_playlist', (conv) => { 273 | conv.add('This is a media response with multiple media objects'); 274 | conv.add(new Media({ 275 | mediaObjects: [ 276 | { 277 | name: 'Cartoon Boing', 278 | description: 'Cartoon Boing SFX', 279 | url: 'https://actions.google.com/sounds/v1/cartoon/cartoon_boing.ogg', 280 | image: { 281 | large: ASSISTANT_LOGO_IMAGE, 282 | } 283 | }, 284 | { 285 | name: 'Cymbal Kick', 286 | description: 'Cymbal Kick SFX', 287 | url: 'https://actions.google.com/sounds/v1/cartoon/cymbal_kick.ogg', 288 | image: { 289 | large: ASSISTANT_LOGO_IMAGE, 290 | } 291 | }, 292 | { 293 | name: 'Drum Roll', 294 | description: 'Drum Roll SFX', 295 | url: 'https://actions.google.com/sounds/v1/cartoon/drum_roll.ogg', 296 | image: { 297 | large: ASSISTANT_LOGO_IMAGE, 298 | } 299 | } 300 | ], 301 | mediaType: 'AUDIO', 302 | optionalMediaControls: ['PAUSED', 'STOPPED'] 303 | })); 304 | }); 305 | 306 | app.handle('media_repeat', (conv) => { 307 | conv.add('This is a media response with a repeat'); 308 | conv.add(new Media({ 309 | mediaObjects: [ 310 | { 311 | name: 'Media name', 312 | description: 'Media description', 313 | url: 'https://actions.google.com/sounds/v1/cartoon/cartoon_boing.ogg', 314 | image: { 315 | large: ASSISTANT_LOGO_IMAGE, 316 | } 317 | } 318 | ], 319 | mediaType: 'AUDIO', 320 | repeatMode: 'ALL', 321 | optionalMediaControls: ['PAUSED', 'STOPPED'] 322 | })); 323 | }); 324 | 325 | // Media Status 326 | app.handle('media_status', (conv) => { 327 | const mediaStatus = conv.intent.params.MEDIA_STATUS.resolved; 328 | switch (mediaStatus) { 329 | case 'FINISHED': 330 | conv.add('Media has finished playing.'); 331 | break; 332 | case 'FAILED': 333 | conv.add('Media has failed.'); 334 | break; 335 | case 'PAUSED': 336 | conv.add(new Media({ 337 | mediaType: 'MEDIA_STATUS_ACK', 338 | })); 339 | break; 340 | case 'STOPPED': 341 | conv.add(new Media({ 342 | mediaType: 'MEDIA_STATUS_ACK', 343 | })); 344 | break; 345 | default: 346 | conv.add('Unknown media status received.'); 347 | } 348 | }); 349 | 350 | exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app); 351 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | --------------------------------------------------------------------------------