diff --git a/.github/workflows/dialogflow-cx.yaml b/.github/workflows/dialogflow-cx.yaml new file mode 100644 index 0000000000..00405c3926 --- /dev/null +++ b/.github/workflows/dialogflow-cx.yaml @@ -0,0 +1,76 @@ +name: dialogflow-cx +on: + push: + branches: + - main + paths: + - 'dialogflow-cx/**' + pull_request: + paths: + - 'dialogflow-cx/**' + pull_request_target: + types: [labeled] + schedule: + - cron: '0 0 * * 0' +jobs: + test: + if: ${{ github.event.action != 'labeled' || github.event.label.name == 'actions:force-run' }} + runs-on: ubuntu-latest + timeout-minutes: 60 + permissions: + contents: 'write' + pull-requests: 'write' + id-token: 'write' + steps: + - uses: actions/checkout@v3 + with: + ref: ${{github.event.pull_request.head.ref}} + repository: ${{github.event.pull_request.head.repo.full_name}} + - uses: google-github-actions/auth@v1.0.0 + with: + workload_identity_provider: 'projects/1046198160504/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider' + service_account: 'kokoro-system-test@long-door-651.iam.gserviceaccount.com' + create_credentials_file: 'true' + access_token_lifetime: 600s + - id: secrets + uses: 'google-github-actions/get-secretmanager-secrets@v0' + with: + secrets: |- + agent_id:nodejs-docs-samples-tests/nodejs-docs-samples-dialogflow-cx-agent-id + test_id:nodejs-docs-samples-tests/nodejs-docs-samples-dialogflow-cx-test-id + - uses: actions/setup-node@v3 + with: + node-version: 14 + - run: npm install + working-directory: dialogflow-cx + - run: npm test + working-directory: dialogflow-cx + env: + AGENT_ID: ${{ steps.secrets.outputs.agent_id }} + TEST_ID: ${{ steps.secrets.outputs.test_id }} + AGENT_PROJECT_ID: nodejs-docs-samples-tests + MOCHA_REPORTER_SUITENAME: dialogflow-cx + MOCHA_REPORTER_OUTPUT: dialogflow_cx_sponge_log.xml + MOCHA_REPORTER: xunit + - if: ${{ github.event.action == 'labeled' && github.event.label.name == 'actions:force-run' }} + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + try { + await github.rest.issues.removeLabel({ + name: 'actions:force-run', + owner: 'GoogleCloudPlatform', + repo: 'nodejs-docs-samples', + issue_number: context.payload.pull_request.number + }); + } catch (e) { + if (!e.message.includes('Label does not exist')) { + throw e; + } + } + - if: ${{ github.event_name == 'schedule' && always() }} + run: | + curl https://github.com/googleapis/repo-automation-bots/releases/download/flakybot-1.1.0/flakybot -o flakybot -s -L + chmod +x ./flakybot + ./flakybot --repo GoogleCloudPlatform/nodejs-docs-samples --commit_hash ${{github.sha}} --build_url https://github.com/${{github.repository}}/actions/runs/${{github.run_id}} diff --git a/.github/workflows/workflows.json b/.github/workflows/workflows.json index 48f7845f7d..7db436808f 100644 --- a/.github/workflows/workflows.json +++ b/.github/workflows/workflows.json @@ -34,6 +34,7 @@ "datastore/functions", "datacatalog/quickstart", "dialogflow", + "dialogflow-cx", "document-ai", "endpoints/getting-started", "endpoints/getting-started-grpc", diff --git a/dialogflow-cx/configure-webhook-to-set-form-parameter-as-optional-or-required.js b/dialogflow-cx/configure-webhook-to-set-form-parameter-as-optional-or-required.js new file mode 100644 index 0000000000..434824d1fa --- /dev/null +++ b/dialogflow-cx/configure-webhook-to-set-form-parameter-as-optional-or-required.js @@ -0,0 +1,48 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Configures a webhook to set form parameters as optional/required + */ + +// [START dialogflow_cx_v3_configure_webhooks_to_set_form_parameter_as_optional_or_required] + +exports.configureOptionalFormParam = (request, response) => { + // The value of the parameter that the webhook will set as optional or required. + // Note that the webhook cannot add or remove any form parameter + + const jsonResponse = { + pageInfo: { + formInfo: { + parameterInfo: [ + { + displayName: 'order-number', + // if required: false, the agent will not reprompt for this parameter, even if the state is 'INVALID' + required: true, + state: 'VALID', + }, + ], + }, + }, + }; + + // Info about form parameter that is sent in the webhook response: + console.log( + 'Parameter Info: \n', + jsonResponse.pageInfo.formInfo.parameterInfo[0] + ); + + response.send(jsonResponse); +}; +// [END dialogflow_cx_v3_configure_webhooks_to_set_form_parameter_as_optional_or_required] diff --git a/dialogflow-cx/create-agent.js b/dialogflow-cx/create-agent.js new file mode 100644 index 0000000000..014203108b --- /dev/null +++ b/dialogflow-cx/create-agent.js @@ -0,0 +1,56 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements + +async function main(projectId, displayName) { + // [START dialogflow_set_agent_sample] + + const parent = 'projects/' + projectId + '/locations/global'; + + const api_endpoint = 'global-dialogflow.googleapis.com'; + + const agent = { + displayName: displayName, + defaultLanguageCode: 'en', + timeZone: 'America/Los_Angeles', + }; + + const {AgentsClient} = require('@google-cloud/dialogflow-cx'); + + const client = new AgentsClient({apiEndpoint: api_endpoint}); + + async function setAgentSample() { + const request = { + agent, + parent, + }; + + const [response] = await client.createAgent(request); + console.log(`response: ${JSON.stringify(response, null, 2)}`); + + // Delete created agent resource + client.deleteAgent({name: response.name}); + } + await setAgentSample(); + // [END dialogflow_set_agent_sample] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/dialogflow-cx/create-page.js b/dialogflow-cx/create-page.js new file mode 100644 index 0000000000..f4b0dd2c0f --- /dev/null +++ b/dialogflow-cx/create-page.js @@ -0,0 +1,51 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {PagesClient} = require('@google-cloud/dialogflow-cx'); + +async function main(projectId, agentId, flowId, location, displayName) { + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const agentId = 'my-agent'; + // const flowId = 'my-flow'; + // const displayName = 'my-display-name'; + // const location = 'global'; + + // [START dialogflow_cx_create_page_sample] + async function createPage(projectId, agentId, flowId, location, displayName) { + const pagesClient = new PagesClient(); + + const createPageRequest = { + parent: `projects/${projectId}/locations/${location}/agents/${agentId}/flows/${flowId}`, + page: { + displayName: displayName, + }, + }; + + const response = await pagesClient.createPage(createPageRequest); + console.log(response); + } + // [END dialogflow_cx_create_page_sample] + + await createPage(projectId, agentId, flowId, location, displayName); +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/dialogflow-cx/delete-page.js b/dialogflow-cx/delete-page.js new file mode 100644 index 0000000000..a7dcaa46f1 --- /dev/null +++ b/dialogflow-cx/delete-page.js @@ -0,0 +1,48 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {PagesClient} = require('@google-cloud/dialogflow-cx'); + +async function main(projectId, agentId, flowId, pageId, location) { + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const agentId = 'my-agent'; + // const flowId = 'my-flow'; + // const pageId = 'my-page'; + // const location = 'global'; + + // [START dialogflow_cx_delete_page_sample] + async function deletePage(projectId, agentId, flowId, pageId, location) { + const pagesClient = new PagesClient(); + + const req = { + name: `projects/${projectId}/locations/${location}/agents/${agentId}/flows/${flowId}/pages/${pageId}`, + }; + + const response = await pagesClient.deletePage(req); + console.log(response); + } + // [END dialogflow_cx_delete_page_sample] + + await deletePage(projectId, agentId, flowId, pageId, location); +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/dialogflow-cx/detect-intent-audio.js b/dialogflow-cx/detect-intent-audio.js new file mode 100644 index 0000000000..a389c00fc8 --- /dev/null +++ b/dialogflow-cx/detect-intent-audio.js @@ -0,0 +1,102 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main( + projectId, + location, + agentId, + audioFileName, + encoding, + sampleRateHertz, + languageCode +) { + // [START dialogflow_cx_detect_intent_audio] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const location = 'global'; + // const agentId = 'my-agent'; + // const audioFileName = '/path/to/audio.raw'; + // const encoding = 'AUDIO_ENCODING_LINEAR_16'; + // const sampleRateHertz = 16000; + // const languageCode = 'en' + + // Imports the Google Cloud Some API library + const {SessionsClient} = require('@google-cloud/dialogflow-cx'); + /** + * Example for regional endpoint: + * const location = 'us-central1' + * const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'}) + */ + const client = new SessionsClient(); + + const fs = require('fs'); + const util = require('util'); + + async function detectIntentAudio() { + const sessionId = Math.random().toString(36).substring(7); + const sessionPath = client.projectLocationAgentSessionPath( + projectId, + location, + agentId, + sessionId + ); + console.info(sessionPath); + + // Read the content of the audio file and send it as part of the request. + const readFile = util.promisify(fs.readFile); + const inputAudio = await readFile(audioFileName); + + const request = { + session: sessionPath, + queryInput: { + audio: { + config: { + audioEncoding: encoding, + sampleRateHertz: sampleRateHertz, + }, + audio: inputAudio, + }, + languageCode, + }, + }; + const [response] = await client.detectIntent(request); + console.log(`User Query: ${response.queryResult.transcript}`); + for (const message of response.queryResult.responseMessages) { + if (message.text) { + console.log(`Agent Response: ${message.text.text}`); + } + } + if (response.queryResult.match.intent) { + console.log( + `Matched Intent: ${response.queryResult.match.intent.displayName}` + ); + } + console.log( + `Current Page: ${response.queryResult.currentPage.displayName}` + ); + } + + detectIntentAudio(); + // [END dialogflow_cx_detect_intent_audio] +} + +main(...process.argv.slice(2)); +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/dialogflow-cx/detect-intent-disabled-webhook.js b/dialogflow-cx/detect-intent-disabled-webhook.js new file mode 100644 index 0000000000..1c9a04e0b7 --- /dev/null +++ b/dialogflow-cx/detect-intent-disabled-webhook.js @@ -0,0 +1,75 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main(projectId, location, agentId, query, languageCode) { + // [START dialogflow_cx_detect_intent_with_disabled_webhook] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const location = 'global'; + // const agentId = 'my-agent'; + // const query = 'Hello'; + // const languageCode = 'en' + + const {SessionsClient} = require('@google-cloud/dialogflow-cx'); + /** + * Example for regional endpoint: + * const location = 'us-central1' + * const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'}) + */ + const client = new SessionsClient(); + + async function detectIntentText() { + const sessionId = Math.random().toString(36).substring(7); + const sessionPath = client.projectLocationAgentSessionPath( + projectId, + location, + agentId, + sessionId + ); + console.info(sessionPath); + + const request = { + session: sessionPath, + queryParams: { + disableWebhook: true, + }, + queryInput: { + text: { + text: query, + }, + languageCode, + }, + }; + const [response] = await client.detectIntent(request); + console.log(`Detect Intent Request: ${request.queryParams.disableWebhook}`); + for (const message of response.queryResult.responseMessages) { + if (message.text) { + console.log(`Agent Response: ${message.text.text}`); + } + } + } + + detectIntentText(); + // [END dialogflow_cx_detect_intent_with_disabled_webhook] +} + +main(...process.argv.slice(2)); +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/dialogflow-cx/detect-intent-event.js b/dialogflow-cx/detect-intent-event.js new file mode 100644 index 0000000000..035bbc5fe8 --- /dev/null +++ b/dialogflow-cx/detect-intent-event.js @@ -0,0 +1,102 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * Detects intent using EventInput + * + * See https://cloud.google.com/dialogflow/cx/docs/quick/api before running the code snippet. + */ + +'use strict'; + +function main(projectId, location, agentId, event, languageCode) { + // [START dialogflow_cx_v3_detect_intent_event_input_async] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + /** + * Required. The name of the session this query is sent to. + * Format: `projects//locations//agents//sessions/` or `projects//locations//agents//environments//sessions/`. + * If `Environment ID` is not specified, we assume default 'draft' + * environment. + * It's up to the API caller to choose an appropriate `Session ID`. It can be + * a random number or some type of session identifiers (preferably hashed). + * The length of the `Session ID` must not exceed 36 characters. + * For more information, see the sessions + * guide (https://cloud.google.com/dialogflow/cx/docs/concept/session). + * Note: Always use agent versions for production traffic. + * See Versions and + * environments (https://cloud.google.com/dialogflow/cx/docs/concept/version). + */ + + /** + * Optional. The parameters of this query. + */ + // const queryParams = {} + /** + * Required. The input specification. See https://cloud.google.com/dialogflow/cx/docs/reference/rest/v3beta1/ConversationTurn#QueryInput for information about query inputs. + */ + // const event = 'name-of-event-to-trigger'; + + // Imports the Cx library + const {SessionsClient} = require('@google-cloud/dialogflow-cx'); + /** + * Example for regional endpoint: + * const location = 'us-central1' + * const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'}) + */ + // Instantiates a client + const cxClient = new SessionsClient(); + + async function detectIntentWithEventInput() { + const sessionId = Math.random().toString(36).substring(7); + const sessionPath = cxClient.projectLocationAgentSessionPath( + projectId, + location, + agentId, + sessionId + ); + + // Construct detect intent request + const request = { + session: sessionPath, + queryInput: { + event: { + event: event, + }, + languageCode, + }, + }; + + // Send request and receive response + const [response] = await cxClient.detectIntent(request); + console.log(`Event Name: ${event}`); + + // Response message from the triggered event + console.log('Agent Response: \n'); + console.log(response.queryResult.responseMessages[0].text.text[0]); + } + + detectIntentWithEventInput(); + // [END dialogflow_cx_v3_detect_intent_event_input_async] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/dialogflow-cx/detect-intent-streaming.js b/dialogflow-cx/detect-intent-streaming.js new file mode 100644 index 0000000000..c0f02959ca --- /dev/null +++ b/dialogflow-cx/detect-intent-streaming.js @@ -0,0 +1,133 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main( + projectId, + location, + agentId, + audioFileName, + encoding, + sampleRateHertz, + languageCode +) { + // [START dialogflow_cx_detect_intent_streaming] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const location = 'global'; + // const agentId = 'my-agent'; + // const audioFileName = '/path/to/audio.raw'; + // const encoding = 'AUDIO_ENCODING_LINEAR_16'; + // const sampleRateHertz = 16000; + // const languageCode = 'en' + + // Imports the Google Cloud Some API library + const {SessionsClient} = require('@google-cloud/dialogflow-cx'); + /** + * Example for regional endpoint: + * const location = 'us-central1' + * const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'}) + */ + const client = new SessionsClient(); + + const fs = require('fs'); + const util = require('util'); + const {Transform, pipeline} = require('stream'); + const pump = util.promisify(pipeline); + + async function detectIntentAudio() { + const sessionId = Math.random().toString(36).substring(7); + const sessionPath = client.projectLocationAgentSessionPath( + projectId, + location, + agentId, + sessionId + ); + console.info(sessionPath); + + // Create a stream for the streaming request. + const detectStream = client + .streamingDetectIntent() + .on('error', console.error) + .on('data', data => { + if (data.recognitionResult) { + console.log( + `Intermediate Transcript: ${data.recognitionResult.transcript}` + ); + } else { + console.log('Detected Intent:'); + const result = data.detectIntentResponse.queryResult; + + console.log(`User Query: ${result.transcript}`); + for (const message of result.responseMessages) { + if (message.text) { + console.log(`Agent Response: ${message.text.text}`); + } + } + if (result.match.intent) { + console.log(`Matched Intent: ${result.match.intent.displayName}`); + } + console.log(`Current Page: ${result.currentPage.displayName}`); + } + }); + + // Write the initial stream request to config for audio input. + const initialStreamRequest = { + session: sessionPath, + queryInput: { + audio: { + config: { + audioEncoding: encoding, + sampleRateHertz: sampleRateHertz, + synthesize_speech_config: { + voice: { + // Set's the name and gender of the ssml voice + name: 'en-GB-Standard-A', + ssml_gender: 'SSML_VOICE_GENDER_FEMALE', + }, + }, + singleUtterance: true, + }, + }, + languageCode: languageCode, + }, + }; + detectStream.write(initialStreamRequest); + + // Stream the audio from audio file to Dialogflow. + await pump( + fs.createReadStream(audioFileName), + // Format the audio stream into the request format. + new Transform({ + objectMode: true, + transform: (obj, _, next) => { + next(null, {queryInput: {audio: {audio: obj}}}); + }, + }), + detectStream + ); + } + + detectIntentAudio(); + // [END dialogflow_cx_detect_intent_streaming] +} + +main(...process.argv.slice(2)); +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/dialogflow-cx/detect-intent-synthesize-tts-response.js b/dialogflow-cx/detect-intent-synthesize-tts-response.js new file mode 100644 index 0000000000..d75521b9ad --- /dev/null +++ b/dialogflow-cx/detect-intent-synthesize-tts-response.js @@ -0,0 +1,105 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * Detects intent and returns a synthesized Text-to-Speech (TTS) response + + * See https://cloud.google.com/dialogflow/cx/docs/quick/api before running the code snippet. + */ + +'use strict'; + +function main( + projectId, + location, + agentId, + sessionId, + query, + languageCode, + outputFile +) { + // [START dialogflow_cx_v3_detect_intent_synthesize_tts_response_async] + + // Imports the Cx library + const {SessionsClient} = require('@google-cloud/dialogflow-cx'); + + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const projectId = 'ID of GCP project associated with your Dialogflow agent'; + // const sessionId = `user specific ID of session, e.g. 12345`; + // const query = `phrase(s) to pass to detect, e.g. I'd like to reserve a room for six people`; + // const languageCode = 'BCP-47 language code, e.g. en-US'; + // const outputFile = `path for audio output file, e.g. ./resources/myOutput.wav`; + + // Instantiates a Sessions client + const sessionsClient = new SessionsClient(); + + // Define session path + const sessionPath = sessionsClient.projectLocationAgentSessionPath( + projectId, + location, + agentId, + sessionId + ); + const fs = require('fs'); + const util = require('util'); + + async function detectIntentSynthesizeTTSResponse() { + // Configuration of how speech should be synthesized. See https://cloud.google.com/dialogflow/cx/docs/reference/rest/v3/OutputAudioConfig#SynthesizeSpeechConfig + const synthesizeSpeechConfig = { + speakingRate: 1.25, + pitch: 10.0, + }; + + // Constructs the audio query request + const request = { + session: sessionPath, + queryInput: { + text: { + text: query, + }, + languageCode: languageCode, + }, + outputAudioConfig: { + audioEncoding: 'OUTPUT_AUDIO_ENCODING_LINEAR_16', + synthesizeSpeechConfig: synthesizeSpeechConfig, + }, + }; + + // Sends the detectIntent request + const [response] = await sessionsClient.detectIntent(request); + // Output audio configurations + console.log( + `Speaking Rate: ${response.outputAudioConfig.synthesizeSpeechConfig.speakingRate}` + ); + console.log( + `Pitch: ${response.outputAudioConfig.synthesizeSpeechConfig.pitch}` + ); + + const audioFile = response.outputAudio; + // Writes audio content to output file + util.promisify(fs.writeFile)(outputFile, audioFile, 'binary'); + console.log(`Audio content written to file: ${outputFile}`); + } + detectIntentSynthesizeTTSResponse(); + // [END dialogflow_cx_v3_detect_intent_synthesize_tts_response_async] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/dialogflow-cx/detect-intent-text.js b/dialogflow-cx/detect-intent-text.js new file mode 100644 index 0000000000..3f90567f98 --- /dev/null +++ b/dialogflow-cx/detect-intent-text.js @@ -0,0 +1,78 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main(projectId, location, agentId, query, languageCode) { + // [START dialogflow_cx_detect_intent_text] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const location = 'global'; + // const agentId = 'my-agent'; + // const query = 'Hello'; + // const languageCode = 'en' + + // Imports the Google Cloud Some API library + const {SessionsClient} = require('@google-cloud/dialogflow-cx'); + /** + * Example for regional endpoint: + * const location = 'us-central1' + * const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'}) + */ + const client = new SessionsClient(); + + async function detectIntentText() { + const sessionId = Math.random().toString(36).substring(7); + const sessionPath = client.projectLocationAgentSessionPath( + projectId, + location, + agentId, + sessionId + ); + const request = { + session: sessionPath, + queryInput: { + text: { + text: query, + }, + languageCode, + }, + }; + const [response] = await client.detectIntent(request); + for (const message of response.queryResult.responseMessages) { + if (message.text) { + console.log(`Agent Response: ${message.text.text}`); + } + } + if (response.queryResult.match.intent) { + console.log( + `Matched Intent: ${response.queryResult.match.intent.displayName}` + ); + } + console.log( + `Current Page: ${response.queryResult.currentPage.displayName}` + ); + } + + detectIntentText(); + // [END dialogflow_cx_detect_intent_text] +} + +main(...process.argv.slice(2)); +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/dialogflow-cx/detect-intent-with-intent-input.js b/dialogflow-cx/detect-intent-with-intent-input.js new file mode 100644 index 0000000000..d08ec4def3 --- /dev/null +++ b/dialogflow-cx/detect-intent-with-intent-input.js @@ -0,0 +1,108 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * Trigger intent programmatically rather than as a result of natural language processing + + * See https://cloud.google.com/dialogflow/cx/docs/quick/api before running the code snippet. + */ + +'use strict'; + +function main(projectId, location, agentId, intentId, languageCode) { + // [START dialogflow_cx_v3_detect_intent_with_intent_input_async] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + + /** + * const projectId = 'your-project-id'; + * const location = 'location'; + * const agentId = 'your-agent-id'; + * const languageCode = 'your-language-code'; + */ + + /** + * The input specification. See https://cloud.google.com/dialogflow/cx/docs/reference/rest/v3beta1/ConversationTurn#QueryInput for information about query inputs. + */ + // const intentId = 'unique-identifier-of-the-intent-to-trigger'; + + // Imports the Cx library + const { + SessionsClient, + IntentsClient, + } = require('@google-cloud/dialogflow-cx'); + /** + * Example for regional endpoint: + * const location = 'us-central1' + * const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'}) + */ + // Instantiates a Sessions client + const sessionsClient = new SessionsClient(); + + // Instantiates an Intents client + const intentsClient = new IntentsClient(); + + async function detectIntentWithIntentInput() { + const sessionId = Math.random().toString(36).substring(7); + + // Creates session path + const sessionPath = sessionsClient.projectLocationAgentSessionPath( + projectId, + location, + agentId, + sessionId + ); + + // Creates intent path. Format: projects//locations//agents//intents/ + const intentPath = intentsClient.intentPath( + projectId, + location, + agentId, + intentId + ); + + // Construct detectIntent request + const request = { + session: sessionPath, + queryInput: { + intent: { + intent: intentPath, + }, + languageCode, + }, + }; + + // Send request and receive response + const [response] = await sessionsClient.detectIntent(request); + + // Display the name of the detected intent + console.log('Intent Name: \n'); + console.log(response.queryResult.intent.displayName); + + // Agent responds with fulfillment message of the detected intent + console.log('Agent Response: \n'); + console.log(response.queryResult.responseMessages[0].text.text[0]); + } + + detectIntentWithIntentInput(); + // [END dialogflow_cx_v3_detect_intent_with_intent_input_async] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/dialogflow-cx/detect-intent-with-sentiment-analysis.js b/dialogflow-cx/detect-intent-with-sentiment-analysis.js new file mode 100644 index 0000000000..a760940cf1 --- /dev/null +++ b/dialogflow-cx/detect-intent-with-sentiment-analysis.js @@ -0,0 +1,120 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * Detects intent with sentiment analysis + * + * See https://cloud.google.com/dialogflow/cx/docs/quick/api before running the code snippet. + */ + +'use strict'; + +function main(projectId, location, agentId, query, languageCode) { + // [START dialogflow_cx_v3_detect_intent_sentiment_analysis_async] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + /** + * Required. The name of the session this query is sent to. + * Format: `projects//locations//agents//sessions/` or `projects//locations//agents//environments//sessions/`. + * If `Environment ID` is not specified, we assume default 'draft' + * environment. + * It's up to the API caller to choose an appropriate `Session ID`. It can be + * a random number or some type of session identifiers (preferably hashed). + * The length of the `Session ID` must not exceed 36 characters. + * For more information, see the sessions + * guide (https://cloud.google.com/dialogflow/cx/docs/concept/session). + * Note: Always use agent versions for production traffic. + * See Versions and + * environments (https://cloud.google.com/dialogflow/cx/docs/concept/version). + */ + + /** + * Optional. The parameters of this query. + */ + // const queryParams = {} + /** + * Required. The input specification. See https://cloud.google.com/dialogflow/cx/docs/reference/rest/v3beta1/ConversationTurn#QueryInput for information about query inputs. + */ + // const text = 'text-of-your-query'; + + // Imports the Cx library + const {SessionsClient} = require('@google-cloud/dialogflow-cx'); + /** + * Example for regional endpoint: + * const location = 'us-central1' + * const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'}) + */ + // Instantiates a client + const cxClient = new SessionsClient(); + + // Configures whether sentiment analysis should be performed. If not provided, sentiment analysis is not performed. + const analyzeQueryTextSentiment = true; + + async function detectIntentWithSentimentAnalysis() { + const sessionId = Math.random().toString(36).substring(7); + const sessionPath = cxClient.projectLocationAgentSessionPath( + projectId, + location, + agentId, + sessionId + ); + + // Construct detect intent request + const request = { + session: sessionPath, + queryInput: { + text: { + text: query, + }, + languageCode, + }, + queryParams: { + analyzeQueryTextSentiment: analyzeQueryTextSentiment, + }, + }; + + // Run request + const [response] = await cxClient.detectIntent(request); + console.log(`User Query: ${query}`); + + // Shows result of sentiment analysis (sentimentAnalysisResult) + const sentimentAnalysis = response.queryResult.sentimentAnalysisResult; + + // Determines sentiment score of user query + let sentiment; + if (sentimentAnalysis.score < 0) { + sentiment = 'negative'; + } else if (sentimentAnalysis.score > 0) { + sentiment = 'positive'; + } else { + sentiment = 'neutral'; + } + console.log( + `User input sentiment has a score of ${sentimentAnalysis.score}, which indicates ${sentiment} sentiment.` + ); + } + + detectIntentWithSentimentAnalysis(); + // [END dialogflow_cx_v3_detect_intent_sentiment_analysis_async] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/dialogflow-cx/list-intents.js b/dialogflow-cx/list-intents.js new file mode 100644 index 0000000000..f28ec20755 --- /dev/null +++ b/dialogflow-cx/list-intents.js @@ -0,0 +1,60 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main(projectId, location, agentId) { + // [START dialogflow_cx_list_intents] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const location = 'global'; + // const agentId = 'my-agent'; + + // Imports the Google Cloud Some API library + const {IntentsClient} = require('@google-cloud/dialogflow-cx'); + /** + * Example for regional endpoint: + * const location = 'us-central1' + * const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'}) + */ + const client = new IntentsClient(); + + async function listIntents() { + const parent = client.agentPath(projectId, location, agentId); + console.info(parent); + + const [intents] = await client.listIntents({ + parent, + pageSize: 100, + }); + intents.forEach(intent => { + console.log('===================='); + console.log(`Intent name: ${intent.name}`); + console.log(`Intent display name: ${intent.displayName}`); + console.log(`# Parameters: ${intent.parameters.length}`); + console.log(`# Training Phrases: ${intent.trainingPhrases.length}`); + }); + } + + listIntents(); + // [END dialogflow_cx_list_intents] +} + +main(...process.argv.slice(2)); +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/dialogflow-cx/list-page.js b/dialogflow-cx/list-page.js new file mode 100644 index 0000000000..3dbe8292af --- /dev/null +++ b/dialogflow-cx/list-page.js @@ -0,0 +1,47 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {PagesClient} = require('@google-cloud/dialogflow-cx'); + +async function main(projectId, agentId, flowId, location) { + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const agentId = 'my-agent'; + // const flowId = 'my-flow'; + // const location = 'global'; + + // [START dialogflow_cx_list_page_sample] + async function listPages(projectId, agentId, flowId, location) { + const pagesClient = new PagesClient(); + const listPageRequest = { + parent: `projects/${projectId}/locations/${location}/agents/${agentId}/flows/${flowId}`, + languageCode: 'en', + }; + + const response = await pagesClient.listPages(listPageRequest); + console.log(response); + } + // [END dialogflow_cx_list_page_sample] + + await listPages(projectId, agentId, flowId, location); +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/dialogflow-cx/list-testcase-results.js b/dialogflow-cx/list-testcase-results.js new file mode 100644 index 0000000000..89a2be1b4a --- /dev/null +++ b/dialogflow-cx/list-testcase-results.js @@ -0,0 +1,49 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main(projectId, agentId, testId, location) { + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const agentId = 'my-agent'; + // const testId = 'my-flow'; + // const location = 'global'; + + // [START dialogflow_cx_list_testcase_sample] + const parent = `projects/${projectId}/locations/${location}/agents/${agentId}/testCases/${testId}`; + + const {TestCasesClient} = require('@google-cloud/dialogflow-cx'); + + const client = new TestCasesClient({ + apiEndpoint: 'global-dialogflow.googleapis.com', + }); + const req = { + parent, + filter: 'environment=draft', + }; + + const res = await client.listTestCaseResults(req); + + console.log(res); + // [END dialogflow_cx_list_testcase_sample] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/dialogflow-cx/long-running-operation.js b/dialogflow-cx/long-running-operation.js new file mode 100644 index 0000000000..020a7a2e25 --- /dev/null +++ b/dialogflow-cx/long-running-operation.js @@ -0,0 +1,54 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main(projectId, agentId, location) { + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const agentId = 'my-agent'; + // const location = 'global'; + + // [START dialogflow_cx_log_running_operation] + + const {AgentsClient, protos} = require('@google-cloud/dialogflow-cx'); + + const api_endpoint = `${location}-dialogflow.googleapis.com`; + + const client = new AgentsClient({apiEndpoint: api_endpoint}); + + const exportAgentRequest = + new protos.google.cloud.dialogflow.cx.v3.ExportAgentRequest(); + + exportAgentRequest.name = `projects/${projectId}/locations/${location}/agents/${agentId}`; + + // exportAgent call returns a promise to a long running operation + const [operation] = await client.exportAgent(exportAgentRequest); + + // Waiting for the long running opporation to finish + const [response] = await operation.promise(); + + // Prints the result of the operation when the operation is done + console.log(response); + + // [END dialogflow_cx_log_running_operation] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/dialogflow-cx/package.json b/dialogflow-cx/package.json new file mode 100644 index 0000000000..5438f221af --- /dev/null +++ b/dialogflow-cx/package.json @@ -0,0 +1,24 @@ +{ + "name": "nodejs-dialogflow-cx-samples", + "private": true, + "license": "Apache-2.0", + "author": "Google LLC", + "engines": { + "node": ">=12.0.0" + }, + "files": [ + "*.js" + ], + "scripts": { + "test": "c8 mocha --timeout 600000 test/*.js" + }, + "dependencies": { + "@google-cloud/dialogflow-cx": "^3.1.2", + "uuid": "^9.0.0" + }, + "devDependencies": { + "c8": "^7.3.0", + "chai": "^4.2.0", + "mocha": "^8.1.1" + } +} diff --git a/dialogflow-cx/quickstart.js b/dialogflow-cx/quickstart.js new file mode 100644 index 0000000000..4e7efe3c31 --- /dev/null +++ b/dialogflow-cx/quickstart.js @@ -0,0 +1,104 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main( + projectId, + location, + agentId, + audioFileName, + encoding, + sampleRateHertz, + languageCode +) { + // [START dialogflow_cx_quickstart] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const location = 'global'; + // const agentId = 'my-agent'; + // const audioFileName = '/path/to/audio.raw'; + // const encoding = 'AUDIO_ENCODING_LINEAR_16'; + // const sampleRateHertz = 16000; + // const languageCode = 'en' + + // Imports the Google Cloud Some API library + const {SessionsClient} = require('@google-cloud/dialogflow-cx'); + /** + * Example for regional endpoint: + * const location = 'us-central1' + * const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'}) + */ + const client = new SessionsClient(); + + const fs = require('fs'); + const util = require('util'); + // Assumes uuid module has been installed from npm, + // npm i uuid: + const {v4} = require('uuid'); + + async function detectIntentAudio() { + const sessionId = v4(); + const sessionPath = client.projectLocationAgentSessionPath( + projectId, + location, + agentId, + sessionId + ); + + // Read the content of the audio file and send it as part of the request. + const readFile = util.promisify(fs.readFile); + const inputAudio = await readFile(audioFileName); + + const request = { + session: sessionPath, + queryInput: { + audio: { + config: { + audioEncoding: encoding, + sampleRateHertz: sampleRateHertz, + }, + audio: inputAudio, + }, + languageCode, + }, + }; + const [response] = await client.detectIntent(request); + console.log(`User Query: ${response.queryResult.transcript}`); + for (const message of response.queryResult.responseMessages) { + if (message.text) { + console.log(`Agent Response: ${message.text.text}`); + } + } + if (response.queryResult.match.intent) { + console.log( + `Matched Intent: ${response.queryResult.match.intent.displayName}` + ); + } + console.log( + `Current Page: ${response.queryResult.currentPage.displayName}` + ); + } + + detectIntentAudio(); + // [END dialogflow_cx_quickstart] +} + +main(...process.argv.slice(2)); +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/dialogflow-cx/resources/book_a_room.wav b/dialogflow-cx/resources/book_a_room.wav new file mode 100644 index 0000000000..9124e92794 Binary files /dev/null and b/dialogflow-cx/resources/book_a_room.wav differ diff --git a/dialogflow-cx/resources/output.wav b/dialogflow-cx/resources/output.wav new file mode 100644 index 0000000000..c180743f63 Binary files /dev/null and b/dialogflow-cx/resources/output.wav differ diff --git a/dialogflow-cx/streaming-detect-intent-partial-response.js b/dialogflow-cx/streaming-detect-intent-partial-response.js new file mode 100644 index 0000000000..6da8439b10 --- /dev/null +++ b/dialogflow-cx/streaming-detect-intent-partial-response.js @@ -0,0 +1,116 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main( + projectId, + location, + agentId, + audioFileName, + encoding, + sampleRateHertz, + languageCode +) { + // [START dialogflow_cx_streaming_detect_intent_enable_partial_response] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const location = 'global'; + // const agentId = 'my-agent'; + // const audioFileName = '/path/to/audio.raw'; + // const encoding = 'AUDIO_ENCODING_LINEAR_16'; + // const sampleRateHertz = 16000; + // const languageCode = 'en'; + + const {SessionsClient} = require('@google-cloud/dialogflow-cx'); + /** + * Example for regional endpoint: + * const location = 'us-central1' + * const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'}) + */ + const client = new SessionsClient(); + + const fs = require('fs'); + const util = require('util'); + const {Transform, pipeline} = require('stream'); + const pump = util.promisify(pipeline); + + async function streamingDetectIntentPartialResponse() { + const sessionId = Math.random().toString(36).substring(7); + const sessionPath = client.projectLocationAgentSessionPath( + projectId, + location, + agentId, + sessionId + ); + + const request = { + session: sessionPath, + queryInput: { + audio: { + config: { + audio_encoding: encoding, + sampleRateHertz: sampleRateHertz, + singleUtterance: true, + }, + }, + languageCode: languageCode, + }, + enablePartialResponse: true, + }; + + const stream = await client.streamingDetectIntent(); + stream.on('data', data => { + if (data.detectIntentResponse) { + const result = data.detectIntentResponse.queryResult; + + for (const message of result.responseMessages) { + if (message.text) { + console.log(`Agent Response: ${message.text.text}`); + } + } + } + }); + stream.on('error', err => { + console.log(err); + }); + stream.on('end', () => { + /* API call completed */ + }); + stream.write(request); + + // Stream the audio from audio file to Dialogflow. + await pump( + fs.createReadStream(audioFileName), + // Format the audio stream into the request format. + new Transform({ + objectMode: true, + transform: (obj, _, next) => { + next(null, {queryInput: {audio: {audio: obj}}}); + }, + }), + stream + ); + } + streamingDetectIntentPartialResponse(); + // [END dialogflow_cx_streaming_detect_intent_enable_partial_response] +} + +main(...process.argv.slice(2)); +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/dialogflow-cx/test/configure-webhook-to-set-form-parameter-as-optional-or-required.js b/dialogflow-cx/test/configure-webhook-to-set-form-parameter-as-optional-or-required.js new file mode 100644 index 0000000000..8cf58a6abc --- /dev/null +++ b/dialogflow-cx/test/configure-webhook-to-set-form-parameter-as-optional-or-required.js @@ -0,0 +1,68 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const webhook = require('../configure-webhook-to-set-form-parameter-as-optional-or-required'); + +describe('configure optional or required form parameter', () => { + it('should test that webhook sets parameter as required', async () => { + const request = { + body: { + fulfillmentInfo: { + tag: 'optional-or-required', + }, + pageInfo: { + formInfo: { + parameterInfo: [ + { + displayName: 'number', + value: 100, + }, + ], + }, + }, + }, + }; + const temp = JSON.stringify(request); + let response = ''; + + const res = { + send: function (s) { + response = JSON.stringify(s); + }, + }; + + webhook.configureOptionalFormParam(JSON.parse(temp), res); + assert.include(response, '"required":true'); + }); +}); diff --git a/dialogflow-cx/test/create-agent.test.js b/dialogflow-cx/test/create-agent.test.js new file mode 100644 index 0000000000..23d805a113 --- /dev/null +++ b/dialogflow-cx/test/create-agent.test.js @@ -0,0 +1,32 @@ +// // Copyright 2021 Google LLC +// // +// // Licensed under the Apache License, Version 2.0 (the "License"); +// // you may not use this file except in compliance with the License. +// // You may obtain a copy of the License at +// // +// // http://www.apache.org/licenses/LICENSE-2.0 +// // +// // Unless required by applicable law or agreed to in writing, software +// // distributed under the License is distributed on an "AS IS" BASIS, +// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// // See the License for the specific language governing permissions and +// // limitations under the License. + +// 'use strict'; + +// const {assert} = require('chai'); +// const {describe, it} = require('mocha'); +// const uuid = require('uuid'); +// const execSync = require('child_process').execSync; +// const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +// describe('create agent', () => { +// const cmd = 'node create-agent.js'; +// const agentId = `temp_agent_${uuid.v4().split('-')[0]}`; +// const projectId = process.env.GCLOUD_PROJECT; + +// it('should create agent', async () => { +// const output = exec(`${cmd} ${projectId} ${agentId}`); +// assert.include(output, agentId); +// }); +// }); diff --git a/dialogflow-cx/test/detect-intent-audio.test.js b/dialogflow-cx/test/detect-intent-audio.test.js new file mode 100644 index 0000000000..e0a3a2745c --- /dev/null +++ b/dialogflow-cx/test/detect-intent-audio.test.js @@ -0,0 +1,40 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +describe('detect intent with audio input', () => { + const cmd = 'node detect-intent-audio.js'; + + const projectId = process.env.GCLOUD_PROJECT; + const location = 'global'; + const agentId = 'b1808233-450b-4065-9492-bc9b40151641'; + const audioFileName = 'resources/book_a_room.wav'; + const encoding = 'AUDIO_ENCODING_LINEAR_16'; + const sampleRateHertz = 16000; + const languageCode = 'en'; + + it('should response to "book a room"', async () => { + const output = exec( + `${cmd} ${projectId} ${location} ${agentId} ${audioFileName} ${encoding} ${sampleRateHertz} ${languageCode}` + ); + console.log(output); + assert.include(output, '?'); + }); +}); diff --git a/dialogflow-cx/test/detect-intent-disabled-webhook-test.js b/dialogflow-cx/test/detect-intent-disabled-webhook-test.js new file mode 100644 index 0000000000..7ff993ea86 --- /dev/null +++ b/dialogflow-cx/test/detect-intent-disabled-webhook-test.js @@ -0,0 +1,36 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +describe('detect intent with disabled webhook', () => { + const cmd = 'node detect-intent-disabled-webhook.js'; + + const projectId = process.env.GCLOUD_PROJECT; + const location = 'global'; + const agentId = 'b1808233-450b-4065-9492-bc9b40151641'; + const languageCode = 'en'; + + it('should have disableWebhook set to "true"', async () => { + const output = exec( + `${cmd} ${projectId} ${location} ${agentId} 'hello' ${languageCode}` + ); + assert.include(output, 'true'); + }); +}); diff --git a/dialogflow-cx/test/detect-intent-event-test.js b/dialogflow-cx/test/detect-intent-event-test.js new file mode 100644 index 0000000000..e0f4b9f520 --- /dev/null +++ b/dialogflow-cx/test/detect-intent-event-test.js @@ -0,0 +1,38 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +describe('detect intent with EventInput', () => { + const cmd = 'node detect-intent-event.js'; + + const projectId = process.env.GCLOUD_PROJECT; + const location = 'global'; + const agentId = 'b1808233-450b-4065-9492-bc9b40151641'; + const languageCode = 'en'; + const event = '"No-input Options"'; + + it('should return agent response for custom event', async () => { + const output = exec( + `${cmd} ${projectId} ${location} ${agentId} ${event} ${languageCode}` + ); + console.log('OUTPUT', output); + assert.include(output, "Hi! I'm the Rental Car Virtual Agent"); + }); +}); diff --git a/dialogflow-cx/test/detect-intent-sentiment-analysis-test.js b/dialogflow-cx/test/detect-intent-sentiment-analysis-test.js new file mode 100644 index 0000000000..6b5b0e8f71 --- /dev/null +++ b/dialogflow-cx/test/detect-intent-sentiment-analysis-test.js @@ -0,0 +1,50 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +describe('detect intent with sentiment analysis', () => { + const cmd = 'node detect-intent-with-sentiment-analysis.js'; + + const projectId = process.env.GCLOUD_PROJECT; + const location = 'global'; + const agentId = 'b1808233-450b-4065-9492-bc9b40151641'; + const languageCode = 'en'; + + it('should detect negative sentiment score of user query', async () => { + const output = exec( + `${cmd} ${projectId} ${location} ${agentId} 'I am not happy' ${languageCode}` + ); + assert.include(output, 'negative'); + }); + + it('should detect positive intent', async () => { + const output = exec( + `${cmd} ${projectId} ${location} ${agentId} 'Perfect!' ${languageCode}` + ); + assert.include(output, 'positive'); + }); + + it('should detect neutral intent', async () => { + const output = exec( + `${cmd} ${projectId} ${location} ${agentId} 'whatever' ${languageCode}` + ); + assert.include(output, 'neutral'); + }); +}); diff --git a/dialogflow-cx/test/detect-intent-synthesize-tts-response-test.js b/dialogflow-cx/test/detect-intent-synthesize-tts-response-test.js new file mode 100644 index 0000000000..4ab8aae9a8 --- /dev/null +++ b/dialogflow-cx/test/detect-intent-synthesize-tts-response-test.js @@ -0,0 +1,40 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +describe('detect intent with TTS response', () => { + const cmd = 'node detect-intent-synthesize-tts-response.js'; + + const projectId = process.env.GCLOUD_PROJECT; + const location = 'global'; + const agentId = 'b1808233-450b-4065-9492-bc9b40151641'; + const sessionId = 'SESSION_ID'; + const testQuery = 'Hello!'; + const languageCode = 'en-US'; + const outputFile = './resources/output.wav'; + + it('should write TTS response to output file', async () => { + const output = exec( + `${cmd} ${projectId} ${location} ${agentId} ${sessionId} ${testQuery} ${languageCode} ${outputFile}` + ); + console.log(output); + assert.include(output, `Audio content written to file: ${outputFile}`); + }); +}); diff --git a/dialogflow-cx/test/detect-intent-text.test.js b/dialogflow-cx/test/detect-intent-text.test.js new file mode 100644 index 0000000000..7fd3bf454a --- /dev/null +++ b/dialogflow-cx/test/detect-intent-text.test.js @@ -0,0 +1,43 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +describe('detect intent with text input', () => { + const cmd = 'node detect-intent-text.js'; + + const projectId = process.env.GCLOUD_PROJECT; + const location = 'global'; + const agentId = 'b1808233-450b-4065-9492-bc9b40151641'; + const languageCode = 'en'; + + it('should respond to "hello"', async () => { + const output = exec( + `${cmd} ${projectId} ${location} ${agentId} 'hello' ${languageCode}` + ); + assert.include(output, 'How can I assist you today?'); + }); + + it('should respond to "reserve a van"', async () => { + const output = exec( + `${cmd} ${projectId} ${location} ${agentId} 'i need to reserve a van' ${languageCode}` + ); + assert.include(output, 'Where would you like '); + }); +}); diff --git a/dialogflow-cx/test/detect-intent-with-intent-input-test.js b/dialogflow-cx/test/detect-intent-with-intent-input-test.js new file mode 100644 index 0000000000..f2f0e926c9 --- /dev/null +++ b/dialogflow-cx/test/detect-intent-with-intent-input-test.js @@ -0,0 +1,38 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +describe('detect intent with IntentInput', () => { + const cmd = 'node detect-intent-with-intent-input.js'; + + const projectId = process.env.GCLOUD_PROJECT; + const location = 'global'; + const agentId = 'b1808233-450b-4065-9492-bc9b40151641'; + const languageCode = 'en'; + const intent = '00000000-0000-0000-0000-000000000000'; + + it('should return agent response Default Welcome Intent', async () => { + const output = exec( + `${cmd} ${projectId} ${location} ${agentId} ${intent} ${languageCode}` + ); + console.log(output); + assert.include(output, 'Default Welcome Intent'); + }); +}); diff --git a/dialogflow-cx/test/list-intents.test.js b/dialogflow-cx/test/list-intents.test.js new file mode 100644 index 0000000000..fd27513471 --- /dev/null +++ b/dialogflow-cx/test/list-intents.test.js @@ -0,0 +1,34 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +describe('list intents', () => { + const cmd = 'node list-intents.js'; + + const projectId = process.env.GCLOUD_PROJECT; + const location = 'global'; + const agentId = 'b1808233-450b-4065-9492-bc9b40151641'; + + it('should List the Intents', async () => { + const output = exec(`${cmd} ${projectId} ${location} ${agentId}`); + assert.include(output, 'Default Welcome Intent'); + assert.include(output, 'Default Negative Intent'); + }); +}); diff --git a/dialogflow-cx/test/list_testcase-results.test.js b/dialogflow-cx/test/list_testcase-results.test.js new file mode 100644 index 0000000000..72d7bf1a74 --- /dev/null +++ b/dialogflow-cx/test/list_testcase-results.test.js @@ -0,0 +1,36 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); +const dialogflow = require('@google-cloud/dialogflow-cx'); + +describe('Test filtering results', async () => { + const cmd = 'node list-testcase-results.js'; + const agentId = process.env.AGENT_ID; + const testId = process.env.TEST_ID; + const location = 'global'; + const agentClient = new dialogflow.AgentsClient(); + const projectId = + process.env.AGENT_PROJECT_ID || (await agentClient.getProjectId()); + + it('should return filtered test results', async () => { + const output = exec(`${cmd} ${projectId} ${agentId} ${testId} ${location}`); + assert.include(output, testId); + }); +}); diff --git a/dialogflow-cx/test/long-running-operation.test.js b/dialogflow-cx/test/long-running-operation.test.js new file mode 100644 index 0000000000..9c60c04faa --- /dev/null +++ b/dialogflow-cx/test/long-running-operation.test.js @@ -0,0 +1,62 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, before, it, after} = require('mocha'); +const execSync = require('child_process').execSync; +const uuid = require('uuid'); +const dialogflow = require('@google-cloud/dialogflow-cx'); +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); +const location = 'global'; +let agentId = ''; +let agentPath = ''; + +describe('update intent', async () => { + const agentClient = new dialogflow.AgentsClient(); + const projectId = await agentClient.getProjectId(); + const agentDisplayName = `temp_agent_${uuid.v4().split('-')[0]}`; + const parent = 'projects/' + projectId + '/locations/' + location; + const cmd = 'node long-running-operation.js'; + + before('create an agent and get agent id', async () => { + // The path to identify the agent that owns the intents. + + const agent = { + displayName: agentDisplayName, + defaultLanguageCode: 'en', + timeZone: 'America/Los_Angeles', + }; + + const request = { + agent, + parent, + }; + + const [agentResponse] = await agentClient.createAgent(request); + + agentPath = agentResponse.name; + agentId = agentPath.split('/')[5]; + }); + + after('delete Agent', async () => { + agentClient.deleteAgent({name: agentPath}); + }); + + it('should export agent', async () => { + const output = exec(`${cmd} ${projectId} ${agentId} ${location}`); + assert.include(output, 'agentContent'); + }); +}); diff --git a/dialogflow-cx/test/page-management.test.js b/dialogflow-cx/test/page-management.test.js new file mode 100644 index 0000000000..f3898c0298 --- /dev/null +++ b/dialogflow-cx/test/page-management.test.js @@ -0,0 +1,74 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the 'License'); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an 'AS IS' BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const uuid = require('uuid'); +const execSync = require('child_process').execSync; +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +describe('should test page management functions', async () => { + const location = 'global'; + const projectId = process.env.GCLOUD_PROJECT; + const flowId = '00000000-0000-0000-0000-000000000000'; + const pageName = `temp_page_${uuid.v4()}`; + const agentID = 'b1808233-450b-4065-9492-bc9b40151641'; + let pageID = ''; + + it('should create a page', async () => { + const cmd = 'node create-page.js'; + const temp = `${cmd} ${projectId} ${agentID} ${flowId} ${location} ${pageName}`; + const output = exec(temp); + assert.include(output, pageName); + }); + + it('should list pages', async () => { + const cmd = 'node list-page.js'; + const output = exec(`${cmd} ${projectId} ${agentID} ${flowId} global`); + assert.include(output, pageName); + }); + + it('should delete a page', async () => { + const {PagesClient, protos} = require('@google-cloud/dialogflow-cx'); + const pagesClient = new PagesClient(); + const listPageRequest = + new protos.google.cloud.dialogflow.cx.v3.ListPagesRequest(); + + listPageRequest.parent = + 'projects/' + + projectId + + '/locations/' + + location + + '/agents/' + + agentID + + '/flows/' + + flowId; + listPageRequest.languageCode = 'en'; + + const response = await pagesClient.listPages(listPageRequest); + + for (let i = 0; i < response[0].length; i++) { + if (response[0][i].displayName === pageName) { + pageID = response[0][i].name.split('/')[9]; + } + } + + const cmd = 'node delete-page.js'; + const temp = `${cmd} ${projectId} ${agentID} ${flowId} ${pageID} global`; + const output = exec(temp); + assert.strictEqual(output.includes('['), true); + }); +}); diff --git a/dialogflow-cx/test/quickstart.js b/dialogflow-cx/test/quickstart.js new file mode 100644 index 0000000000..eca2311972 --- /dev/null +++ b/dialogflow-cx/test/quickstart.js @@ -0,0 +1,44 @@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ** This file is automatically generated by gapic-generator-typescript. ** +// ** https://github.com/googleapis/gapic-generator-typescript ** +// ** All changes to this file may be overwritten. ** + +'use strict'; + +const path = require('path'); +const {assert} = require('chai'); +const cp = require('child_process'); +const {describe, it} = require('mocha'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cwd = path.join(__dirname, '..'); + +const project = process.env.GCLOUD_PROJECT; + +describe('Quickstart', () => { + it('should run quickstart', async () => { + try { + // TODO: write an actual functional test: + execSync( + `node ./quickstart.js ${project} global my-agent audio.raw AUDIO_ENCODING_LINEAR_16 16000 en`, + {cwd} + ); + assert('unreachable'); + } catch (err) { + assert.match(err.message, /no such file or directory, open 'audio.raw/); + } + }); +}); diff --git a/dialogflow-cx/test/streaming-detect-intent-partial-response-test.js b/dialogflow-cx/test/streaming-detect-intent-partial-response-test.js new file mode 100644 index 0000000000..e0c414c78e --- /dev/null +++ b/dialogflow-cx/test/streaming-detect-intent-partial-response-test.js @@ -0,0 +1,39 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +describe('streaming detect intent with partial response', () => { + const cmd = 'node streaming-detect-intent-partial-response.js'; + + const projectId = process.env.GCLOUD_PROJECT; + const location = 'global'; + const agentId = '7e4c5542-823b-4e28-bd02-d37016826e9e'; + const audioFileName = 'resources/book_a_room.wav'; + const encoding = 'AUDIO_ENCODING_LINEAR_16'; + const sampleRateHertz = 16000; + const languageCode = 'en'; + + it('should respond to with partial response', async () => { + const output = exec( + `${cmd} ${projectId} ${location} ${agentId} ${audioFileName} ${encoding} ${sampleRateHertz} ${languageCode}` + ); + assert.include(output, 'One moment while I try to help!'); + }); +}); diff --git a/dialogflow-cx/test/update-intent.test.js b/dialogflow-cx/test/update-intent.test.js new file mode 100644 index 0000000000..63e44cf664 --- /dev/null +++ b/dialogflow-cx/test/update-intent.test.js @@ -0,0 +1,76 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, before, it, after} = require('mocha'); +const execSync = require('child_process').execSync; +const uuid = require('uuid'); +const dialogflow = require('@google-cloud/dialogflow-cx'); +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); +const intentId = []; +const location = 'global'; +let agentId = ''; +let agentPath = ''; + +describe('update intent', async () => { + const intentClient = new dialogflow.IntentsClient(); + const agentClient = new dialogflow.AgentsClient(); + const projectId = await agentClient.getProjectId(); + const displayName = `fake_display_name_${uuid.v4().split('-')[0]}`; + const agentDisplayName = `temp_agent_${uuid.v4().split('-')[0]}`; + const parent = 'projects/' + projectId + '/locations/' + location; + const cmd = 'node update-intent.js'; + + before('get intent ID and agent ID', async () => { + // The path to identify the agent that owns the intents. + + const agent = { + displayName: agentDisplayName, + defaultLanguageCode: 'en', + timeZone: 'America/Los_Angeles', + }; + + const request = { + agent, + parent, + }; + + const [agentResponse] = await agentClient.createAgent(request); + + agentPath = agentResponse.name; + agentId = agentPath.split('/')[5]; + + const intentRequest = { + parent: agentPath, + }; + + const [response] = await intentClient.listIntents(intentRequest); + response.forEach(intent => { + intentId.push(intent.name.split('/')[7]); + }); + }); + + after('delete Agent', async () => { + agentClient.deleteAgent({name: agentPath}); + }); + + it('should update an intent using fieldmasks', async () => { + const output = exec( + `${cmd} ${projectId} ${agentId} ${intentId[0]} ${location} ${displayName}` + ); + assert.include(output, displayName); + }); +}); diff --git a/dialogflow-cx/test/webhook-configure-session-parameters-test.js b/dialogflow-cx/test/webhook-configure-session-parameters-test.js new file mode 100644 index 0000000000..a03209a5e7 --- /dev/null +++ b/dialogflow-cx/test/webhook-configure-session-parameters-test.js @@ -0,0 +1,58 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const webhook = require('../webhook-configure-session-parameters'); + +describe('configure session parameters', () => { + it('should test that webhook adds new session parameter', async () => { + const request = { + body: { + fulfillmentInfo: { + tag: 'configure-session-parameter', + }, + }, + }; + const temp = JSON.stringify(request); + let response = ''; + + const res = { + send: function (s) { + response = JSON.stringify(s); + }, + }; + + webhook.configureSessionParams(JSON.parse(temp), res); + assert.include(response, 'orderNumber'); + }); +}); diff --git a/dialogflow-cx/test/webhook-validate-form-parameter-test.js b/dialogflow-cx/test/webhook-validate-form-parameter-test.js new file mode 100644 index 0000000000..0a4d0f3ce9 --- /dev/null +++ b/dialogflow-cx/test/webhook-validate-form-parameter-test.js @@ -0,0 +1,58 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const webhook = require('../webhook-validate-form-parameter'); + +describe('configure session parameters', () => { + it('should test that webhook invalidates form parameter', async () => { + const request = { + body: { + fulfillmentInfo: { + tag: 'invalidate-form-parameter', + }, + }, + }; + const temp = JSON.stringify(request); + let response = ''; + + const res = { + send: function (s) { + response = JSON.stringify(s); + }, + }; + + webhook.validateParameter(JSON.parse(temp), res); + assert.include(response, 'INVALID'); + }); +}); diff --git a/dialogflow-cx/test/webhook.test.js b/dialogflow-cx/test/webhook.test.js new file mode 100644 index 0000000000..cf3e338f40 --- /dev/null +++ b/dialogflow-cx/test/webhook.test.js @@ -0,0 +1,45 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const webhook = require('../webhooks'); + +const request = { + body: { + fulfillmentInfo: { + tag: 'Default Welcome Intent', + }, + text: 'hi', + languageCode: 'en', + }, +}; + +describe('create agent', () => { + it('should test webhook returns correct response', async () => { + const temp = JSON.stringify(request); + let response = ''; + + const res = { + send: function (s) { + response = JSON.stringify(s); + }, + }; + + webhook.handleWebhook(JSON.parse(temp), res); + assert.include(response, 'Hello from a GCF Webhook'); + }); +}); diff --git a/dialogflow-cx/update-intent.js b/dialogflow-cx/update-intent.js new file mode 100644 index 0000000000..129e4ff4f6 --- /dev/null +++ b/dialogflow-cx/update-intent.js @@ -0,0 +1,65 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main(projectId, agentId, intentId, location, displayName) { + // [START dialogflow_cx_update_intent] + + const {IntentsClient} = require('@google-cloud/dialogflow-cx'); + + const intentClient = new IntentsClient(); + + //TODO(developer): Uncomment these variables before running the sample. + // const projectId = 'your-project-id'; + // const agentId = 'your-agent-id'; + // const intentId = 'your-intent-id'; + // const location = 'your-location'; + // const displayName = 'your-display-name'; + + async function updateIntent() { + const agentPath = intentClient.projectPath(projectId); + const intentPath = `${agentPath}/locations/${location}/agents/${agentId}/intents/${intentId}`; + + //Gets the intent from intentPath + const intent = await intentClient.getIntent({name: intentPath}); + intent[0].displayName = displayName; + + //Specifies what is being updated + const updateMask = { + paths: ['display_name'], + }; + + const updateIntentRequest = { + intent: intent[0], + updateMask, + languageCode: 'en', + }; + + //Send the request for update the intent. + const result = await intentClient.updateIntent(updateIntentRequest); + console.log(result); + } + + updateIntent(); + + // [END dialogflow_cx_update_intent] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/dialogflow-cx/webhook-configure-session-parameters.js b/dialogflow-cx/webhook-configure-session-parameters.js new file mode 100644 index 0000000000..b4b1199be9 --- /dev/null +++ b/dialogflow-cx/webhook-configure-session-parameters.js @@ -0,0 +1,35 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Configures a webhook to set a session parameter + */ + +// [START dialogflow_cx_v3_webhook_configure_session_parameters] + +exports.configureSessionParams = (request, response) => { + // Session parameter configured by the webhook + const orderNumber = 123; + + const jsonResponse = { + sessionInfo: { + parameters: { + orderNumber: orderNumber, + }, + }, + }; + + response.send(jsonResponse); +}; +// [END dialogflow_cx_v3_webhook_configure_session_parameters] diff --git a/dialogflow-cx/webhook-validate-form-parameter.js b/dialogflow-cx/webhook-validate-form-parameter.js new file mode 100644 index 0000000000..0cde7dce74 --- /dev/null +++ b/dialogflow-cx/webhook-validate-form-parameter.js @@ -0,0 +1,48 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Uses a webhook to validate or invalidate form parameters. + */ + +// [START dialogflow_cx_v3_webhook_validate_form_parameter] + +exports.validateParameter = (request, response) => { + // Webhook will validate or invalidate parameter based on logic configured by the user. + // Access parameter values through the webhook request via `request.body.pageInfo.formInfo.parameterInfo[]` + + const jsonResponse = { + page_info: { + form_info: { + parameter_info: [ + { + displayName: 'orderNumber', + required: true, + state: 'INVALID', + value: 123, + }, + ], + }, + }, + sessionInfo: { + parameters: { + // Set session parameter to null if the form parameter is 'INVALID' and your agent needs to reprompt the user + orderNumber: null, + }, + }, + }; + + response.send(jsonResponse); +}; +// [END dialogflow_cx_v3_webhook_validate_form_parameter] diff --git a/dialogflow-cx/webhooks.js b/dialogflow-cx/webhooks.js new file mode 100644 index 0000000000..9d687394bd --- /dev/null +++ b/dialogflow-cx/webhooks.js @@ -0,0 +1,46 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +// [START dialogflow_cx_webhook] + +exports.handleWebhook = (request, response) => { + const tag = request.body.fulfillmentInfo.tag; + let text = ''; + + if (tag === 'Default Welcome Intent') { + text = 'Hello from a GCF Webhook'; + } else if (tag === 'get-name') { + text = 'My name is Flowhook'; + } else { + text = `There are no fulfillment responses defined for "${tag}"" tag`; + } + + const jsonResponse = { + fulfillment_response: { + messages: [ + { + text: { + //fulfillment text response to be sent to the agent + text: [text], + }, + }, + ], + }, + }; + + response.send(jsonResponse); +}; +// [END dialogflow_cx_webhook]