diff --git a/dialogflow/Dialogflow/.gitignore b/dialogflow/Dialogflow/.gitignore new file mode 100644 index 00000000..fe900bc7 --- /dev/null +++ b/dialogflow/Dialogflow/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +/.idea +.DS_Store +/build +/captures +.externalNativeBuild + +app/src/main/res/raw/*.json diff --git a/dialogflow/Dialogflow/README.md b/dialogflow/Dialogflow/README.md new file mode 100644 index 00000000..28e8f958 --- /dev/null +++ b/dialogflow/Dialogflow/README.md @@ -0,0 +1,44 @@ +# Google Cloud Dialogflow Enterprise examples + +This directory contains Android example that uses the +[Google Cloud Dialogflow Enterprise](https://cloud.google.com/dialogflow-enterprise/). + +## Prerequisites + +### Enable Cloud Dialogflow Enterprise + +If you have not already done so, [enable Cloud Dialogflow Enterprise for your project]( +https://cloud.google.com/dialogflow-enterprise/). + +### Set Up to Authenticate With Your Project's Credentials + +This Android app uses JSON credential file locally stored in the resources. ***You should not do +this in your production app.*** Instead, you should set up your own backend server that +authenticates app users. The server should delegate API calls from your client app. This way, you +can enforce usage quota per user. Alternatively, you should get the access token on the server side, +and supply client app with it. The access token will expire in a short while. + +In this sample, we just put the Service Account in the client for ease of use. The app still gets +an access token using the service account credential, and use the token to call the API, so you can +see how to do so. + +In order to try out this sample, visit the [Cloud Console](https://console.cloud.google.com/), and +navigate to: +`API Manager > Credentials > Create credentials > Service account key > New service account`. +Create a new service account, and download the JSON credentials file. Put the file in the app +resources as `app/src/main/res/raw/credential.json`. + +Again, ***you should not do this in your production app.*** + +See the [Cloud Platform Auth Guide](https://cloud.google.com/docs/authentication#developer_workflow) +for more information. + +### Project name and agent name for Dialogflow + +Open the file `gradle.properties` and change the Dialogflow project name and agent name there. + +``` +dialogflowProjectName=(your project name here) +dialogflowAgentName(your agent name here) +dialogflowLanguageCode=(language code, such as en-US) +``` diff --git a/dialogflow/Dialogflow/app/.gitignore b/dialogflow/Dialogflow/app/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/dialogflow/Dialogflow/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/dialogflow/Dialogflow/app/build.gradle b/dialogflow/Dialogflow/app/build.gradle new file mode 100644 index 00000000..86de66f0 --- /dev/null +++ b/dialogflow/Dialogflow/app/build.gradle @@ -0,0 +1,118 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +apply plugin: 'com.android.application' +apply plugin: 'com.google.protobuf' + +ext { + supportLibraryVersion = '27.1.1' + grpcVersion = '1.14.0' +} + +android { + compileSdkVersion 27 + defaultConfig { + applicationId 'com.google.cloud.android.dialogflow' + minSdkVersion 16 + targetSdkVersion 27 + versionCode 1 + versionName '1.0' + testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner' + vectorDrawables.useSupportLibrary = true + + // Dialogflow project & agent settings + buildConfigField 'String', 'PROJECT_NAME', "\"${project.property("dialogflowProjectName")}\"" + buildConfigField 'String', 'LANGUAGE_CODE', "\"${project.property("dialogflowLanguageCode")}\"" + } + buildTypes { + debug { + minifyEnabled false + multiDexEnabled true + } + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + configurations.all { + resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.2' + resolutionStrategy.force "com.android.support:support-annotations:$supportLibraryVersion" + } + lintOptions { + lintConfig file('lint.xml') + } +} + +protobuf { + protoc { + artifact = 'com.google.protobuf:protoc:3.3.0' + } + plugins { + javalite { + artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0' + } + grpc { + artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" + } + } + generateProtoTasks { + all().each { task -> + task.plugins { + javalite {} + grpc { + // Options added to --grpc_out + option 'lite' + } + } + } + } +} + +dependencies { + // Support Libraries + implementation "com.android.support:appcompat-v7:$supportLibraryVersion" + implementation "com.android.support:recyclerview-v7:$supportLibraryVersion" + + // gRPC + implementation "io.grpc:grpc-okhttp:$grpcVersion" + implementation "io.grpc:grpc-protobuf-lite:$grpcVersion" + implementation "io.grpc:grpc-stub:$grpcVersion" + implementation 'javax.annotation:javax.annotation-api:1.3' + protobuf 'com.google.protobuf:protobuf-java:3.4.0' + protobuf 'com.google.api.grpc:googleapis-common-protos:0.0.3' + + // OAuth2 for Google API + implementation('com.google.auth:google-auth-library-oauth2-http:0.9.0') { + exclude module: 'httpclient' + } + + // Test + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:2.19.0' + androidTestImplementation 'org.mockito:mockito-android:2.19.0' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test:rules:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} + +task copySecretKey(type: Copy) { + File secretKey = file "$System.env.GOOGLE_APPLICATION_CREDENTIALS" + from secretKey.getParent() + include secretKey.getName() + into 'src/main/res/raw' + rename secretKey.getName(), "credential.json" +} +preBuild.dependsOn(copySecretKey) diff --git a/dialogflow/Dialogflow/app/lint.xml b/dialogflow/Dialogflow/app/lint.xml new file mode 100644 index 00000000..7022a9f8 --- /dev/null +++ b/dialogflow/Dialogflow/app/lint.xml @@ -0,0 +1,24 @@ + + + + + + + + + + diff --git a/dialogflow/Dialogflow/app/proguard-rules.pro b/dialogflow/Dialogflow/app/proguard-rules.pro new file mode 100644 index 00000000..c8bcd1eb --- /dev/null +++ b/dialogflow/Dialogflow/app/proguard-rules.pro @@ -0,0 +1,23 @@ +# Copyright 2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# 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. + +# Suppress warnings from gRPC dependencies +-dontwarn com.google.common.** +-dontwarn com.google.api.client.** +-dontwarn com.google.protobuf.** +-dontwarn io.grpc.** +-dontwarn okio.** +-dontwarn com.google.errorprone.annotations.** +-keep class io.grpc.internal.DnsNameResolveProvider +-keep class io.grpc.okhttp.OkHttpChannelProvider diff --git a/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/MainActivityTest.java b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/MainActivityTest.java new file mode 100644 index 00000000..04da8957 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/MainActivityTest.java @@ -0,0 +1,107 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.replaceText; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +import static com.google.cloud.android.dialogflow.TestUtils.hasDirection; + +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; + +import android.Manifest; +import android.support.test.filters.LargeTest; +import android.support.test.filters.MediumTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.rule.GrantPermissionRule; +import android.support.test.runner.AndroidJUnit4; + +import com.google.cloud.android.dialogflow.api.DialogflowService; +import com.google.cloud.android.dialogflow.api.Utterance; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + + +@RunWith(AndroidJUnit4.class) +public class MainActivityTest { + + @Rule + public ActivityTestRule activityRule = + new ActivityTestRule<>(MainActivity.class); + + @Rule + public GrantPermissionRule permissionRule = + GrantPermissionRule.grant(Manifest.permission.RECORD_AUDIO); + + private DialogflowService.Listener mListener; + + @Before + public void setUp() { + final DialogflowService service = activityRule.getActivity().mDialogflowService; + mListener = mock(DialogflowService.Listener.class); + service.addListener(mListener); + } + + @After + public void tearDown() { + activityRule.getActivity().mDialogflowService.removeListener(mListener); + } + + @Test + @MediumTest + public void initialState() { + onView(withId(R.id.text)).check(matches(isDisplayed())); + onView(withId(R.id.toggle)).check(matches(isDisplayed())); + onView(withId(R.id.history)).check(matches(isDisplayed())); + } + + @Test + @LargeTest + public void detectIntentByText() { + verify(mListener, timeout(TestUtils.API_TIMEOUT_MILLIS)).onApiReady(); + onView(withId(R.id.text)).perform(replaceText("MainActivityTest")); + onView(withId(R.id.toggle)).perform(click()); + verify(mListener) + .onNewUtterance(eq(new Utterance(Utterance.OUTGOING, "MainActivityTest"))); + onView(withId(R.id.history)).check(matches(hasDescendant(withText("MainActivityTest")))); + verify(mListener, timeout(TestUtils.API_TIMEOUT_MILLIS)) + .onNewUtterance(argThat(hasDirection(Utterance.INCOMING))); + } + + @Test + @LargeTest + public void switchToVoice() { + verify(mListener, timeout(TestUtils.API_TIMEOUT_MILLIS)).onApiReady(); + onView(withId(R.id.toggle)).perform(click()); + onView(withId(R.id.indicator)).check(matches(isDisplayed())); + } + +} diff --git a/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/TestUtils.java b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/TestUtils.java new file mode 100644 index 00000000..044df649 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/TestUtils.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow; + +import com.google.cloud.android.dialogflow.api.Utterance; + +import org.mockito.ArgumentMatcher; + + +public class TestUtils { + + /** Timeout limit for API calls. */ + public static final int API_TIMEOUT_MILLIS = 10000; + + private TestUtils() { + } + + /** + * Matches an {@link Utterance} with the specified {@code direction}. + * + * @param direction The direction. Either {@link Utterance#INCOMING} or {@link + * Utterance#OUTGOING}. + * @return The matcher. + */ + public static ArgumentMatcher hasDirection(final int direction) { + return new ArgumentMatcher() { + @Override + public boolean matches(Utterance utterance) { + return utterance.direction == direction; + } + }; + } + +} diff --git a/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/api/DialogflowServiceTest.java b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/api/DialogflowServiceTest.java new file mode 100644 index 00000000..dbb5b931 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/api/DialogflowServiceTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.api; + +import static com.google.cloud.android.dialogflow.TestUtils.hasDirection; + +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; + +import android.content.Intent; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.support.test.rule.ServiceTestRule; +import android.support.test.runner.AndroidJUnit4; + +import com.google.cloud.android.dialogflow.TestUtils; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.concurrent.TimeoutException; + + +@RunWith(AndroidJUnit4.class) +public class DialogflowServiceTest { + + @Rule + public final ServiceTestRule serviceRule = new ServiceTestRule(); + + private DialogflowService mService; + private DialogflowService.Listener mListener; + + @Before + public void setUp() throws TimeoutException { + mService = DialogflowService.from(serviceRule.bindService( + new Intent(InstrumentationRegistry.getTargetContext(), DialogflowService.class))); + mListener = mock(DialogflowService.Listener.class); + mService.addListener(mListener); + } + + @After + public void tearDown() { + mService.removeListener(mListener); + serviceRule.unbindService(); + } + + @Test + @LargeTest + public void detectIntentByText() { + if (!mService.isApiReady()) { + verify(mListener, timeout(TestUtils.API_TIMEOUT_MILLIS)).onApiReady(); + } + mService.detectIntentByText("detectIntentByText"); + verify(mListener) + .onNewUtterance(eq(new Utterance(Utterance.OUTGOING, "detectIntentByText"))); + verify(mListener, timeout(TestUtils.API_TIMEOUT_MILLIS)) + .onNewUtterance(argThat(hasDirection(Utterance.INCOMING))); + } + + +} diff --git a/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/api/UtteranceTest.java b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/api/UtteranceTest.java new file mode 100644 index 00000000..79a9ba29 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/api/UtteranceTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.api; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +import android.os.Parcel; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + + +@RunWith(AndroidJUnit4.class) +public class UtteranceTest { + + @Test + @SmallTest + public void instantiate() { + final Utterance utterance = new Utterance(Utterance.INCOMING, "Hello"); + assertThat(utterance.direction, is(Utterance.INCOMING)); + assertThat(utterance.text, is("Hello")); + } + + @Test + @SmallTest + public void parcel() { + final Utterance original = new Utterance(Utterance.INCOMING, "Hello"); + final Parcel parcel = Parcel.obtain(); + try { + parcel.writeParcelable(original, 0); + parcel.setDataPosition(0); + final Utterance restored = parcel.readParcelable(getClass().getClassLoader()); + assertThat(restored.direction, is(Utterance.INCOMING)); + assertThat(restored.text, is("Hello")); + } finally { + parcel.recycle(); + } + } + +} diff --git a/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/AudioIndicatorViewTest.java b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/AudioIndicatorViewTest.java new file mode 100644 index 00000000..abaf4aab --- /dev/null +++ b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/AudioIndicatorViewTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.ui; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +import android.support.test.InstrumentationRegistry; +import android.support.test.espresso.UiController; +import android.support.test.espresso.ViewAction; +import android.support.test.filters.MediumTest; +import android.support.test.runner.AndroidJUnit4; +import android.view.View; + +import com.google.cloud.android.dialogflow.R; + +import org.hamcrest.Matcher; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + + +@RunWith(AndroidJUnit4.class) +public class AudioIndicatorViewTest extends UiTest { + + private AudioIndicatorView mAudioIndicatorView; + + @Before + public void setUp() throws Throwable { + mAudioIndicatorView = activityRule.getActivity().findViewById(R.id.indicator); + activityRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mAudioIndicatorView.setVisibility(View.VISIBLE); + } + }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + } + + @Test + @MediumTest + public void hearingVoice() { + assertThat(mAudioIndicatorView.isHearingVoice(), is(false)); + onView(withId(R.id.indicator)).perform(setHearingVoice(true)); + assertThat(mAudioIndicatorView.isHearingVoice(), is(true)); + onView(withId(R.id.indicator)).perform(setHearingVoice(false)); + assertThat(mAudioIndicatorView.isHearingVoice(), is(false)); + } + + private ViewAction setHearingVoice(final boolean hearingVoice) { + return new ViewAction() { + @Override + public Matcher getConstraints() { + return isAssignableFrom(AudioIndicatorView.class); + } + + @Override + public String getDescription() { + return "setHearingVoice"; + } + + @Override + public void perform(UiController uiController, View view) { + final AudioIndicatorView indicator = (AudioIndicatorView) view; + indicator.setHearingVoice(hearingVoice); + } + }; + } + +} diff --git a/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/BubbleViewTest.java b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/BubbleViewTest.java new file mode 100644 index 00000000..ff199e2f --- /dev/null +++ b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/BubbleViewTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.ui; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.MediumTest; +import android.support.test.runner.AndroidJUnit4; + +import com.google.cloud.android.dialogflow.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + + +@RunWith(AndroidJUnit4.class) +public class BubbleViewTest extends UiTest { + + private BubbleView mBubbleView; + + @Before + public void setUp() { + mBubbleView = activityRule.getActivity().findViewById(R.id.bubble); + } + + @Test + @MediumTest + public void direction() throws Throwable { + assertThat(mBubbleView.getDirection(), is(BubbleView.DIRECTION_INCOMING)); + activityRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mBubbleView.setDirection(BubbleView.DIRECTION_OUTGOING); + } + }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + assertThat(mBubbleView.getDirection(), is(BubbleView.DIRECTION_OUTGOING)); + } + +} diff --git a/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/InputHelperTest.java b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/InputHelperTest.java new file mode 100644 index 00000000..d29933ed --- /dev/null +++ b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/InputHelperTest.java @@ -0,0 +1,126 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.ui; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.replaceText; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.MediumTest; +import android.support.test.runner.AndroidJUnit4; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageButton; + +import com.google.cloud.android.dialogflow.R; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + + +@RunWith(AndroidJUnit4.class) +public class InputHelperTest extends UiTest { + + private EditText mEditText; + private ImageButton mToggle; + private AudioIndicatorView mAudioIndicatorView; + + private InputHelper.Callback mCallback; + private InputHelper mInputHelper; + + @Before + public void setUp() throws Throwable { + final UiTestActivity activity = activityRule.getActivity(); + mEditText = activity.findViewById(R.id.input); + mToggle = activity.findViewById(R.id.toggle); + mAudioIndicatorView = activity.findViewById(R.id.indicator); + mCallback = mock(InputHelper.Callback.class); + activityRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mInputHelper = new InputHelper(mEditText, mToggle, mAudioIndicatorView, mCallback); + mInputHelper.setEnabled(true); + } + }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + } + + @After + public void tearDown() { + mInputHelper.release(); + } + + @Test + @MediumTest + public void initialState() { + assertNotNull(mInputHelper); + assertThat(mToggle.getContentDescription().toString(), is("Voice")); + assertThat(mEditText.isEnabled(), is(true)); + assertThat(mToggle.isEnabled(), is(true)); + assertThat(mToggle.getVisibility(), is(View.VISIBLE)); + assertThat(mAudioIndicatorView.getVisibility(), is(View.GONE)); + } + + @Test + @MediumTest + public void setEnabled() throws Throwable { + activityRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mInputHelper.setEnabled(false); + } + }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + assertThat(mEditText.isEnabled(), is(false)); + assertThat(mToggle.isEnabled(), is(false)); + } + + @Test + @MediumTest + public void type() { + onView(withId(R.id.input)).perform(replaceText("Hello")); + assertThat(mToggle.getContentDescription().toString(), is("Send")); + onView(withId(R.id.toggle)).perform(click()); + verify(mCallback).onText(eq("Hello")); + assertThat(mEditText.getText().toString(), is("")); + assertThat(mToggle.getContentDescription().toString(), is("Voice")); + } + + @Test + @MediumTest + public void audio() { + when(mCallback.ensureRecordAudioPermission()).thenReturn(true); + onView(withId(R.id.toggle)).perform(click()); + assertThat(mToggle.getContentDescription().toString(), is("Keyboard")); + assertThat(mAudioIndicatorView.getVisibility(), is(View.VISIBLE)); + onView(withId(R.id.toggle)).perform(click()); + assertThat(mToggle.getContentDescription().toString(), is("Voice")); + } + +} diff --git a/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/MessageDialogFragmentTest.java b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/MessageDialogFragmentTest.java new file mode 100644 index 00000000..debc0c55 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/MessageDialogFragmentTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.ui; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.support.test.filters.MediumTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + + +@RunWith(AndroidJUnit4.class) +public class MessageDialogFragmentTest extends UiTest { + + private MessageDialogFragment.Listener mListener; + private MessageDialogFragment mMessageDialogFragment; + + @Before + public void setUp() { + mListener = mock(MessageDialogFragment.Listener.class); + activityRule.getActivity().setMessageDialogFragmentListener(mListener); + mMessageDialogFragment = MessageDialogFragment.newInstance("MessageDialogFragmentTest"); + } + + @Test + @MediumTest + public void showAndDismiss() { + mMessageDialogFragment.show(activityRule.getActivity().getSupportFragmentManager(), "a"); + onView(withText("MessageDialogFragmentTest")).check(matches(isDisplayed())); + onView(withText(android.R.string.ok)).perform(click()); + verify(mListener).onMessageDialogDismissed(); + } + +} diff --git a/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/UiTest.java b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/UiTest.java new file mode 100644 index 00000000..af3e67a9 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/androidTest/java/com/google/cloud/android/dialogflow/ui/UiTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.ui; + +import android.Manifest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.rule.GrantPermissionRule; + +import org.junit.Rule; + + +/** + * Base class for UI tests with {@link UiTestActivity}. + */ +abstract class UiTest { + + @Rule + public ActivityTestRule activityRule = + new ActivityTestRule<>(UiTestActivity.class); + + @Rule + public GrantPermissionRule permissionRule = + GrantPermissionRule.grant(Manifest.permission.RECORD_AUDIO); + +} diff --git a/dialogflow/Dialogflow/app/src/debug/AndroidManifest.xml b/dialogflow/Dialogflow/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..4b85bf00 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/debug/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + diff --git a/dialogflow/Dialogflow/app/src/debug/java/com/google/cloud/android/dialogflow/ui/UiTestActivity.java b/dialogflow/Dialogflow/app/src/debug/java/com/google/cloud/android/dialogflow/ui/UiTestActivity.java new file mode 100644 index 00000000..3f9b9cd8 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/debug/java/com/google/cloud/android/dialogflow/ui/UiTestActivity.java @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.ui; + +import android.Manifest; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.ActivityCompat; +import android.support.v7.app.AppCompatActivity; + +import com.google.cloud.android.dialogflow.R; + + +/** + * This is only for testing purpose. This activity has all UI components used in this app, and + * the testing code can use this to test UI components without actually calling APIs. + */ +public class UiTestActivity extends AppCompatActivity implements MessageDialogFragment.Listener { + + private static final int REQUEST_RECORD_AUDIO_PERMISSION = 1; + + private MessageDialogFragment.Listener mListener; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_ui_test); + requestAudioPermission(); + } + + public void setMessageDialogFragmentListener(MessageDialogFragment.Listener listener) { + mListener = listener; + } + + private void requestAudioPermission() { + // The test code deals with the dialog. The permission is always granted. + if (ActivityCompat.checkSelfPermission(UiTestActivity.this, + Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(UiTestActivity.this, + new String[]{Manifest.permission.RECORD_AUDIO}, + REQUEST_RECORD_AUDIO_PERMISSION); + } + } + + @Override + public void onMessageDialogDismissed() { + if (mListener != null) { + mListener.onMessageDialogDismissed(); + } + } + +} diff --git a/dialogflow/Dialogflow/app/src/debug/res/layout/activity_ui_test.xml b/dialogflow/Dialogflow/app/src/debug/res/layout/activity_ui_test.xml new file mode 100644 index 00000000..029709a2 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/debug/res/layout/activity_ui_test.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + diff --git a/dialogflow/Dialogflow/app/src/main/AndroidManifest.xml b/dialogflow/Dialogflow/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..01bbd8dd --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/AndroidManifest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + diff --git a/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/MainActivity.java b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/MainActivity.java new file mode 100644 index 00000000..56a189d3 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/MainActivity.java @@ -0,0 +1,222 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow; + +import android.Manifest; +import android.content.ComponentName; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.IBinder; +import android.support.annotation.NonNull; +import android.support.annotation.VisibleForTesting; +import android.support.v4.app.ActivityCompat; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.widget.EditText; +import android.widget.ImageButton; + +import com.google.cloud.android.dialogflow.api.DialogflowService; +import com.google.cloud.android.dialogflow.api.Utterance; +import com.google.cloud.android.dialogflow.ui.AudioIndicatorView; +import com.google.cloud.android.dialogflow.ui.HistoryAdapter; +import com.google.cloud.android.dialogflow.ui.InputHelper; +import com.google.cloud.android.dialogflow.ui.MessageDialogFragment; + + +public class MainActivity extends AppCompatActivity { + + private static final String FRAGMENT_MESSAGE_DIALOG = "message_dialog"; + private static final int REQUEST_RECORD_AUDIO_PERMISSION = 1; + + private static final String STATE_HISTORY = "history"; + + @VisibleForTesting + DialogflowService mDialogflowService; + + private LinearLayoutManager mLayoutManager; + private HistoryAdapter mAdapter; + + private InputHelper mInputHelper; + + private final ServiceConnection mServiceConnection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName componentName, IBinder binder) { + mDialogflowService = DialogflowService.from(binder); + mDialogflowService.addListener(mSpeechServiceListener); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + mDialogflowService = null; + } + + }; + + private DialogflowService.Listener mSpeechServiceListener + = new DialogflowService.Listener() { + + @Override + public void onApiReady() { + mInputHelper.setEnabled(true); + } + + @Override + public void onNewUtterance(Utterance utterance) { + if (mInputHelper != null && utterance.direction == Utterance.OUTGOING) { + mInputHelper.showTranscript(null); + } + mAdapter.addUtterance(utterance); + mLayoutManager.scrollToPosition(mAdapter.getItemCount() - 1); + } + + @Override + public void onNewRecognition(String text) { + if (mInputHelper != null) { + mInputHelper.showTranscript(text); + } + } + + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + // The main conversation view + final RecyclerView history = findViewById(R.id.history); + history.setItemAnimator(new DefaultItemAnimator()); + mLayoutManager = new LinearLayoutManager(this); + mLayoutManager.setStackFromEnd(true); + history.setLayoutManager(mLayoutManager); + mAdapter = new HistoryAdapter(); + if (savedInstanceState != null) { + mAdapter.restoreHistory( + savedInstanceState.getParcelableArrayList(STATE_HISTORY)); + } + history.setAdapter(mAdapter); + // User input + mInputHelper = new InputHelper((EditText) findViewById(R.id.text), + (ImageButton) findViewById(R.id.toggle), + (AudioIndicatorView) findViewById(R.id.indicator), new InputHelper.Callback() { + @Override + public void onText(String text) { + if (mDialogflowService != null) { + mDialogflowService.detectIntentByText(text); + } + } + + @Override + public void onVoiceStart() { + if (mDialogflowService != null) { + mDialogflowService.startDetectIntentByVoice(mInputHelper.getSampleRate()); + } + } + + @Override + public void onVoice(byte[] data, int size) { + if (mDialogflowService != null) { + mDialogflowService.detectIntentByVoice(data, size); + } + } + + @Override + public void onVoiceEnd() { + if (mDialogflowService != null) { + mDialogflowService.finishDetectIntentByVoice(); + } + } + + @Override + public boolean ensureRecordAudioPermission() { + if (ActivityCompat.checkSelfPermission(MainActivity.this, + Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) { + return true; + } else if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, + Manifest.permission.RECORD_AUDIO)) { + showPermissionMessageDialog(); + } else { + ActivityCompat.requestPermissions(MainActivity.this, + new String[]{Manifest.permission.RECORD_AUDIO}, + REQUEST_RECORD_AUDIO_PERMISSION); + } + return false; + } + }); + } + + @Override + protected void onDestroy() { + mInputHelper.release(); + super.onDestroy(); + } + + @Override + protected void onStart() { + super.onStart(); + + // Prepare Cloud Conversation Engine + bindService(new Intent(this, DialogflowService.class), mServiceConnection, + BIND_AUTO_CREATE); + } + + @Override + protected void onStop() { + // Stop Cloud Conversation Engine + if (mDialogflowService != null) { + mDialogflowService.removeListener(mSpeechServiceListener); + unbindService(mServiceConnection); + mDialogflowService = null; + } + + super.onStop(); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + if (mAdapter != null) { + outState.putParcelableArrayList(STATE_HISTORY, mAdapter.getHistory()); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) { + if (permissions.length == 1 && grantResults.length == 1 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + mInputHelper.resumeAudio(); + } else { + mInputHelper.fallbackToText(); + } + } else { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + } + + private void showPermissionMessageDialog() { + MessageDialogFragment + .newInstance(getString(R.string.permission_message)) + .show(getSupportFragmentManager(), FRAGMENT_MESSAGE_DIALOG); + } + +} diff --git a/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/api/DialogflowService.java b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/api/DialogflowService.java new file mode 100644 index 00000000..f8107ca5 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/api/DialogflowService.java @@ -0,0 +1,556 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.api; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.AsyncTask; +import android.os.Binder; +import android.os.Handler; +import android.os.IBinder; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.Log; + +import com.google.auth.Credentials; +import com.google.auth.oauth2.AccessToken; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.android.dialogflow.BuildConfig; +import com.google.cloud.android.dialogflow.R; +import com.google.cloud.dialogflow.v2.AudioEncoding; +import com.google.cloud.dialogflow.v2.DetectIntentRequest; +import com.google.cloud.dialogflow.v2.DetectIntentResponse; +import com.google.cloud.dialogflow.v2.InputAudioConfig; +import com.google.cloud.dialogflow.v2.QueryInput; +import com.google.cloud.dialogflow.v2.QueryResult; +import com.google.cloud.dialogflow.v2.SessionsGrpc; +import com.google.cloud.dialogflow.v2.StreamingDetectIntentRequest; +import com.google.cloud.dialogflow.v2.StreamingDetectIntentResponse; +import com.google.cloud.dialogflow.v2.StreamingRecognitionResult; +import com.google.cloud.dialogflow.v2.TextInput; +import com.google.protobuf.ByteString; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.WeakReference; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ClientInterceptors; +import io.grpc.ManagedChannel; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import io.grpc.Status; +import io.grpc.StatusException; +import io.grpc.StatusRuntimeException; +import io.grpc.internal.DnsNameResolverProvider; +import io.grpc.okhttp.OkHttpChannelProvider; +import io.grpc.stub.StreamObserver; + + +/** + * This service interacts with Cloud Dialogflow Enterprise. + */ +public class DialogflowService extends Service { + + /** + * Callback listener for {@link DialogflowService}. + */ + public interface Listener { + + /** + * Called when the API is ready. + */ + void onApiReady(); + + /** + * Called when a new {@link Utterance} occurred from either side of the conversation. + * + * @param utterance A new {@link Utterance}. + */ + void onNewUtterance(Utterance utterance); + + /** + * Called when a new piece of text is recognized in the speech recognition. + * + * @param text A new recognition result. + */ + void onNewRecognition(String text); + + } + + private static final String TAG = "DialogflowService"; + + private static final String PREFS = "DialogflowService"; + + private static final String PREF_ACCESS_TOKEN_VALUE = "access_token_value"; + private static final String PREF_ACCESS_TOKEN_EXPIRATION_TIME = "access_token_expiration_time"; + + /** We reuse an access token if its expiration time is longer than this. */ + private static final int ACCESS_TOKEN_EXPIRATION_TOLERANCE = 30 * 60 * 1000; // thirty minutes + /** We refresh the current access token before it expires. */ + private static final int ACCESS_TOKEN_FETCH_MARGIN = 60 * 1000; // one minute + + private static final List SCOPE = + Collections.singletonList("https://www.googleapis.com/auth/cloud-platform"); + private static final String HOSTNAME = "dialogflow.googleapis.com"; + private static final int PORT = 443; + + /** + * The unique name for this session; this should be changed depending on the user for example. + */ + private static final String SESSION_NAME = "sample-session"; + + private final DialogflowBinder mBinder = new DialogflowBinder(); + + private SessionsGrpc.SessionsStub mApi; + + private final ArrayList mListeners = new ArrayList<>(); + + private Handler mHandler; + + private final Runnable mFetchAccessTokenRunnable = new Runnable() { + @Override + public void run() { + prepareApi(); + } + }; + + private AccessTokenTask mAccessTokenTask; + + private final StreamObserver mTextResponseObserver + = new StreamObserver() { + + @Override + public void onNext(DetectIntentResponse detectIntentResponse) { + if (mHandler == null) { + return; + } + final String text = detectIntentResponse.getQueryResult().getFulfillmentText(); + mHandler.post(new Runnable() { + @Override + public void run() { + dispatchNewUtterance(new Utterance(Utterance.INCOMING, text)); + } + }); + } + + @Override + public void onError(Throwable throwable) { + Log.e(TAG, "onError: ", throwable); + } + + @Override + public void onCompleted() { + Log.d(TAG, "onCompleted"); + } + + }; + + private StreamObserver mVoiceResponseObserver + = new StreamObserver() { + @Override + public void onNext(StreamingDetectIntentResponse response) { + if (mHandler == null) { + return; + } + final StreamingRecognitionResult recognitionResult = response.getRecognitionResult(); + if (recognitionResult != null) { + mHandler.post(new Runnable() { + @Override + public void run() { + if (recognitionResult.getIsFinal()) { + dispatchNewUtterance(new Utterance(Utterance.OUTGOING, + recognitionResult.getTranscript())); + } else { + dispatchNewRecognition(recognitionResult.getTranscript()); + } + } + }); + } + final QueryResult queryResult = response.getQueryResult(); + if (queryResult != null) { + final String fulfillment = queryResult.getFulfillmentText(); + if (!TextUtils.isEmpty(fulfillment)) { + mHandler.post(new Runnable() { + @Override + public void run() { + dispatchNewUtterance(new Utterance(Utterance.INCOMING, fulfillment)); + } + }); + } + } + } + + @Override + public void onError(Throwable throwable) { + if (throwable instanceof StatusRuntimeException) { + if (((StatusRuntimeException) throwable).getStatus().getCode() == + Status.Code.NOT_FOUND) { + // Probably the audio didn't contain speech; ignore. + return; + } + } + Log.e(TAG, "Error while detecting intent by voice: ", throwable); + } + + @Override + public void onCompleted() { + Log.d(TAG, "Detect intent by voice completed."); + } + }; + + private StreamObserver mRequestObserver; + + public static DialogflowService from(IBinder binder) { + return ((DialogflowBinder) binder).getService(); + } + + @Override + public void onCreate() { + super.onCreate(); + prepareApi(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + releaseApi(); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + public void addListener(@NonNull Listener listener) { + mListeners.add(listener); + if (mApi != null) { + listener.onApiReady(); + } + } + + public void removeListener(@NonNull Listener listener) { + mListeners.remove(listener); + } + + public boolean isApiReady() { + return mApi != null; + } + + public void detectIntentByText(String text) { + if (mApi == null) { + Log.w(TAG, "API not ready. Ignoring the request."); + return; + } + dispatchNewUtterance(new Utterance(Utterance.OUTGOING, text)); + mApi.detectIntent(DetectIntentRequest.newBuilder() + .setSession(createSession(BuildConfig.PROJECT_NAME, SESSION_NAME)) + .setQueryInput(QueryInput.newBuilder() + .setText(TextInput.newBuilder() + .setLanguageCode(BuildConfig.LANGUAGE_CODE) + .setText(text))) + .build(), mTextResponseObserver); + } + + public void startDetectIntentByVoice(int sampleRate) { + if (mApi == null) { + Log.w(TAG, "API not ready. Ignoring the request."); + return; + } + mRequestObserver = mApi.streamingDetectIntent(mVoiceResponseObserver); + mRequestObserver.onNext(StreamingDetectIntentRequest.newBuilder() + .setSession(createSession(BuildConfig.PROJECT_NAME, SESSION_NAME)) + .setQueryInput(QueryInput.newBuilder() + .setAudioConfig(InputAudioConfig.newBuilder() + .setAudioEncoding(AudioEncoding.AUDIO_ENCODING_LINEAR_16) + .setLanguageCode(BuildConfig.LANGUAGE_CODE) + .setSampleRateHertz(sampleRate))) + .build()); + } + + public void detectIntentByVoice(byte[] data, int size) { + if (mRequestObserver == null) { + return; + } + mRequestObserver.onNext(StreamingDetectIntentRequest.newBuilder() + .setInputAudio(ByteString.copyFrom(data, 0, size)) + .build()); + } + + public void finishDetectIntentByVoice() { + if (mRequestObserver == null) { + return; + } + mRequestObserver.onCompleted(); + mRequestObserver = null; + } + + private void prepareApi() { + if (mAccessTokenTask != null) { + return; + } + mHandler = new Handler(); + mAccessTokenTask = new AccessTokenTask(this); + mAccessTokenTask.execute(); + } + + private void releaseApi() { + mHandler.removeCallbacks(mFetchAccessTokenRunnable); + mHandler = null; + // Release the gRPC channel. + if (mApi != null) { + final ManagedChannel channel = (ManagedChannel) mApi.getChannel(); + if (channel != null && !channel.isShutdown()) { + try { + channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Log.e(TAG, "Error shutting down the gRPC channel", e); + } + } + mApi = null; + } + } + + private void dispatchApiReady() { + for (int i = 0, size = mListeners.size(); i < size; i++) { + mListeners.get(i).onApiReady(); + } + } + + private void dispatchNewUtterance(Utterance utterance) { + for (int i = 0, size = mListeners.size(); i < size; i++) { + mListeners.get(i).onNewUtterance(utterance); + } + } + + private void dispatchNewRecognition(String text) { + for (int i = 0, size = mListeners.size(); i < size; i++) { + mListeners.get(i).onNewRecognition(text); + } + } + + private String createSession(String projectId, String sessionName) { + return "projects/" + projectId + "/agent/sessions/" + sessionName; + } + + private class DialogflowBinder extends Binder { + + DialogflowService getService() { + return DialogflowService.this; + } + + } + + private static class AccessTokenTask extends AsyncTask { + + private final WeakReference mServiceRef; + + AccessTokenTask(DialogflowService service) { + mServiceRef = new WeakReference<>(service); + } + + @Override + protected AccessToken doInBackground(Void... voids) { + final DialogflowService service = mServiceRef.get(); + if (service == null) { + return null; + } + final SharedPreferences prefs = service.getApplication() + .getSharedPreferences(PREFS, Context.MODE_PRIVATE); + final String tokenValue = prefs.getString(PREF_ACCESS_TOKEN_VALUE, null); + long expirationTime = prefs.getLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME, -1); + + // Check if the current token is still valid for a while + if (tokenValue != null && expirationTime > 0) { + if (expirationTime + > System.currentTimeMillis() + ACCESS_TOKEN_EXPIRATION_TOLERANCE) { + return new AccessToken(tokenValue, new Date(expirationTime)); + } + } + // ***** WARNING ***** + // In this sample, we load the credential from a JSON file stored in a raw resource + // folder of this client app. You should never do this in your app. Instead, store + // the file in your server and obtain an access token from there. + // ******************* + final InputStream stream = service.getApplication().getResources() + .openRawResource(R.raw.credential); + try { + final GoogleCredentials credentials = GoogleCredentials.fromStream(stream) + .createScoped(SCOPE); + final AccessToken token = credentials.refreshAccessToken(); + prefs.edit() + .putString(PREF_ACCESS_TOKEN_VALUE, token.getTokenValue()) + .putLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME, + token.getExpirationTime().getTime()) + .apply(); + return token; + } catch (IOException e) { + Log.e(TAG, "Failed to obtain access token.", e); + } + return null; + } + + @Override + protected void onPostExecute(AccessToken accessToken) { + final DialogflowService service = mServiceRef.get(); + if (service == null) { + return; + } + final ManagedChannel channel = new OkHttpChannelProvider() + .builderForAddress(HOSTNAME, PORT) + .nameResolverFactory(new DnsNameResolverProvider()) + .intercept(new GoogleCredentialsInterceptor( + GoogleCredentials.create(accessToken) + .createScoped(SCOPE))) + .build(); + service.mApi = SessionsGrpc.newStub(channel); + service.dispatchApiReady(); + + // Schedule access token refresh before it expires + if (service.mHandler != null) { + service.mHandler.postDelayed(service.mFetchAccessTokenRunnable, + Math.max(accessToken.getExpirationTime().getTime() + - System.currentTimeMillis() - ACCESS_TOKEN_FETCH_MARGIN, + ACCESS_TOKEN_EXPIRATION_TOLERANCE)); + } + } + + } + + /** + * Authenticates the gRPC channel using the specified {@link GoogleCredentials}. + */ + private static class GoogleCredentialsInterceptor implements ClientInterceptor { + + private final Credentials mCredentials; + + private Metadata mCached; + + private Map> mLastMetadata; + + GoogleCredentialsInterceptor(Credentials credentials) { + mCredentials = credentials; + } + + @Override + public ClientCall interceptCall( + final MethodDescriptor method, CallOptions callOptions, + final Channel next) { + return new ClientInterceptors.CheckedForwardingClientCall( + next.newCall(method, callOptions)) { + @Override + protected void checkedStart(Listener responseListener, Metadata headers) + throws StatusException { + Metadata cachedSaved; + URI uri = serviceUri(next, method); + synchronized (this) { + Map> latestMetadata = getRequestMetadata(uri); + if (mLastMetadata == null || mLastMetadata != latestMetadata) { + mLastMetadata = latestMetadata; + mCached = toHeaders(mLastMetadata); + } + cachedSaved = mCached; + } + headers.merge(cachedSaved); + delegate().start(responseListener, headers); + } + }; + } + + /** + * Generate a JWT-specific service URI. The URI is simply an identifier with enough + * information for a service to know that the JWT was intended for it. The URI will + * commonly be verified with a simple string equality check. + */ + private URI serviceUri(Channel channel, MethodDescriptor method) + throws StatusException { + String authority = channel.authority(); + if (authority == null) { + throw Status.UNAUTHENTICATED + .withDescription("Channel has no authority") + .asException(); + } + // Always use HTTPS + final String scheme = "https"; + final int defaultPort = 443; + String path = "/" + MethodDescriptor.extractFullServiceName(method.getFullMethodName()); + URI uri; + try { + uri = new URI(scheme, authority, path, null, null); + } catch (URISyntaxException e) { + throw Status.UNAUTHENTICATED + .withDescription("Unable to construct service URI for auth") + .withCause(e).asException(); + } + // The default port must not be present. Alternative ports should be present. + if (uri.getPort() == defaultPort) { + uri = removePort(uri); + } + return uri; + } + + private URI removePort(URI uri) throws StatusException { + try { + return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), -1 /* port */, + uri.getPath(), uri.getQuery(), uri.getFragment()); + } catch (URISyntaxException e) { + throw Status.UNAUTHENTICATED + .withDescription("Unable to construct service URI after removing port") + .withCause(e).asException(); + } + } + + private Map> getRequestMetadata(URI uri) throws StatusException { + try { + return mCredentials.getRequestMetadata(uri); + } catch (IOException e) { + throw Status.UNAUTHENTICATED.withCause(e).asException(); + } + } + + private static Metadata toHeaders(Map> metadata) { + Metadata headers = new Metadata(); + if (metadata != null) { + for (String key : metadata.keySet()) { + Metadata.Key headerKey = Metadata.Key.of( + key, Metadata.ASCII_STRING_MARSHALLER); + for (String value : metadata.get(key)) { + headers.put(headerKey, value); + } + } + } + return headers; + } + + } + +} diff --git a/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/api/Utterance.java b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/api/Utterance.java new file mode 100644 index 00000000..d3a38cec --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/api/Utterance.java @@ -0,0 +1,91 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.api; + +import android.os.Parcel; +import android.os.Parcelable; + +public class Utterance implements Parcelable { + + public static final int INCOMING = 1; + public static final int OUTGOING = 2; + + public final int direction; + public final String text; + + public Utterance(int direction, String text) { + this.direction = direction; + this.text = text; + } + + private Utterance(Parcel in) { + direction = in.readInt(); + text = in.readString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Utterance utterance = (Utterance) o; + + //noinspection SimplifiableIfStatement + if (direction != utterance.direction) return false; + return text != null ? text.equals(utterance.text) : utterance.text == null; + + } + + @Override + public int hashCode() { + int result = direction; + result = 31 * result + (text != null ? text.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Utterance{" + + "direction=" + direction + + ", text='" + text + '\'' + + '}'; + } + + public static final Creator CREATOR = new Creator() { + @Override + public Utterance createFromParcel(Parcel in) { + return new Utterance(in); + } + + @Override + public Utterance[] newArray(int size) { + return new Utterance[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeInt(direction); + parcel.writeString(text); + } + +} diff --git a/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/AudioIndicatorView.java b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/AudioIndicatorView.java new file mode 100644 index 00000000..bfe74063 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/AudioIndicatorView.java @@ -0,0 +1,109 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.ui; + +import android.animation.ObjectAnimator; +import android.content.Context; +import android.content.res.ColorStateList; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; +import android.support.v4.widget.ImageViewCompat; +import android.support.v7.widget.AppCompatImageView; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.AccelerateDecelerateInterpolator; + +import com.google.cloud.android.dialogflow.R; + + +/** + * Shows microphone icon indicating that the app is listening to audio. + */ +public class AudioIndicatorView extends AppCompatImageView { + + private final int mColorNormal; + private final int mColorHearingVoice; + + private boolean mHearingVoice; + private ObjectAnimator mAnimator; + + public AudioIndicatorView(Context context) { + this(context, null); + } + + public AudioIndicatorView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public AudioIndicatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setImageResource(R.drawable.ic_mic); + mColorNormal = ContextCompat.getColor(context, R.color.input_button); + mColorHearingVoice = ContextCompat.getColor(context, R.color.accent); + ImageViewCompat.setImageTintList(this, ColorStateList.valueOf(mColorNormal)); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + startAnimating(); + } + + @Override + protected void onDetachedFromWindow() { + if (mHearingVoice) { + stopAnimating(); + } + super.onDetachedFromWindow(); + } + + public void setHearingVoice(boolean hearingVoice) { + if (mHearingVoice == hearingVoice) { + return; + } + mHearingVoice = hearingVoice; + if (hearingVoice) { + stopAnimating(); + ImageViewCompat.setImageTintList(this, ColorStateList.valueOf(mColorHearingVoice)); + } else { + startAnimating(); + ImageViewCompat.setImageTintList(this, ColorStateList.valueOf(mColorNormal)); + } + } + + public boolean isHearingVoice() { + return mHearingVoice; + } + + private void startAnimating() { + mAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 1.f, 0.3f); + mAnimator.setRepeatCount(ObjectAnimator.INFINITE); + mAnimator.setRepeatMode(ObjectAnimator.REVERSE); + mAnimator.setDuration(1000); + mAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); + mAnimator.start(); + } + + private void stopAnimating() { + if (mAnimator != null) { + mAnimator.end(); + setAlpha(1.0f); + mAnimator = null; + } + } + +} diff --git a/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/BubbleView.java b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/BubbleView.java new file mode 100644 index 00000000..dacb6527 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/BubbleView.java @@ -0,0 +1,107 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.ui; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.support.annotation.IntDef; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; +import android.support.v4.view.ViewCompat; +import android.support.v7.widget.AppCompatTextView; +import android.util.AttributeSet; + +import com.google.cloud.android.dialogflow.R; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + + +/** + * A {@link android.widget.TextView} that displays text in a speech bubble. + */ +public class BubbleView extends AppCompatTextView { + + public static final int DIRECTION_INCOMING = 1; + public static final int DIRECTION_OUTGOING = 2; + + private final ColorStateList mTintIncoming; + private final ColorStateList mTintOutgoing; + + private final int mPaddingVertical; + private final int mPaddingHorizontalShort; + private final int mPaddingHorizontalLong; + + @IntDef({DIRECTION_INCOMING, DIRECTION_OUTGOING}) + @Retention(RetentionPolicy.SOURCE) + @interface Direction { + } + + private int mDirection; + + public BubbleView(Context context) { + this(context, null); + } + + public BubbleView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + @SuppressWarnings("WrongConstant") + public BubbleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mTintIncoming = ColorStateList.valueOf( + ContextCompat.getColor(context, R.color.incoming)); + mTintOutgoing = ColorStateList.valueOf( + ContextCompat.getColor(context, R.color.outgoing)); + final Resources resources = getResources(); + mPaddingVertical = resources.getDimensionPixelSize(R.dimen.bubble_padding_vertical); + mPaddingHorizontalShort = resources.getDimensionPixelSize( + R.dimen.bubble_padding_horizontal_short); + mPaddingHorizontalLong = resources.getDimensionPixelSize( + R.dimen.bubble_padding_horizontal_long); + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BubbleView); + setDirection(a.getInt(R.styleable.BubbleView_direction, DIRECTION_INCOMING)); + a.recycle(); + } + + public void setDirection(@Direction int direction) { + if (mDirection == direction) { + return; + } + mDirection = direction; + if (mDirection == DIRECTION_INCOMING) { + setBackgroundResource(R.drawable.bubble_incoming); + ViewCompat.setBackgroundTintList(this, mTintIncoming); + setPadding(mPaddingHorizontalLong, mPaddingVertical, + mPaddingHorizontalShort, mPaddingVertical); + } else { + setBackgroundResource(R.drawable.bubble_outgoing); + ViewCompat.setBackgroundTintList(this, mTintOutgoing); + setPadding(mPaddingHorizontalShort, mPaddingVertical, + mPaddingHorizontalLong, mPaddingVertical); + } + } + + @Direction + public int getDirection() { + return mDirection; + } + +} diff --git a/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/HistoryAdapter.java b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/HistoryAdapter.java new file mode 100644 index 00000000..e87c8ff0 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/HistoryAdapter.java @@ -0,0 +1,94 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.ui; + +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.google.cloud.android.dialogflow.R; +import com.google.cloud.android.dialogflow.api.Utterance; + +import java.util.ArrayList; + + +public class HistoryAdapter extends RecyclerView.Adapter { + + private final ArrayList mHistory = new ArrayList<>(); + + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new ViewHolder(LayoutInflater.from(parent.getContext()), parent); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + final Utterance utterance = mHistory.get(position); + holder.bind(utterance.text, + utterance.direction == Utterance.INCOMING + ? BubbleView.DIRECTION_INCOMING + : BubbleView.DIRECTION_OUTGOING); + } + + @Override + public int getItemCount() { + return mHistory.size(); + } + + public void addUtterance(Utterance utterance) { + mHistory.add(utterance); + notifyItemInserted(mHistory.size() - 1); + } + + public ArrayList getHistory() { + return mHistory; + } + + public void restoreHistory(ArrayList history) { + mHistory.clear(); + mHistory.addAll(history); + } + + static class ViewHolder extends RecyclerView.ViewHolder { + + FrameLayout frame; + BubbleView bubble; + + ViewHolder(LayoutInflater inflater, ViewGroup parent) { + super(inflater.inflate(R.layout.item_conversation, parent, false)); + frame = itemView.findViewById(R.id.frame); + bubble = itemView.findViewById(R.id.bubble); + } + + void bind(String message, int direction) { + bubble.setText(message); + bubble.setDirection(direction); + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) bubble.getLayoutParams(); + if (direction == BubbleView.DIRECTION_INCOMING) { + lp.gravity = Gravity.START | Gravity.CENTER_VERTICAL; + } else { + lp.gravity = Gravity.END | Gravity.CENTER_VERTICAL; + } + bubble.setLayoutParams(lp); + } + + } + +} diff --git a/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/InputHelper.java b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/InputHelper.java new file mode 100644 index 00000000..c66512b3 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/InputHelper.java @@ -0,0 +1,293 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.ui; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.TextView; + +import com.google.cloud.android.dialogflow.R; +import com.google.cloud.android.dialogflow.util.VoiceRecorder; + + +/** + * Helper class for managing 2 input modes; software keyboard and audio. + */ +public class InputHelper { + + /** Software keyboard mode; input is empty */ + private static final int MODE_TEXT_EMPTY = 1; + /** Software keyboard mode; user is typing */ + private static final int MODE_TEXT_TYPING = 2; + /** Audio input mode */ + private static final int MODE_AUDIO = 3; + + private final EditText mText; + private final ImageButton mToggle; + private final AudioIndicatorView mIndicator; + + private final VoiceRecorder mVoiceRecorder; + + private final Callback mCallback; + + private int mMode = MODE_TEXT_EMPTY; + + private final String mDescriptionVoice; + private final String mDescriptionSend; + private final String mDescriptionKeyboard; + + private boolean mEnabled; + + /** + * Instantiates a new instance of {@link InputHelper}. + * + * @param text The text input for the software keyboard. This is also used to show + * transcript of audio input. + * @param toggle The button to toggle the modes. + * @param callback The callback. + */ + public InputHelper(EditText text, ImageButton toggle, AudioIndicatorView indicator, + Callback callback) { + mText = text; + mToggle = toggle; + mIndicator = indicator; + mCallback = callback; + mVoiceRecorder = new VoiceRecorder(wrapVoiceCallback(callback)); + // Bind event handlers + text.addTextChangedListener(new TextWatcherAdapter() { + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (mMode == MODE_AUDIO) { + return; + } + changeTextMode(s); + } + }); + text.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + send(); + return true; + } + }); + toggle.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (mMode == MODE_TEXT_EMPTY) { + startAudio(); + } else if (mMode == MODE_TEXT_TYPING) { + send(); + } else if (mMode == MODE_AUDIO) { + startText(); + } + } + }); + // String resources + final Context context = mText.getContext(); + mDescriptionVoice = context.getString(R.string.description_voice); + mDescriptionSend = context.getString(R.string.description_send); + mDescriptionKeyboard = context.getString(R.string.description_keyboard); + // Initial view states + mText.setEnabled(false); + mToggle.setEnabled(false); + changeTextMode(text.getText()); + } + + public void setEnabled(boolean enabled) { + if (mEnabled == enabled) { + return; + } + mEnabled = enabled; + mText.setEnabled(enabled); + mToggle.setEnabled(enabled); + } + + /** + * Releases all the retained resources. + */ + public void release() { + mVoiceRecorder.stop(); + } + + /** + * @return The sample rate for the audio input. + */ + public int getSampleRate() { + return mVoiceRecorder.getSampleRate(); + } + + /** + * Resumes audio input. + */ + public void resumeAudio() { + mVoiceRecorder.start(); + } + + /** + * Falls back to text input mode. + */ + public void fallbackToText() { + startText(); + } + + /** + * Shows a real-time audio recognition result. This is only available when the user is using + * audio input. + * + * @param transcript The transcript. Pass {@code null} to clear. + */ + public void showTranscript(@Nullable String transcript) { + if (mMode != MODE_AUDIO) { + return; + } + mText.setText(transcript); + } + + private void startAudio() { + if (mCallback.ensureRecordAudioPermission()) { + mIndicator.setVisibility(View.VISIBLE); + mText.getText().clear(); + mText.setEnabled(false); + mText.setHint(R.string.hint_audio); + mToggle.setImageResource(R.drawable.ic_keyboard); + mToggle.setContentDescription(mDescriptionKeyboard); + mMode = MODE_AUDIO; + mVoiceRecorder.start(); + } + } + + private void startText() { + mVoiceRecorder.stop(); + mIndicator.setVisibility(View.GONE); + mText.getText().clear(); + mText.setEnabled(true); + mText.setHint(R.string.hint_text); + mToggle.setImageResource(R.drawable.ic_mic); + mToggle.setContentDescription(mDescriptionVoice); + mMode = MODE_TEXT_EMPTY; + } + + private void send() { + if (!mEnabled) { + return; + } + final Editable content = mText.getText(); + if (TextUtils.isEmpty(content)) { + return; + } + mCallback.onText(content.toString()); + content.clear(); + changeTextMode(null); + } + + private void changeTextMode(CharSequence s) { + if (TextUtils.isEmpty(s)) { + mToggle.setImageResource(R.drawable.ic_mic); + mToggle.setContentDescription(mDescriptionVoice); + mMode = MODE_TEXT_EMPTY; + } else { + mToggle.setImageResource(R.drawable.ic_send); + mToggle.setContentDescription(mDescriptionSend); + mMode = MODE_TEXT_TYPING; + } + } + + private VoiceRecorder.Callback wrapVoiceCallback(final Callback callback) { + return new VoiceRecorder.Callback() { + @Override + public void onVoiceStart() { + callback.onVoiceStart(); + mIndicator.post(new Runnable() { + @Override + public void run() { + mIndicator.setHearingVoice(true); + } + }); + } + + @Override + public void onVoice(byte[] data, int size) { + callback.onVoice(data, size); + } + + @Override + public void onVoiceEnd() { + mIndicator.post(new Runnable() { + @Override + public void run() { + mIndicator.setHearingVoice(false); + } + }); + callback.onVoiceEnd(); + } + }; + } + + /** + * Callbacks for {@link InputHelper}. + */ + public static abstract class Callback extends VoiceRecorder.Callback { + + /** + * Called when a new text is input from the keyboard. + * + * @param text A new text input. + */ + public void onText(String text) { + } + + /** + * Called when the {@link InputHelper} needs to make sure that the app has permission for + * audio recording. + * + * @return {@code true} if audio recording permission is available. If the implementation + * returns {@code false}, it is responsible for calling {@link #resumeAudio()} after the + * permission is granted. + */ + public boolean ensureRecordAudioPermission() { + return false; + } + + } + + /** + * A convenience class for overriding some methods of {@link TextWatcher}. + */ + private static abstract class TextWatcherAdapter implements TextWatcher { + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + } + + } + +} diff --git a/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/MessageDialogFragment.java b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/MessageDialogFragment.java new file mode 100644 index 00000000..3ec14c48 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/ui/MessageDialogFragment.java @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.ui; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatDialogFragment; + + +/** + * A simple dialog with a message. + * + *

The calling {@link android.app.Activity} needs to implement {@link + * MessageDialogFragment.Listener}.

+ */ +public class MessageDialogFragment extends AppCompatDialogFragment { + + interface Listener { + /** + * Called when the dialog is dismissed. + */ + void onMessageDialogDismissed(); + } + + private static final String ARG_MESSAGE = "message"; + + /** + * Creates a new instance of {@link MessageDialogFragment}. + * + * @param message The message to be shown on the dialog. + * @return A newly created dialog fragment. + */ + public static MessageDialogFragment newInstance(String message) { + final MessageDialogFragment fragment = new MessageDialogFragment(); + final Bundle args = new Bundle(); + args.putString(ARG_MESSAGE, message); + fragment.setArguments(args); + return fragment; + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); + final Bundle args = getArguments(); + if (args != null) { + builder.setMessage(getArguments().getString(ARG_MESSAGE)); + } + return builder + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + ((Listener) requireActivity()).onMessageDialogDismissed(); + } + }) + .setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialogInterface) { + ((Listener) requireActivity()).onMessageDialogDismissed(); + } + }) + .create(); + } + +} diff --git a/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/util/VoiceRecorder.java b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/util/VoiceRecorder.java new file mode 100644 index 00000000..5f3ac9ff --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/java/com/google/cloud/android/dialogflow/util/VoiceRecorder.java @@ -0,0 +1,230 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +package com.google.cloud.android.dialogflow.util; + +import android.media.AudioFormat; +import android.media.AudioRecord; +import android.media.MediaRecorder; +import android.support.annotation.NonNull; + + +/** + * Continuously records audio and notifies the {@link VoiceRecorder.Callback} when voice (or any + * sound) is heard. + * + *

The recorded audio format is always {@link AudioFormat#ENCODING_PCM_16BIT} and + * {@link AudioFormat#CHANNEL_IN_MONO}. This class will automatically pick the right sample rate + * for the device. Use {@link #getSampleRate()} to get the selected value.

+ */ +public class VoiceRecorder { + + private static final int[] SAMPLE_RATE_CANDIDATES = new int[]{16000, 11025, 22050, 44100}; + + private static final int CHANNEL = AudioFormat.CHANNEL_IN_MONO; + private static final int ENCODING = AudioFormat.ENCODING_PCM_16BIT; + + private static final int AMPLITUDE_THRESHOLD = 1500; + private static final int SPEECH_TIMEOUT_MILLIS = 2000; + private static final int MAX_SPEECH_LENGTH_MILLIS = 30 * 1000; + + public static abstract class Callback { + + /** + * Called when the recorder starts hearing voice. + */ + public void onVoiceStart() { + } + + /** + * Called when the recorder is hearing voice. + * + * @param data The audio data in {@link AudioFormat#ENCODING_PCM_16BIT}. + * @param size The size of the actual data in {@code data}. + */ + public void onVoice(byte[] data, int size) { + } + + /** + * Called when the recorder stops hearing voice. + */ + public void onVoiceEnd() { + } + } + + private final Callback mCallback; + + private AudioRecord mAudioRecord; + + private Thread mThread; + + private byte[] mBuffer; + + private final Object mLock = new Object(); + + /** The timestamp of the last time that voice is heard. */ + private long mLastVoiceHeardMillis = Long.MAX_VALUE; + + /** The timestamp when the current voice is started. */ + private long mVoiceStartedMillis; + + public VoiceRecorder(@NonNull Callback callback) { + mCallback = callback; + } + + /** + * Starts recording audio. + * + *

The caller is responsible for calling {@link #stop()} later.

+ */ + public void start() { + // Stop recording if it is currently ongoing. + stop(); + // Try to create a new recording session. + mAudioRecord = createAudioRecord(); + if (mAudioRecord == null) { + throw new RuntimeException("Cannot instantiate VoiceRecorder"); + } + // Start recording. + mAudioRecord.startRecording(); + // Start processing the captured audio. + mThread = new Thread(new ProcessVoice()); + mThread.start(); + } + + /** + * Stops recording audio. + */ + public void stop() { + synchronized (mLock) { + dismiss(); + if (mThread != null) { + mThread.interrupt(); + mThread = null; + } + if (mAudioRecord != null) { + mAudioRecord.stop(); + mAudioRecord.release(); + mAudioRecord = null; + } + mBuffer = null; + } + } + + /** + * Dismisses the currently ongoing utterance. + */ + @SuppressWarnings("WeakerAccess") + public void dismiss() { + if (mLastVoiceHeardMillis != Long.MAX_VALUE) { + mLastVoiceHeardMillis = Long.MAX_VALUE; + mCallback.onVoiceEnd(); + } + } + + /** + * Retrieves the sample rate currently used to record audio. + * + * @return The sample rate of recorded audio. + */ + public int getSampleRate() { + if (mAudioRecord != null) { + return mAudioRecord.getSampleRate(); + } + return 0; + } + + /** + * Creates a new {@link AudioRecord}. + * + * @return A newly created {@link AudioRecord}, or null if it cannot be created (missing + * permissions?). + */ + private AudioRecord createAudioRecord() { + for (int sampleRate : SAMPLE_RATE_CANDIDATES) { + final int sizeInBytes = AudioRecord.getMinBufferSize(sampleRate, CHANNEL, ENCODING); + if (sizeInBytes == AudioRecord.ERROR_BAD_VALUE) { + continue; + } + final AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, + sampleRate, CHANNEL, ENCODING, sizeInBytes); + if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) { + mBuffer = new byte[sizeInBytes]; + return audioRecord; + } else { + audioRecord.release(); + } + } + return null; + } + + /** + * Continuously processes the captured audio and notifies {@link #mCallback} of corresponding + * events. + */ + private class ProcessVoice implements Runnable { + + @Override + public void run() { + while (true) { + synchronized (mLock) { + if (Thread.currentThread().isInterrupted()) { + break; + } + final int size = mAudioRecord.read(mBuffer, 0, mBuffer.length); + final long now = System.currentTimeMillis(); + if (isHearingVoice(mBuffer, size)) { + if (mLastVoiceHeardMillis == Long.MAX_VALUE) { + mVoiceStartedMillis = now; + mCallback.onVoiceStart(); + } + mCallback.onVoice(mBuffer, size); + mLastVoiceHeardMillis = now; + if (now - mVoiceStartedMillis > MAX_SPEECH_LENGTH_MILLIS) { + end(); + } + } else if (mLastVoiceHeardMillis != Long.MAX_VALUE) { + mCallback.onVoice(mBuffer, size); + if (now - mLastVoiceHeardMillis > SPEECH_TIMEOUT_MILLIS) { + end(); + } + } + } + } + } + + private void end() { + mLastVoiceHeardMillis = Long.MAX_VALUE; + mCallback.onVoiceEnd(); + } + + private boolean isHearingVoice(byte[] buffer, int size) { + for (int i = 0; i < size - 1; i += 2) { + // The buffer has LINEAR16 in little endian. + int s = buffer[i + 1]; + if (s < 0) s *= -1; + s <<= 8; + s += Math.abs(buffer[i]); + if (s > AMPLITUDE_THRESHOLD) { + return true; + } + } + return false; + } + + } + +} diff --git a/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/agent.proto b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/agent.proto new file mode 100644 index 00000000..ec2ed6da --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/agent.proto @@ -0,0 +1,330 @@ +// Copyright 2018 Google Inc. +// +// 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. + +syntax = "proto3"; + +package google.cloud.dialogflow.v2; + +import "google/api/annotations.proto"; +import "google/longrunning/operations.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/struct.proto"; + +option cc_enable_arenas = true; +option csharp_namespace = "Google.Cloud.Dialogflow.V2"; +option go_package = "google.golang.org/genproto/googleapis/cloud/dialogflow/v2;dialogflow"; +option java_multiple_files = true; +option java_outer_classname = "AgentProto"; +option java_package = "com.google.cloud.dialogflow.v2"; +option objc_class_prefix = "DF"; + + +// Agents are best described as Natural Language Understanding (NLU) modules +// that transform user requests into actionable data. You can include agents +// in your app, product, or service to determine user intent and respond to the +// user in a natural way. +// +// After you create an agent, you can add [Intents][google.cloud.dialogflow.v2.Intents], [Contexts][google.cloud.dialogflow.v2.Contexts], +// [Entity Types][google.cloud.dialogflow.v2.EntityTypes], [Webhooks][google.cloud.dialogflow.v2.WebhookRequest], and so on to +// manage the flow of a conversation and match user input to predefined intents +// and actions. +// +// You can create an agent using both Dialogflow Standard Edition and +// Dialogflow Enterprise Edition. For details, see +// [Dialogflow Editions](/dialogflow-enterprise/docs/editions). +// +// You can save your agent for backup or versioning by exporting the agent by +// using the [ExportAgent][google.cloud.dialogflow.v2.Agents.ExportAgent] method. You can import a saved +// agent by using the [ImportAgent][google.cloud.dialogflow.v2.Agents.ImportAgent] method. +// +// Dialogflow provides several +// [prebuilt agents](https://dialogflow.com/docs/prebuilt-agents) for common +// conversation scenarios such as determining a date and time, converting +// currency, and so on. +// +// For more information about agents, see the +// [Dialogflow documentation](https://dialogflow.com/docs/agents). +service Agents { + // Retrieves the specified agent. + rpc GetAgent(GetAgentRequest) returns (Agent) { + option (google.api.http) = { + get: "/v2/{parent=projects/*}/agent" + }; + } + + // Returns the list of agents. + // + // Since there is at most one conversational agent per project, this method is + // useful primarily for listing all agents across projects the caller has + // access to. One can achieve that with a wildcard project collection id "-". + // Refer to [List + // Sub-Collections](https://cloud.google.com/apis/design/design_patterns#list_sub-collections). + rpc SearchAgents(SearchAgentsRequest) returns (SearchAgentsResponse) { + option (google.api.http) = { + get: "/v2/{parent=projects/*}/agent:search" + }; + } + + // Trains the specified agent. + // + // Operation + rpc TrainAgent(TrainAgentRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v2/{parent=projects/*}/agent:train" + body: "*" + }; + } + + // Exports the specified agent to a ZIP file. + // + // Operation + rpc ExportAgent(ExportAgentRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v2/{parent=projects/*}/agent:export" + body: "*" + }; + } + + // Imports the specified agent from a ZIP file. + // + // Uploads new intents and entity types without deleting the existing ones. + // Intents and entity types with the same name are replaced with the new + // versions from ImportAgentRequest. + // + // Operation + rpc ImportAgent(ImportAgentRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v2/{parent=projects/*}/agent:import" + body: "*" + }; + } + + // Restores the specified agent from a ZIP file. + // + // Replaces the current agent version with a new one. All the intents and + // entity types in the older version are deleted. + // + // Operation + rpc RestoreAgent(RestoreAgentRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v2/{parent=projects/*}/agent:restore" + body: "*" + }; + } +} + +// Represents a conversational agent. +message Agent { + // Match mode determines how intents are detected from user queries. + enum MatchMode { + // Not specified. + MATCH_MODE_UNSPECIFIED = 0; + + // Best for agents with a small number of examples in intents and/or wide + // use of templates syntax and composite entities. + MATCH_MODE_HYBRID = 1; + + // Can be used for agents with a large number of examples in intents, + // especially the ones using @sys.any or very large developer entities. + MATCH_MODE_ML_ONLY = 2; + } + + // Required. The project of this agent. + // Format: `projects/`. + string parent = 1; + + // Required. The name of this agent. + string display_name = 2; + + // Required. The default language of the agent as a language tag. See + // [Language Support](https://dialogflow.com/docs/reference/language) for a + // list of the currently supported language codes. + // This field cannot be set by the `Update` method. + string default_language_code = 3; + + // Optional. The list of all languages supported by this agent (except for the + // `default_language_code`). + repeated string supported_language_codes = 4; + + // Required. The time zone of this agent from the + // [time zone database](https://www.iana.org/time-zones), e.g., + // America/New_York, Europe/Paris. + string time_zone = 5; + + // Optional. The description of this agent. + // The maximum length is 500 characters. If exceeded, the request is rejected. + string description = 6; + + // Optional. The URI of the agent's avatar. + // Avatars are used throughout the Dialogflow console and in the self-hosted + // [Web Demo](https://dialogflow.com/docs/integrations/web-demo) integration. + string avatar_uri = 7; + + // Optional. Determines whether this agent should log conversation queries. + bool enable_logging = 8; + + // Optional. Determines how intents are detected from user queries. + MatchMode match_mode = 9; + + // Optional. To filter out false positive results and still get variety in + // matched natural language inputs for your agent, you can tune the machine + // learning classification threshold. If the returned score value is less than + // the threshold value, then a fallback intent is be triggered or, if there + // are no fallback intents defined, no intent will be triggered. The score + // values range from 0.0 (completely uncertain) to 1.0 (completely certain). + // If set to 0.0, the default of 0.3 is used. + float classification_threshold = 10; +} + +// The request message for [Agents.GetAgent][google.cloud.dialogflow.v2.Agents.GetAgent]. +message GetAgentRequest { + // Required. The project that the agent to fetch is associated with. + // Format: `projects/`. + string parent = 1; +} + +// The request message for [Agents.SearchAgents][google.cloud.dialogflow.v2.Agents.SearchAgents]. +message SearchAgentsRequest { + // Required. The project to list agents from. + // Format: `projects/`. + string parent = 1; + + // Optional. The maximum number of items to return in a single page. By + // default 100 and at most 1000. + int32 page_size = 2; + + // Optional. The next_page_token value returned from a previous list request. + string page_token = 3; +} + +// The response message for [Agents.SearchAgents][google.cloud.dialogflow.v2.Agents.SearchAgents]. +message SearchAgentsResponse { + // The list of agents. There will be a maximum number of items returned based + // on the page_size field in the request. + repeated Agent agents = 1; + + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + string next_page_token = 2; +} + +// The request message for [Agents.TrainAgent][google.cloud.dialogflow.v2.Agents.TrainAgent]. +message TrainAgentRequest { + // Required. The project that the agent to train is associated with. + // Format: `projects/`. + string parent = 1; +} + +// The request message for [Agents.ExportAgent][google.cloud.dialogflow.v2.Agents.ExportAgent]. +message ExportAgentRequest { + // Required. The project that the agent to export is associated with. + // Format: `projects/`. + string parent = 1; + + // Optional. The Google Cloud Storage URI to export the agent to. + // Note: The URI must start with + // "gs://". If left unspecified, the serialized agent is returned inline. + string agent_uri = 2; +} + +// The response message for [Agents.ExportAgent][google.cloud.dialogflow.v2.Agents.ExportAgent]. +message ExportAgentResponse { + // Required. The exported agent. + oneof agent { + // The URI to a file containing the exported agent. This field is populated + // only if `agent_uri` is specified in `ExportAgentRequest`. + string agent_uri = 1; + + // The exported agent. + // + // Example for how to export an agent to a zip file via a command line: + // + // curl \ + // 'https://dialogflow.googleapis.com/v2/projects//agent:export'\ + // -X POST \ + // -H 'Authorization: Bearer '$(gcloud auth print-access-token) \ + // -H 'Accept: application/json' \ + // -H 'Content-Type: application/json' \ + // --compressed \ + // --data-binary '{}' \ + // | grep agentContent | sed -e 's/.*"agentContent": "\([^"]*\)".*/\1/' \ + // | base64 --decode > + bytes agent_content = 2; + } +} + +// The request message for [Agents.ImportAgent][google.cloud.dialogflow.v2.Agents.ImportAgent]. +message ImportAgentRequest { + // Required. The project that the agent to import is associated with. + // Format: `projects/`. + string parent = 1; + + // Required. The agent to import. + oneof agent { + // The URI to a Google Cloud Storage file containing the agent to import. + // Note: The URI must start with "gs://". + string agent_uri = 2; + + // The agent to import. + // + // Example for how to import an agent via the command line: + // + // curl \ + // 'https://dialogflow.googleapis.com/v2/projects//agent:import\ + // -X POST \ + // -H 'Authorization: Bearer '$(gcloud auth print-access-token) \ + // -H 'Accept: application/json' \ + // -H 'Content-Type: application/json' \ + // --compressed \ + // --data-binary "{ + // 'agentContent': '$(cat | base64 -w 0)' + // }" + bytes agent_content = 3; + } +} + +// The request message for [Agents.RestoreAgent][google.cloud.dialogflow.v2.Agents.RestoreAgent]. +message RestoreAgentRequest { + // Required. The project that the agent to restore is associated with. + // Format: `projects/`. + string parent = 1; + + // Required. The agent to restore. + oneof agent { + // The URI to a Google Cloud Storage file containing the agent to restore. + // Note: The URI must start with "gs://". + string agent_uri = 2; + + // The agent to restore. + // + // Example for how to restore an agent via the command line: + // + // curl \ + // 'https://dialogflow.googleapis.com/v2/projects//agent:restore\ + // -X POST \ + // -H 'Authorization: Bearer '$(gcloud auth print-access-token) \ + // -H 'Accept: application/json' \ + // -H 'Content-Type: application/json' \ + // --compressed \ + // --data-binary "{ + // 'agentContent': '$(cat | base64 -w 0)' + // }" \ + bytes agent_content = 3; + } +} diff --git a/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/context.proto b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/context.proto new file mode 100644 index 00000000..2d1798e0 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/context.proto @@ -0,0 +1,177 @@ +// Copyright 2018 Google Inc. +// +// 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. + +syntax = "proto3"; + +package google.cloud.dialogflow.v2; + +import "google/api/annotations.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/struct.proto"; + +option cc_enable_arenas = true; +option csharp_namespace = "Google.Cloud.Dialogflow.V2"; +option go_package = "google.golang.org/genproto/googleapis/cloud/dialogflow/v2;dialogflow"; +option java_multiple_files = true; +option java_outer_classname = "ContextProto"; +option java_package = "com.google.cloud.dialogflow.v2"; +option objc_class_prefix = "DF"; + + +// A context represents additional information included with user input or with +// an intent returned by the Dialogflow API. Contexts are helpful for +// differentiating user input which may be vague or have a different meaning +// depending on additional details from your application such as user setting +// and preferences, previous user input, where the user is in your application, +// geographic location, and so on. +// +// You can include contexts as input parameters of a +// [DetectIntent][google.cloud.dialogflow.v2.Sessions.DetectIntent] (or +// [StreamingDetectIntent][google.cloud.dialogflow.v2.Sessions.StreamingDetectIntent]) request, +// or as output contexts included in the returned intent. +// Contexts expire when an intent is matched, after the number of `DetectIntent` +// requests specified by the `lifespan_count` parameter, or after 10 minutes +// if no intents are matched for a `DetectIntent` request. +// +// For more information about contexts, see the +// [Dialogflow documentation](https://dialogflow.com/docs/contexts). +service Contexts { + // Returns the list of all contexts in the specified session. + rpc ListContexts(ListContextsRequest) returns (ListContextsResponse) { + option (google.api.http) = { + get: "/v2/{parent=projects/*/agent/sessions/*}/contexts" + }; + } + + // Retrieves the specified context. + rpc GetContext(GetContextRequest) returns (Context) { + option (google.api.http) = { + get: "/v2/{name=projects/*/agent/sessions/*/contexts/*}" + }; + } + + // Creates a context. + rpc CreateContext(CreateContextRequest) returns (Context) { + option (google.api.http) = { + post: "/v2/{parent=projects/*/agent/sessions/*}/contexts" + body: "context" + }; + } + + // Updates the specified context. + rpc UpdateContext(UpdateContextRequest) returns (Context) { + option (google.api.http) = { + patch: "/v2/{context.name=projects/*/agent/sessions/*/contexts/*}" + body: "context" + }; + } + + // Deletes the specified context. + rpc DeleteContext(DeleteContextRequest) returns (google.protobuf.Empty) { + option (google.api.http) = { + delete: "/v2/{name=projects/*/agent/sessions/*/contexts/*}" + }; + } + + // Deletes all active contexts in the specified session. + rpc DeleteAllContexts(DeleteAllContextsRequest) returns (google.protobuf.Empty) { + option (google.api.http) = { + delete: "/v2/{parent=projects/*/agent/sessions/*}/contexts" + }; + } +} + +// Represents a context. +message Context { + // Required. The unique identifier of the context. Format: + // `projects//agent/sessions//contexts/`. + string name = 1; + + // Optional. The number of conversational query requests after which the + // context expires. If set to `0` (the default) the context expires + // immediately. Contexts expire automatically after 10 minutes even if there + // are no matching queries. + int32 lifespan_count = 2; + + // Optional. The collection of parameters associated with this context. + // Refer to [this doc](https://dialogflow.com/docs/actions-and-parameters) for + // syntax. + google.protobuf.Struct parameters = 3; +} + +// The request message for [Contexts.ListContexts][google.cloud.dialogflow.v2.Contexts.ListContexts]. +message ListContextsRequest { + // Required. The session to list all contexts from. + // Format: `projects//agent/sessions/`. + string parent = 1; + + // Optional. The maximum number of items to return in a single page. By + // default 100 and at most 1000. + int32 page_size = 2; + + // Optional. The next_page_token value returned from a previous list request. + string page_token = 3; +} + +// The response message for [Contexts.ListContexts][google.cloud.dialogflow.v2.Contexts.ListContexts]. +message ListContextsResponse { + // The list of contexts. There will be a maximum number of items + // returned based on the page_size field in the request. + repeated Context contexts = 1; + + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + string next_page_token = 2; +} + +// The request message for [Contexts.GetContext][google.cloud.dialogflow.v2.Contexts.GetContext]. +message GetContextRequest { + // Required. The name of the context. Format: + // `projects//agent/sessions//contexts/`. + string name = 1; +} + +// The request message for [Contexts.CreateContext][google.cloud.dialogflow.v2.Contexts.CreateContext]. +message CreateContextRequest { + // Required. The session to create a context for. + // Format: `projects//agent/sessions/`. + string parent = 1; + + // Required. The context to create. + Context context = 2; +} + +// The request message for [Contexts.UpdateContext][google.cloud.dialogflow.v2.Contexts.UpdateContext]. +message UpdateContextRequest { + // Required. The context to update. + Context context = 1; + + // Optional. The mask to control which fields get updated. + google.protobuf.FieldMask update_mask = 2; +} + +// The request message for [Contexts.DeleteContext][google.cloud.dialogflow.v2.Contexts.DeleteContext]. +message DeleteContextRequest { + // Required. The name of the context to delete. Format: + // `projects//agent/sessions//contexts/`. + string name = 1; +} + +// The request message for [Contexts.DeleteAllContexts][google.cloud.dialogflow.v2.Contexts.DeleteAllContexts]. +message DeleteAllContextsRequest { + // Required. The name of the session to delete all contexts from. Format: + // `projects//agent/sessions/`. + string parent = 1; +} diff --git a/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/dialogflow_gapic.yaml b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/dialogflow_gapic.yaml new file mode 100644 index 00000000..4664a8f9 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/dialogflow_gapic.yaml @@ -0,0 +1,1280 @@ +type: com.google.api.codegen.ConfigProto +config_schema_version: 1.0.0 +# The settings of generated code in a specific language. +language_settings: + java: + package_name: com.google.cloud.dialogflow.v2 + python: + package_name: google.cloud.dialogflow_v2.gapic + go: + package_name: cloud.google.com/go/dialogflow/apiv2 + csharp: + package_name: Google.Cloud.Dialogflow.V2 + ruby: + package_name: Google::Cloud::Dialogflow::V2 + php: + package_name: Google\Cloud\Dialogflow\V2 + nodejs: + package_name: dialogflow.v2 +# The configuration for the license header to put on generated files. +license_header: + # The file containing the copyright line(s). + copyright_file: copyright-google.txt + # The file containing the raw license header without any copyright line(s). + license_file: license-header-apache-2.0.txt +# A list of API interface configurations. +interfaces: + # The fully qualified name of the API interface. +- name: google.cloud.dialogflow.v2.Agents + # A list of resource collection configurations. + # Consists of a name_pattern and an entity_name. + # The name_pattern is a pattern to describe the names of the resources of this + # collection, using the platform's conventions for URI patterns. A generator + # may use this to generate methods to compose and decompose such names. The + # pattern should use named placeholders as in `shelves/{shelf}/books/{book}`; + # those will be taken as hints for the parameter names of the generated + # methods. If empty, no name methods are generated. + # The entity_name is the name to be used as a basis for generated methods and + # classes. + collections: + - name_pattern: projects/{project} + entity_name: project + language_overrides: + - language: csharp + common_resource_name: Google.Api.Gax.ResourceNames.ProjectName + # Definition for retryable codes. + retry_codes_def: + - name: idempotent + retry_codes: + - UNAVAILABLE + - DEADLINE_EXCEEDED + - name: non_idempotent + retry_codes: [] + # Definition for retry/backoff parameters. + retry_params_def: + - name: default + initial_retry_delay_millis: 100 + retry_delay_multiplier: 1.3 + max_retry_delay_millis: 60000 + initial_rpc_timeout_millis: 20000 + rpc_timeout_multiplier: 1 + max_rpc_timeout_millis: 20000 + total_timeout_millis: 600000 + # A list of method configurations. + # Common properties: + # name - The simple name of the method. + # flattening - Specifies the configuration for parameter flattening. + # Describes the parameter groups for which a generator should produce + # method overloads which allow a client to directly pass request message + # fields as method parameters. This information may or may not be used, + # depending on the target language. + # Consists of groups, which each represent a list of parameters to be + # flattened. Each parameter listed must be a field of the request + # message. + # required_fields - Fields that are always required for a request to be + # valid. + # request_object_method - Turns on or off the generation of a method whose + # sole parameter is a request object. Not all languages will generate + # this method. + # page_streaming - Specifies the configuration for paging. + # Describes information for generating a method which transforms a + # paging list RPC into a stream of resources. + # Consists of a request and a response. + # The request specifies request information of the list method. It + # defines which fields match the paging pattern in the request. The + # request consists of a page_size_field and a token_field. The + # page_size_field is the name of the optional field specifying the + # maximum number of elements to be returned in the response. The + # token_field is the name of the field in the request containing the + # page token. + # The response specifies response information of the list method. It + # defines which fields match the paging pattern in the response. The + # response consists of a token_field and a resources_field. The + # token_field is the name of the field in the response containing the + # next page token. The resources_field is the name of the field in the + # response containing the list of resources belonging to the page. + # retry_codes_name - Specifies the configuration for retryable codes. The + # name must be defined in interfaces.retry_codes_def. + # retry_params_name - Specifies the configuration for retry/backoff + # parameters. The name must be defined in interfaces.retry_params_def. + # field_name_patterns - Maps the field name of the request type to + # entity_name of interfaces.collections. + # Specifies the string pattern that the field must follow. + # timeout_millis - Specifies the default timeout for a non-retrying call. If + # the call is retrying, refer to retry_params_name instead. + methods: + - name: GetAgent + flattening: + groups: + - parameters: + - parent + required_fields: + - parent + request_object_method: false + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: project + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: SearchAgents + flattening: + groups: + - parameters: + - parent + required_fields: + - parent + request_object_method: true + page_streaming: + request: + page_size_field: page_size + token_field: page_token + response: + token_field: next_page_token + resources_field: agents + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: project + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: TrainAgent + flattening: + groups: + - parameters: + - parent + required_fields: + - parent + request_object_method: false + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: project + timeout_millis: 60000 + long_running: + # LINT.IfChange(train_agent_long_running_operation) + return_type: google.protobuf.Empty + metadata_type: google.protobuf.Struct + # LINT.ThenChange() + initial_poll_delay_millis: 500 + poll_delay_multiplier: 1.5 + max_poll_delay_millis: 5000 + total_poll_timeout_millis: 300000 + resource_name_treatment: STATIC_TYPES + - name: ExportAgent + flattening: + groups: + - parameters: + - parent + required_fields: + - parent + request_object_method: true + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: project + timeout_millis: 60000 + long_running: + # LINT.IfChange(export_agent_long_running_operation) + return_type: google.cloud.dialogflow.v2.ExportAgentResponse + metadata_type: google.protobuf.Struct + # LINT.ThenChange() + initial_poll_delay_millis: 500 + poll_delay_multiplier: 1.5 + max_poll_delay_millis: 5000 + total_poll_timeout_millis: 300000 + resource_name_treatment: STATIC_TYPES + - name: ImportAgent + required_fields: + - parent + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + parent: project + timeout_millis: 60000 + long_running: + # LINT.IfChange(import_agent_long_running_operation) + return_type: google.protobuf.Empty + metadata_type: google.protobuf.Struct + # LINT.ThenChange() + initial_poll_delay_millis: 500 + poll_delay_multiplier: 1.5 + max_poll_delay_millis: 5000 + total_poll_timeout_millis: 300000 + resource_name_treatment: STATIC_TYPES + - name: RestoreAgent + + required_fields: + - parent + request_object_method: true + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: project + timeout_millis: 60000 + long_running: + # LINT.IfChange(restore_agent_long_running_operation) + return_type: google.protobuf.Empty + metadata_type: google.protobuf.Struct + # LINT.ThenChange() + initial_poll_delay_millis: 500 + poll_delay_multiplier: 1.5 + max_poll_delay_millis: 5000 + total_poll_timeout_millis: 300000 + resource_name_treatment: STATIC_TYPES + # The fully qualified name of the API interface. +- name: google.cloud.dialogflow.v2.Contexts + # A list of resource collection configurations. + # Consists of a name_pattern and an entity_name. + # The name_pattern is a pattern to describe the names of the resources of this + # collection, using the platform's conventions for URI patterns. A generator + # may use this to generate methods to compose and decompose such names. The + # pattern should use named placeholders as in `shelves/{shelf}/books/{book}`; + # those will be taken as hints for the parameter names of the generated + # methods. If empty, no name methods are generated. + # The entity_name is the name to be used as a basis for generated methods and + # classes. + collections: + - name_pattern: projects/{project}/agent/sessions/{session} + entity_name: session + - name_pattern: projects/{project}/agent/sessions/{session}/contexts/{context} + entity_name: context + # Definition for retryable codes. + retry_codes_def: + - name: idempotent + retry_codes: + - UNAVAILABLE + - DEADLINE_EXCEEDED + - name: non_idempotent + retry_codes: [] + # Definition for retry/backoff parameters. + retry_params_def: + - name: default + initial_retry_delay_millis: 100 + retry_delay_multiplier: 1.3 + max_retry_delay_millis: 60000 + initial_rpc_timeout_millis: 20000 + rpc_timeout_multiplier: 1 + max_rpc_timeout_millis: 20000 + total_timeout_millis: 600000 + # A list of method configurations. + # Common properties: + # name - The simple name of the method. + # flattening - Specifies the configuration for parameter flattening. + # Describes the parameter groups for which a generator should produce + # method overloads which allow a client to directly pass request message + # fields as method parameters. This information may or may not be used, + # depending on the target language. + # Consists of groups, which each represent a list of parameters to be + # flattened. Each parameter listed must be a field of the request + # message. + # required_fields - Fields that are always required for a request to be + # valid. + # request_object_method - Turns on or off the generation of a method whose + # sole parameter is a request object. Not all languages will generate + # this method. + # page_streaming - Specifies the configuration for paging. + # Describes information for generating a method which transforms a + # paging list RPC into a stream of resources. + # Consists of a request and a response. + # The request specifies request information of the list method. It + # defines which fields match the paging pattern in the request. The + # request consists of a page_size_field and a token_field. The + # page_size_field is the name of the optional field specifying the + # maximum number of elements to be returned in the response. The + # token_field is the name of the field in the request containing the + # page token. + # The response specifies response information of the list method. It + # defines which fields match the paging pattern in the response. The + # response consists of a token_field and a resources_field. The + # token_field is the name of the field in the response containing the + # next page token. The resources_field is the name of the field in the + # response containing the list of resources belonging to the page. + # retry_codes_name - Specifies the configuration for retryable codes. The + # name must be defined in interfaces.retry_codes_def. + # retry_params_name - Specifies the configuration for retry/backoff + # parameters. The name must be defined in interfaces.retry_params_def. + # field_name_patterns - Maps the field name of the request type to + # entity_name of interfaces.collections. + # Specifies the string pattern that the field must follow. + # timeout_millis - Specifies the default timeout for a non-retrying call. If + # the call is retrying, refer to retry_params_name instead. + methods: + - name: ListContexts + flattening: + groups: + - parameters: + - parent + required_fields: + - parent + request_object_method: true + page_streaming: + request: + page_size_field: page_size + token_field: page_token + response: + token_field: next_page_token + resources_field: contexts + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: session + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: GetContext + flattening: + groups: + - parameters: + - name + required_fields: + - name + request_object_method: false + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + name: context + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: CreateContext + flattening: + groups: + - parameters: + - parent + - context + required_fields: + - parent + - context + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + parent: session + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: UpdateContext + flattening: + groups: + - parameters: + - context + required_fields: + - context + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + context.name: context + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: DeleteContext + flattening: + groups: + - parameters: + - name + required_fields: + - name + request_object_method: false + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + name: context + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: DeleteAllContexts + flattening: + groups: + - parameters: + - parent + required_fields: + - parent + request_object_method: false + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: session + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + # The fully qualified name of the API interface. +- name: google.cloud.dialogflow.v2.EntityTypes + # A list of resource collection configurations. + # Consists of a name_pattern and an entity_name. + # The name_pattern is a pattern to describe the names of the resources of this + # collection, using the platform's conventions for URI patterns. A generator + # may use this to generate methods to compose and decompose such names. The + # pattern should use named placeholders as in `shelves/{shelf}/books/{book}`; + # those will be taken as hints for the parameter names of the generated + # methods. If empty, no name methods are generated. + # The entity_name is the name to be used as a basis for generated methods and + # classes. + collections: + - name_pattern: projects/{project}/agent + entity_name: project_agent + - name_pattern: projects/{project}/agent/entityTypes/{entity_type} + entity_name: entity_type + # Definition for retryable codes. + retry_codes_def: + - name: idempotent + retry_codes: + - UNAVAILABLE + - DEADLINE_EXCEEDED + - name: non_idempotent + retry_codes: [] + # Definition for retry/backoff parameters. + retry_params_def: + - name: default + initial_retry_delay_millis: 100 + retry_delay_multiplier: 1.3 + max_retry_delay_millis: 60000 + initial_rpc_timeout_millis: 20000 + rpc_timeout_multiplier: 1 + max_rpc_timeout_millis: 20000 + total_timeout_millis: 600000 + # A list of method configurations. + # Common properties: + # name - The simple name of the method. + # flattening - Specifies the configuration for parameter flattening. + # Describes the parameter groups for which a generator should produce + # method overloads which allow a client to directly pass request message + # fields as method parameters. This information may or may not be used, + # depending on the target language. + # Consists of groups, which each represent a list of parameters to be + # flattened. Each parameter listed must be a field of the request + # message. + # required_fields - Fields that are always required for a request to be + # valid. + # request_object_method - Turns on or off the generation of a method whose + # sole parameter is a request object. Not all languages will generate + # this method. + # page_streaming - Specifies the configuration for paging. + # Describes information for generating a method which transforms a + # paging list RPC into a stream of resources. + # Consists of a request and a response. + # The request specifies request information of the list method. It + # defines which fields match the paging pattern in the request. The + # request consists of a page_size_field and a token_field. The + # page_size_field is the name of the optional field specifying the + # maximum number of elements to be returned in the response. The + # token_field is the name of the field in the request containing the + # page token. + # The response specifies response information of the list method. It + # defines which fields match the paging pattern in the response. The + # response consists of a token_field and a resources_field. The + # token_field is the name of the field in the response containing the + # next page token. The resources_field is the name of the field in the + # response containing the list of resources belonging to the page. + # retry_codes_name - Specifies the configuration for retryable codes. The + # name must be defined in interfaces.retry_codes_def. + # retry_params_name - Specifies the configuration for retry/backoff + # parameters. The name must be defined in interfaces.retry_params_def. + # field_name_patterns - Maps the field name of the request type to + # entity_name of interfaces.collections. + # Specifies the string pattern that the field must follow. + # timeout_millis - Specifies the default timeout for a non-retrying call. If + # the call is retrying, refer to retry_params_name instead. + methods: + - name: ListEntityTypes + flattening: + groups: + - parameters: + - parent + - parameters: + - parent + - language_code + required_fields: + - parent + request_object_method: true + page_streaming: + request: + page_size_field: page_size + token_field: page_token + response: + token_field: next_page_token + resources_field: entity_types + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: project_agent + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: GetEntityType + flattening: + groups: + - parameters: + - name + - parameters: + - name + - language_code + required_fields: + - name + request_object_method: true + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + name: entity_type + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: CreateEntityType + flattening: + groups: + - parameters: + - parent + - entity_type + - parameters: + - parent + - entity_type + - language_code + required_fields: + - parent + - entity_type + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + parent: project_agent + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: UpdateEntityType + flattening: + groups: + - parameters: + - entity_type + - parameters: + - entity_type + - language_code + required_fields: + - entity_type + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + entity_type.name: entity_type + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: DeleteEntityType + flattening: + groups: + - parameters: + - name + required_fields: + - name + request_object_method: false + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + name: entity_type + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: BatchUpdateEntityTypes + required_fields: + - parent + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + parent: project_agent + timeout_millis: 60000 + long_running: + # LINT.IfChange(batch_update_entity_types_long_running_operation) + return_type: google.cloud.dialogflow.v2.BatchUpdateEntityTypesResponse + metadata_type: google.protobuf.Struct + # LINT.ThenChange() + initial_poll_delay_millis: 500 + poll_delay_multiplier: 1.5 + max_poll_delay_millis: 5000 + total_poll_timeout_millis: 300000 + resource_name_treatment: STATIC_TYPES + - name: BatchDeleteEntityTypes + flattening: + groups: + - parameters: + - parent + - entity_type_names + required_fields: + - parent + - entity_type_names + request_object_method: true + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: project_agent + timeout_millis: 60000 + long_running: + # LINT.IfChange(batch_delete_entity_types_long_running_operation) + return_type: google.protobuf.Empty + metadata_type: google.protobuf.Struct + # LINT.ThenChange() + initial_poll_delay_millis: 500 + poll_delay_multiplier: 1.5 + max_poll_delay_millis: 5000 + total_poll_timeout_millis: 300000 + resource_name_treatment: STATIC_TYPES + - name: BatchCreateEntities + flattening: + groups: + - parameters: + - parent + - entities + - parameters: + - parent + - entities + - language_code + required_fields: + - parent + - entities + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + parent: entity_type + timeout_millis: 60000 + long_running: + # LINT.IfChange(batch_create_entities_long_running_operation) + return_type: google.protobuf.Empty + metadata_type: google.protobuf.Struct + # LINT.ThenChange() + initial_poll_delay_millis: 500 + poll_delay_multiplier: 1.5 + max_poll_delay_millis: 5000 + total_poll_timeout_millis: 300000 + resource_name_treatment: STATIC_TYPES + - name: BatchUpdateEntities + flattening: + groups: + - parameters: + - parent + - entities + - parameters: + - parent + - entities + - language_code + required_fields: + - parent + - entities + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + parent: entity_type + timeout_millis: 60000 + long_running: + # LINT.IfChange(batch_update_entities_long_running_operation) + return_type: google.protobuf.Empty + metadata_type: google.protobuf.Struct + # LINT.ThenChange() + initial_poll_delay_millis: 500 + poll_delay_multiplier: 1.5 + max_poll_delay_millis: 5000 + total_poll_timeout_millis: 300000 + resource_name_treatment: STATIC_TYPES + - name: BatchDeleteEntities + flattening: + groups: + - parameters: + - parent + - entity_values + - parameters: + - parent + - entity_values + - language_code + required_fields: + - parent + - entity_values + request_object_method: true + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: entity_type + timeout_millis: 60000 + long_running: + # LINT.IfChange(batch_delete_entities_long_running_operation) + return_type: google.protobuf.Empty + metadata_type: google.protobuf.Struct + # LINT.ThenChange() + initial_poll_delay_millis: 500 + poll_delay_multiplier: 1.5 + max_poll_delay_millis: 5000 + total_poll_timeout_millis: 300000 + resource_name_treatment: STATIC_TYPES + # The fully qualified name of the API interface. +- name: google.cloud.dialogflow.v2.Intents + # A list of resource collection configurations. + # Consists of a name_pattern and an entity_name. + # The name_pattern is a pattern to describe the names of the resources of this + # collection, using the platform's conventions for URI patterns. A generator + # may use this to generate methods to compose and decompose such names. The + # pattern should use named placeholders as in `shelves/{shelf}/books/{book}`; + # those will be taken as hints for the parameter names of the generated + # methods. If empty, no name methods are generated. + # The entity_name is the name to be used as a basis for generated methods and + # classes. + collections: + - name_pattern: projects/{project}/agent + entity_name: project_agent + - name_pattern: projects/{project}/agent/intents/{intent} + entity_name: intent + - name_pattern: projects/{project}/agents/{agent} + entity_name: agent + # Definition for retryable codes. + retry_codes_def: + - name: idempotent + retry_codes: + - UNAVAILABLE + - DEADLINE_EXCEEDED + - name: non_idempotent + retry_codes: [] + # Definition for retry/backoff parameters. + retry_params_def: + - name: default + initial_retry_delay_millis: 100 + retry_delay_multiplier: 1.3 + max_retry_delay_millis: 60000 + initial_rpc_timeout_millis: 20000 + rpc_timeout_multiplier: 1 + max_rpc_timeout_millis: 20000 + total_timeout_millis: 600000 + # A list of method configurations. + # Common properties: + # name - The simple name of the method. + # flattening - Specifies the configuration for parameter flattening. + # Describes the parameter groups for which a generator should produce + # method overloads which allow a client to directly pass request message + # fields as method parameters. This information may or may not be used, + # depending on the target language. + # Consists of groups, which each represent a list of parameters to be + # flattened. Each parameter listed must be a field of the request + # message. + # required_fields - Fields that are always required for a request to be + # valid. + # request_object_method - Turns on or off the generation of a method whose + # sole parameter is a request object. Not all languages will generate + # this method. + # page_streaming - Specifies the configuration for paging. + # Describes information for generating a method which transforms a + # paging list RPC into a stream of resources. + # Consists of a request and a response. + # The request specifies request information of the list method. It + # defines which fields match the paging pattern in the request. The + # request consists of a page_size_field and a token_field. The + # page_size_field is the name of the optional field specifying the + # maximum number of elements to be returned in the response. The + # token_field is the name of the field in the request containing the + # page token. + # The response specifies response information of the list method. It + # defines which fields match the paging pattern in the response. The + # response consists of a token_field and a resources_field. The + # token_field is the name of the field in the response containing the + # next page token. The resources_field is the name of the field in the + # response containing the list of resources belonging to the page. + # retry_codes_name - Specifies the configuration for retryable codes. The + # name must be defined in interfaces.retry_codes_def. + # retry_params_name - Specifies the configuration for retry/backoff + # parameters. The name must be defined in interfaces.retry_params_def. + # field_name_patterns - Maps the field name of the request type to + # entity_name of interfaces.collections. + # Specifies the string pattern that the field must follow. + # timeout_millis - Specifies the default timeout for a non-retrying call. If + # the call is retrying, refer to retry_params_name instead. + methods: + - name: ListIntents + flattening: + groups: + - parameters: + - parent + - parameters: + - parent + - language_code + required_fields: + - parent + request_object_method: true + page_streaming: + request: + page_size_field: page_size + token_field: page_token + response: + token_field: next_page_token + resources_field: intents + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: project_agent + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: GetIntent + flattening: + groups: + - parameters: + - name + - parameters: + - name + - language_code + required_fields: + - name + request_object_method: true + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + name: intent + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: CreateIntent + flattening: + groups: + - parameters: + - parent + - intent + - parameters: + - parent + - intent + - language_code + required_fields: + - parent + - intent + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + parent: project_agent + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: UpdateIntent + flattening: + groups: + - parameters: + - intent + - language_code + - parameters: + - intent + - language_code + - update_mask + required_fields: + - intent + - language_code + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + intent.name: intent + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: DeleteIntent + flattening: + groups: + - parameters: + - name + required_fields: + - name + request_object_method: false + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + name: intent + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: BatchUpdateIntents + required_fields: + - parent + - language_code + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + parent: project_agent + timeout_millis: 60000 + long_running: + # LINT.IfChange(batch_update_intents_long_running_operation) + return_type: google.cloud.dialogflow.v2.BatchUpdateIntentsResponse + metadata_type: google.protobuf.Struct + # LINT.ThenChange() + initial_poll_delay_millis: 500 + poll_delay_multiplier: 1.5 + max_poll_delay_millis: 5000 + total_poll_timeout_millis: 300000 + resource_name_treatment: STATIC_TYPES + - name: BatchDeleteIntents + flattening: + groups: + - parameters: + - parent + - intents + required_fields: + - parent + - intents + request_object_method: true + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: project_agent + timeout_millis: 60000 + long_running: + # LINT.IfChange(batch_delete_intents_long_running_operation) + return_type: google.protobuf.Empty + metadata_type: google.protobuf.Struct + # LINT.ThenChange() + initial_poll_delay_millis: 500 + poll_delay_multiplier: 1.5 + max_poll_delay_millis: 5000 + total_poll_timeout_millis: 300000 + resource_name_treatment: STATIC_TYPES + # The fully qualified name of the API interface. +- name: google.cloud.dialogflow.v2.SessionEntityTypes + # A list of resource collection configurations. + # Consists of a name_pattern and an entity_name. + # The name_pattern is a pattern to describe the names of the resources of this + # collection, using the platform's conventions for URI patterns. A generator + # may use this to generate methods to compose and decompose such names. The + # pattern should use named placeholders as in `shelves/{shelf}/books/{book}`; + # those will be taken as hints for the parameter names of the generated + # methods. If empty, no name methods are generated. + # The entity_name is the name to be used as a basis for generated methods and + # classes. + collections: + - name_pattern: projects/{project}/agent/sessions/{session} + entity_name: session + - name_pattern: projects/{project}/agent/sessions/{session}/entityTypes/{entity_type} + entity_name: session_entity_type + # Definition for retryable codes. + retry_codes_def: + - name: idempotent + retry_codes: + - UNAVAILABLE + - DEADLINE_EXCEEDED + - name: non_idempotent + retry_codes: [] + # Definition for retry/backoff parameters. + retry_params_def: + - name: default + initial_retry_delay_millis: 100 + retry_delay_multiplier: 1.3 + max_retry_delay_millis: 60000 + initial_rpc_timeout_millis: 20000 + rpc_timeout_multiplier: 1 + max_rpc_timeout_millis: 20000 + total_timeout_millis: 600000 + # A list of method configurations. + # Common properties: + # name - The simple name of the method. + # flattening - Specifies the configuration for parameter flattening. + # Describes the parameter groups for which a generator should produce + # method overloads which allow a client to directly pass request message + # fields as method parameters. This information may or may not be used, + # depending on the target language. + # Consists of groups, which each represent a list of parameters to be + # flattened. Each parameter listed must be a field of the request + # message. + # required_fields - Fields that are always required for a request to be + # valid. + # request_object_method - Turns on or off the generation of a method whose + # sole parameter is a request object. Not all languages will generate + # this method. + # page_streaming - Specifies the configuration for paging. + # Describes information for generating a method which transforms a + # paging list RPC into a stream of resources. + # Consists of a request and a response. + # The request specifies request information of the list method. It + # defines which fields match the paging pattern in the request. The + # request consists of a page_size_field and a token_field. The + # page_size_field is the name of the optional field specifying the + # maximum number of elements to be returned in the response. The + # token_field is the name of the field in the request containing the + # page token. + # The response specifies response information of the list method. It + # defines which fields match the paging pattern in the response. The + # response consists of a token_field and a resources_field. The + # token_field is the name of the field in the response containing the + # next page token. The resources_field is the name of the field in the + # response containing the list of resources belonging to the page. + # retry_codes_name - Specifies the configuration for retryable codes. The + # name must be defined in interfaces.retry_codes_def. + # retry_params_name - Specifies the configuration for retry/backoff + # parameters. The name must be defined in interfaces.retry_params_def. + # field_name_patterns - Maps the field name of the request type to + # entity_name of interfaces.collections. + # Specifies the string pattern that the field must follow. + # timeout_millis - Specifies the default timeout for a non-retrying call. If + # the call is retrying, refer to retry_params_name instead. + methods: + - name: ListSessionEntityTypes + flattening: + groups: + - parameters: + - parent + required_fields: + - parent + request_object_method: true + page_streaming: + request: + page_size_field: page_size + token_field: page_token + response: + token_field: next_page_token + resources_field: session_entity_types + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + parent: session + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: GetSessionEntityType + flattening: + groups: + - parameters: + - name + required_fields: + - name + request_object_method: false + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + name: session_entity_type + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: CreateSessionEntityType + flattening: + groups: + - parameters: + - parent + - session_entity_type + required_fields: + - parent + - session_entity_type + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + parent: session + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: UpdateSessionEntityType + flattening: + groups: + - parameters: + - session_entity_type + required_fields: + - session_entity_type + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + session_entity_type.name: session_entity_type + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + - name: DeleteSessionEntityType + flattening: + groups: + - parameters: + - name + required_fields: + - name + request_object_method: false + retry_codes_name: idempotent + retry_params_name: default + field_name_patterns: + name: session_entity_type + timeout_millis: 60000 + resource_name_treatment: STATIC_TYPES + # The fully qualified name of the API interface. +- name: google.cloud.dialogflow.v2.Sessions + # A list of resource collection configurations. + # Consists of a name_pattern and an entity_name. + # The name_pattern is a pattern to describe the names of the resources of this + # collection, using the platform's conventions for URI patterns. A generator + # may use this to generate methods to compose and decompose such names. The + # pattern should use named placeholders as in `shelves/{shelf}/books/{book}`; + # those will be taken as hints for the parameter names of the generated + # methods. If empty, no name methods are generated. + # The entity_name is the name to be used as a basis for generated methods and + # classes. + collections: + - name_pattern: projects/{project}/agent/sessions/{session} + entity_name: session + # Definition for retryable codes. + retry_codes_def: + - name: idempotent + retry_codes: + - UNAVAILABLE + - DEADLINE_EXCEEDED + - name: non_idempotent + retry_codes: [] + # Definition for retry/backoff parameters. + retry_params_def: + - name: default + initial_retry_delay_millis: 100 + retry_delay_multiplier: 1.3 + max_retry_delay_millis: 60000 + initial_rpc_timeout_millis: 20000 + rpc_timeout_multiplier: 1 + max_rpc_timeout_millis: 20000 + total_timeout_millis: 600000 + # A list of method configurations. + # Common properties: + # name - The simple name of the method. + # flattening - Specifies the configuration for parameter flattening. + # Describes the parameter groups for which a generator should produce + # method overloads which allow a client to directly pass request message + # fields as method parameters. This information may or may not be used, + # depending on the target language. + # Consists of groups, which each represent a list of parameters to be + # flattened. Each parameter listed must be a field of the request + # message. + # required_fields - Fields that are always required for a request to be + # valid. + # request_object_method - Turns on or off the generation of a method whose + # sole parameter is a request object. Not all languages will generate + # this method. + # page_streaming - Specifies the configuration for paging. + # Describes information for generating a method which transforms a + # paging list RPC into a stream of resources. + # Consists of a request and a response. + # The request specifies request information of the list method. It + # defines which fields match the paging pattern in the request. The + # request consists of a page_size_field and a token_field. The + # page_size_field is the name of the optional field specifying the + # maximum number of elements to be returned in the response. The + # token_field is the name of the field in the request containing the + # page token. + # The response specifies response information of the list method. It + # defines which fields match the paging pattern in the response. The + # response consists of a token_field and a resources_field. The + # token_field is the name of the field in the response containing the + # next page token. The resources_field is the name of the field in the + # response containing the list of resources belonging to the page. + # retry_codes_name - Specifies the configuration for retryable codes. The + # name must be defined in interfaces.retry_codes_def. + # retry_params_name - Specifies the configuration for retry/backoff + # parameters. The name must be defined in interfaces.retry_params_def. + # field_name_patterns - Maps the field name of the request type to + # entity_name of interfaces.collections. + # Specifies the string pattern that the field must follow. + # timeout_millis - Specifies the default timeout for a non-retrying call. If + # the call is retrying, refer to retry_params_name instead. + methods: + - name: DetectIntent + flattening: + groups: + - parameters: + - session + - query_input + required_fields: + - session + - query_input + request_object_method: true + retry_codes_name: non_idempotent + retry_params_name: default + field_name_patterns: + session: session + timeout_millis: 220000 + resource_name_treatment: STATIC_TYPES + - name: StreamingDetectIntent + required_fields: + - session + - query_input + request_object_method: false + retry_codes_name: non_idempotent + retry_params_name: default + timeout_millis: 220000 +resource_name_generation: +- message_name: GetAgentRequest + field_entity_map: + parent: project +- message_name: SearchAgentsRequest + field_entity_map: + parent: project +- message_name: TrainAgentRequest + field_entity_map: + parent: project +- message_name: ExportAgentRequest + field_entity_map: + parent: project +- message_name: ImportAgentRequest + field_entity_map: + parent: project +- message_name: RestoreAgentRequest + field_entity_map: + parent: project +- message_name: ListContextsRequest + field_entity_map: + parent: session +- message_name: GetContextRequest + field_entity_map: + name: context +- message_name: CreateContextRequest + field_entity_map: + parent: session +- message_name: Context + field_entity_map: + name: context +- message_name: DeleteContextRequest + field_entity_map: + name: context +- message_name: DeleteAllContextsRequest + field_entity_map: + parent: session +- message_name: ListEntityTypesRequest + field_entity_map: + parent: project_agent +- message_name: GetEntityTypeRequest + field_entity_map: + name: entity_type +- message_name: CreateEntityTypeRequest + field_entity_map: + parent: project_agent +- message_name: EntityType + field_entity_map: + name: entity_type +- message_name: DeleteEntityTypeRequest + field_entity_map: + name: entity_type +- message_name: BatchUpdateEntityTypesRequest + field_entity_map: + parent: project_agent +- message_name: BatchDeleteEntityTypesRequest + field_entity_map: + parent: project_agent +- message_name: BatchCreateEntitiesRequest + field_entity_map: + parent: entity_type +- message_name: BatchUpdateEntitiesRequest + field_entity_map: + parent: entity_type +- message_name: BatchDeleteEntitiesRequest + field_entity_map: + parent: entity_type +- message_name: ListIntentsRequest + field_entity_map: + parent: project_agent +- message_name: GetIntentRequest + field_entity_map: + name: intent +- message_name: CreateIntentRequest + field_entity_map: + parent: project_agent +- message_name: Intent + field_entity_map: + name: intent +- message_name: DeleteIntentRequest + field_entity_map: + name: intent +- message_name: BatchUpdateIntentsRequest + field_entity_map: + parent: project_agent +- message_name: BatchDeleteIntentsRequest + field_entity_map: + parent: project_agent +- message_name: ListSessionEntityTypesRequest + field_entity_map: + parent: session +- message_name: GetSessionEntityTypeRequest + field_entity_map: + name: session_entity_type +- message_name: CreateSessionEntityTypeRequest + field_entity_map: + parent: session +- message_name: SessionEntityType + field_entity_map: + name: session_entity_type +- message_name: DeleteSessionEntityTypeRequest + field_entity_map: + name: session_entity_type +- message_name: DetectIntentRequest + field_entity_map: + session: session diff --git a/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/entity_type.proto b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/entity_type.proto new file mode 100644 index 00000000..ce36c716 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/entity_type.proto @@ -0,0 +1,419 @@ +// Copyright 2018 Google Inc. +// +// 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. + +syntax = "proto3"; + +package google.cloud.dialogflow.v2; + +import "google/api/annotations.proto"; +import "google/longrunning/operations.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/struct.proto"; + +option cc_enable_arenas = true; +option csharp_namespace = "Google.Cloud.Dialogflow.V2"; +option go_package = "google.golang.org/genproto/googleapis/cloud/dialogflow/v2;dialogflow"; +option java_multiple_files = true; +option java_outer_classname = "EntityTypeProto"; +option java_package = "com.google.cloud.dialogflow.v2"; +option objc_class_prefix = "DF"; + + +// Entities are extracted from user input and represent parameters that are +// meaningful to your application. For example, a date range, a proper name +// such as a geographic location or landmark, and so on. Entities represent +// actionable data for your application. +// +// When you define an entity, you can also include synonyms that all map to +// that entity. For example, "soft drink", "soda", "pop", and so on. +// +// There are three types of entities: +// +// * **System** - entities that are defined by the Dialogflow API for common +// data types such as date, time, currency, and so on. A system entity is +// represented by the `EntityType` type. +// +// * **Developer** - entities that are defined by you that represent +// actionable data that is meaningful to your application. For example, +// you could define a `pizza.sauce` entity for red or white pizza sauce, +// a `pizza.cheese` entity for the different types of cheese on a pizza, +// a `pizza.topping` entity for different toppings, and so on. A developer +// entity is represented by the `EntityType` type. +// +// * **User** - entities that are built for an individual user such as +// favorites, preferences, playlists, and so on. A user entity is +// represented by the [SessionEntityType][google.cloud.dialogflow.v2.SessionEntityType] type. +// +// For more information about entity types, see the +// [Dialogflow documentation](https://dialogflow.com/docs/entities). +service EntityTypes { + // Returns the list of all entity types in the specified agent. + rpc ListEntityTypes(ListEntityTypesRequest) returns (ListEntityTypesResponse) { + option (google.api.http) = { + get: "/v2/{parent=projects/*/agent}/entityTypes" + }; + } + + // Retrieves the specified entity type. + rpc GetEntityType(GetEntityTypeRequest) returns (EntityType) { + option (google.api.http) = { + get: "/v2/{name=projects/*/agent/entityTypes/*}" + }; + } + + // Creates an entity type in the specified agent. + rpc CreateEntityType(CreateEntityTypeRequest) returns (EntityType) { + option (google.api.http) = { + post: "/v2/{parent=projects/*/agent}/entityTypes" + body: "entity_type" + }; + } + + // Updates the specified entity type. + rpc UpdateEntityType(UpdateEntityTypeRequest) returns (EntityType) { + option (google.api.http) = { + patch: "/v2/{entity_type.name=projects/*/agent/entityTypes/*}" + body: "entity_type" + }; + } + + // Deletes the specified entity type. + rpc DeleteEntityType(DeleteEntityTypeRequest) returns (google.protobuf.Empty) { + option (google.api.http) = { + delete: "/v2/{name=projects/*/agent/entityTypes/*}" + }; + } + + // Updates/Creates multiple entity types in the specified agent. + // + // Operation + rpc BatchUpdateEntityTypes(BatchUpdateEntityTypesRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v2/{parent=projects/*/agent}/entityTypes:batchUpdate" + body: "*" + }; + } + + // Deletes entity types in the specified agent. + // + // Operation + rpc BatchDeleteEntityTypes(BatchDeleteEntityTypesRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v2/{parent=projects/*/agent}/entityTypes:batchDelete" + body: "*" + }; + } + + // Creates multiple new entities in the specified entity type (extends the + // existing collection of entries). + // + // Operation + rpc BatchCreateEntities(BatchCreateEntitiesRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v2/{parent=projects/*/agent/entityTypes/*}/entities:batchCreate" + body: "*" + }; + } + + // Updates entities in the specified entity type (replaces the existing + // collection of entries). + // + // Operation + rpc BatchUpdateEntities(BatchUpdateEntitiesRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v2/{parent=projects/*/agent/entityTypes/*}/entities:batchUpdate" + body: "*" + }; + } + + // Deletes entities in the specified entity type. + // + // Operation + rpc BatchDeleteEntities(BatchDeleteEntitiesRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v2/{parent=projects/*/agent/entityTypes/*}/entities:batchDelete" + body: "*" + }; + } +} + +// Represents an entity type. +// Entity types serve as a tool for extracting parameter values from natural +// language queries. +message EntityType { + // Optional. Represents an entity. + message Entity { + // Required. + // For `KIND_MAP` entity types: + // A canonical name to be used in place of synonyms. + // For `KIND_LIST` entity types: + // A string that can contain references to other entity types (with or + // without aliases). + string value = 1; + + // Required. A collection of synonyms. For `KIND_LIST` entity types this + // must contain exactly one synonym equal to `value`. + repeated string synonyms = 2; + } + + // Represents kinds of entities. + enum Kind { + // Not specified. This value should be never used. + KIND_UNSPECIFIED = 0; + + // Map entity types allow mapping of a group of synonyms to a canonical + // value. + KIND_MAP = 1; + + // List entity types contain a set of entries that do not map to canonical + // values. However, list entity types can contain references to other entity + // types (with or without aliases). + KIND_LIST = 2; + } + + // Represents different entity type expansion modes. Automated expansion + // allows an agent to recognize values that have not been explicitly listed in + // the entity (for example, new kinds of shopping list items). + enum AutoExpansionMode { + // Auto expansion disabled for the entity. + AUTO_EXPANSION_MODE_UNSPECIFIED = 0; + + // Allows an agent to recognize values that have not been explicitly + // listed in the entity. + AUTO_EXPANSION_MODE_DEFAULT = 1; + } + + // Required for all methods except `create` (`create` populates the name + // automatically. + // The unique identifier of the entity type. Format: + // `projects//agent/entityTypes/`. + string name = 1; + + // Required. The name of the entity. + string display_name = 2; + + // Required. Indicates the kind of entity type. + Kind kind = 3; + + // Optional. Indicates whether the entity type can be automatically + // expanded. + AutoExpansionMode auto_expansion_mode = 4; + + // Optional. The collection of entities associated with the entity type. + repeated Entity entities = 6; +} + +// The request message for [EntityTypes.ListEntityTypes][google.cloud.dialogflow.v2.EntityTypes.ListEntityTypes]. +message ListEntityTypesRequest { + // Required. The agent to list all entity types from. + // Format: `projects//agent`. + string parent = 1; + + // Optional. The language to list entity synonyms for. If not specified, + // the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 2; + + // Optional. The maximum number of items to return in a single page. By + // default 100 and at most 1000. + int32 page_size = 3; + + // Optional. The next_page_token value returned from a previous list request. + string page_token = 4; +} + +// The response message for [EntityTypes.ListEntityTypes][google.cloud.dialogflow.v2.EntityTypes.ListEntityTypes]. +message ListEntityTypesResponse { + // The list of agent entity types. There will be a maximum number of items + // returned based on the page_size field in the request. + repeated EntityType entity_types = 1; + + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + string next_page_token = 2; +} + +// The request message for [EntityTypes.GetEntityType][google.cloud.dialogflow.v2.EntityTypes.GetEntityType]. +message GetEntityTypeRequest { + // Required. The name of the entity type. + // Format: `projects//agent/entityTypes/`. + string name = 1; + + // Optional. The language to retrieve entity synonyms for. If not specified, + // the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 2; +} + +// The request message for [EntityTypes.CreateEntityType][google.cloud.dialogflow.v2.EntityTypes.CreateEntityType]. +message CreateEntityTypeRequest { + // Required. The agent to create a entity type for. + // Format: `projects//agent`. + string parent = 1; + + // Required. The entity type to create. + EntityType entity_type = 2; + + // Optional. The language of entity synonyms defined in `entity_type`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 3; +} + +// The request message for [EntityTypes.UpdateEntityType][google.cloud.dialogflow.v2.EntityTypes.UpdateEntityType]. +message UpdateEntityTypeRequest { + // Required. The entity type to update. + // Format: `projects//agent/entityTypes/`. + EntityType entity_type = 1; + + // Optional. The language of entity synonyms defined in `entity_type`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 2; + + // Optional. The mask to control which fields get updated. + google.protobuf.FieldMask update_mask = 3; +} + +// The request message for [EntityTypes.DeleteEntityType][google.cloud.dialogflow.v2.EntityTypes.DeleteEntityType]. +message DeleteEntityTypeRequest { + // Required. The name of the entity type to delete. + // Format: `projects//agent/entityTypes/`. + string name = 1; +} + +// The request message for [EntityTypes.BatchUpdateEntityTypes][google.cloud.dialogflow.v2.EntityTypes.BatchUpdateEntityTypes]. +message BatchUpdateEntityTypesRequest { + // Required. The name of the agent to update or create entity types in. + // Format: `projects//agent`. + string parent = 1; + + // Required. The source of the entity type batch. + // + // For each entity type in the batch: + // * If `name` is specified, we update an existing entity type. + // * If `name` is not specified, we create a new entity type. + oneof entity_type_batch { + // The URI to a Google Cloud Storage file containing entity types to update + // or create. The file format can either be a serialized proto (of + // EntityBatch type) or a JSON object. Note: The URI must start with + // "gs://". + string entity_type_batch_uri = 2; + + // The collection of entity type to update or create. + EntityTypeBatch entity_type_batch_inline = 3; + } + + // Optional. The language of entity synonyms defined in `entity_types`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 4; + + // Optional. The mask to control which fields get updated. + google.protobuf.FieldMask update_mask = 5; +} + +// The response message for [EntityTypes.BatchUpdateEntityTypes][google.cloud.dialogflow.v2.EntityTypes.BatchUpdateEntityTypes]. +message BatchUpdateEntityTypesResponse { + // The collection of updated or created entity types. + repeated EntityType entity_types = 1; +} + +// The request message for [EntityTypes.BatchDeleteEntityTypes][google.cloud.dialogflow.v2.EntityTypes.BatchDeleteEntityTypes]. +message BatchDeleteEntityTypesRequest { + // Required. The name of the agent to delete all entities types for. Format: + // `projects//agent`. + string parent = 1; + + // Required. The names entity types to delete. All names must point to the + // same agent as `parent`. + repeated string entity_type_names = 2; +} + +// The request message for [EntityTypes.BatchCreateEntities][google.cloud.dialogflow.v2.EntityTypes.BatchCreateEntities]. +message BatchCreateEntitiesRequest { + // Required. The name of the entity type to create entities in. Format: + // `projects//agent/entityTypes/`. + string parent = 1; + + // Required. The collection of entities to create. + repeated EntityType.Entity entities = 2; + + // Optional. The language of entity synonyms defined in `entities`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 3; +} + +// The response message for [EntityTypes.BatchCreateEntities][google.cloud.dialogflow.v2.EntityTypes.BatchCreateEntities]. +message BatchUpdateEntitiesRequest { + // Required. The name of the entity type to update the entities in. Format: + // `projects//agent/entityTypes/`. + string parent = 1; + + // Required. The collection of new entities to replace the existing entities. + repeated EntityType.Entity entities = 2; + + // Optional. The language of entity synonyms defined in `entities`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 3; + + // Optional. The mask to control which fields get updated. + google.protobuf.FieldMask update_mask = 4; +} + +// The request message for [EntityTypes.BatchDeleteEntities][google.cloud.dialogflow.v2.EntityTypes.BatchDeleteEntities]. +message BatchDeleteEntitiesRequest { + // Required. The name of the entity type to delete entries for. Format: + // `projects//agent/entityTypes/`. + string parent = 1; + + // Required. The canonical `values` of the entities to delete. Note that + // these are not fully-qualified names, i.e. they don't start with + // `projects/`. + repeated string entity_values = 2; + + // Optional. The language of entity synonyms defined in `entities`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 3; +} + +// This message is a wrapper around a collection of entity types. +message EntityTypeBatch { + // A collection of entity types. + repeated EntityType entity_types = 1; +} diff --git a/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/intent.proto b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/intent.proto new file mode 100644 index 00000000..7d22280f --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/intent.proto @@ -0,0 +1,811 @@ +// Copyright 2018 Google Inc. +// +// 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. + +syntax = "proto3"; + +package google.cloud.dialogflow.v2; + +import "google/api/annotations.proto"; +import "google/cloud/dialogflow/v2/context.proto"; +import "google/longrunning/operations.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/struct.proto"; + +option cc_enable_arenas = true; +option csharp_namespace = "Google.Cloud.Dialogflow.V2"; +option go_package = "google.golang.org/genproto/googleapis/cloud/dialogflow/v2;dialogflow"; +option java_multiple_files = true; +option java_outer_classname = "IntentProto"; +option java_package = "com.google.cloud.dialogflow.v2"; +option objc_class_prefix = "DF"; + + +// An intent represents a mapping between input from a user and an action to +// be taken by your application. When you pass user input to the +// [DetectIntent][google.cloud.dialogflow.v2.Sessions.DetectIntent] (or +// [StreamingDetectIntent][google.cloud.dialogflow.v2.Sessions.StreamingDetectIntent]) method, the +// Dialogflow API analyzes the input and searches +// for a matching intent. If no match is found, the Dialogflow API returns a +// fallback intent (`is_fallback` = true). +// +// You can provide additional information for the Dialogflow API to use to +// match user input to an intent by adding the following to your intent. +// +// * **Contexts** - provide additional context for intent analysis. For +// example, if an intent is related to an object in your application that +// plays music, you can provide a context to determine when to match the +// intent if the user input is “turn it off”. You can include a context +// that matches the intent when there is previous user input of +// "play music", and not when there is previous user input of +// "turn on the light". +// +// * **Events** - allow for matching an intent by using an event name +// instead of user input. Your application can provide an event name and +// related parameters to the Dialogflow API to match an intent. For +// example, when your application starts, you can send a welcome event +// with a user name parameter to the Dialogflow API to match an intent with +// a personalized welcome message for the user. +// +// * **Training phrases** - provide examples of user input to train the +// Dialogflow API agent to better match intents. +// +// For more information about intents, see the +// [Dialogflow documentation](https://dialogflow.com/docs/intents). +service Intents { + // Returns the list of all intents in the specified agent. + rpc ListIntents(ListIntentsRequest) returns (ListIntentsResponse) { + option (google.api.http) = { + get: "/v2/{parent=projects/*/agent}/intents" + }; + } + + // Retrieves the specified intent. + rpc GetIntent(GetIntentRequest) returns (Intent) { + option (google.api.http) = { + get: "/v2/{name=projects/*/agent/intents/*}" + }; + } + + // Creates an intent in the specified agent. + rpc CreateIntent(CreateIntentRequest) returns (Intent) { + option (google.api.http) = { + post: "/v2/{parent=projects/*/agent}/intents" + body: "intent" + }; + } + + // Updates the specified intent. + rpc UpdateIntent(UpdateIntentRequest) returns (Intent) { + option (google.api.http) = { + patch: "/v2/{intent.name=projects/*/agent/intents/*}" + body: "intent" + }; + } + + // Deletes the specified intent. + rpc DeleteIntent(DeleteIntentRequest) returns (google.protobuf.Empty) { + option (google.api.http) = { + delete: "/v2/{name=projects/*/agent/intents/*}" + }; + } + + // Updates/Creates multiple intents in the specified agent. + // + // Operation + rpc BatchUpdateIntents(BatchUpdateIntentsRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v2/{parent=projects/*/agent}/intents:batchUpdate" + body: "*" + }; + } + + // Deletes intents in the specified agent. + // + // Operation + rpc BatchDeleteIntents(BatchDeleteIntentsRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v2/{parent=projects/*/agent}/intents:batchDelete" + body: "*" + }; + } +} + +// Represents an intent. +// Intents convert a number of user expressions or patterns into an action. An +// action is an extraction of a user command or sentence semantics. +message Intent { + // Represents an example or template that the agent is trained on. + message TrainingPhrase { + // Represents a part of a training phrase. + message Part { + // Required. The text corresponding to the example or template, + // if there are no annotations. For + // annotated examples, it is the text for one of the example's parts. + string text = 1; + + // Optional. The entity type name prefixed with `@`. This field is + // required for the annotated part of the text and applies only to + // examples. + string entity_type = 2; + + // Optional. The parameter name for the value extracted from the + // annotated part of the example. + string alias = 3; + + // Optional. Indicates whether the text was manually annotated by the + // developer. + bool user_defined = 4; + } + + // Represents different types of training phrases. + enum Type { + // Not specified. This value should never be used. + TYPE_UNSPECIFIED = 0; + + // Examples do not contain @-prefixed entity type names, but example parts + // can be annotated with entity types. + EXAMPLE = 1; + + // Templates are not annotated with entity types, but they can contain + // @-prefixed entity type names as substrings. + TEMPLATE = 2; + } + + // Required. The unique identifier of this training phrase. + string name = 1; + + // Required. The type of the training phrase. + Type type = 2; + + // Required. The collection of training phrase parts (can be annotated). + // Fields: `entity_type`, `alias` and `user_defined` should be populated + // only for the annotated parts of the training phrase. + repeated Part parts = 3; + + // Optional. Indicates how many times this example or template was added to + // the intent. Each time a developer adds an existing sample by editing an + // intent or training, this counter is increased. + int32 times_added_count = 4; + } + + // Represents intent parameters. + message Parameter { + // The unique identifier of this parameter. + string name = 1; + + // Required. The name of the parameter. + string display_name = 2; + + // Optional. The definition of the parameter value. It can be: + // - a constant string, + // - a parameter value defined as `$parameter_name`, + // - an original parameter value defined as `$parameter_name.original`, + // - a parameter value from some context defined as + // `#context_name.parameter_name`. + string value = 3; + + // Optional. The default value to use when the `value` yields an empty + // result. + // Default values can be extracted from contexts by using the following + // syntax: `#context_name.parameter_name`. + string default_value = 4; + + // Optional. The name of the entity type, prefixed with `@`, that + // describes values of the parameter. If the parameter is + // required, this must be provided. + string entity_type_display_name = 5; + + // Optional. Indicates whether the parameter is required. That is, + // whether the intent cannot be completed without collecting the parameter + // value. + bool mandatory = 6; + + // Optional. The collection of prompts that the agent can present to the + // user in order to collect value for the parameter. + repeated string prompts = 7; + + // Optional. Indicates whether the parameter represents a list of values. + bool is_list = 8; + } + + // Corresponds to the `Response` field in the Dialogflow console. + message Message { + // The text response message. + message Text { + // Optional. The collection of the agent's responses. + repeated string text = 1; + } + + // The image response message. + message Image { + // Optional. The public URI to an image file. + string image_uri = 1; + + // Optional. A text description of the image to be used for accessibility, + // e.g., screen readers. + string accessibility_text = 2; + } + + // The quick replies response message. + message QuickReplies { + // Optional. The title of the collection of quick replies. + string title = 1; + + // Optional. The collection of quick replies. + repeated string quick_replies = 2; + } + + // The card response message. + message Card { + // Optional. Contains information about a button. + message Button { + // Optional. The text to show on the button. + string text = 1; + + // Optional. The text to send back to the Dialogflow API or a URI to + // open. + string postback = 2; + } + + // Optional. The title of the card. + string title = 1; + + // Optional. The subtitle of the card. + string subtitle = 2; + + // Optional. The public URI to an image file for the card. + string image_uri = 3; + + // Optional. The collection of card buttons. + repeated Button buttons = 4; + } + + // The simple response message containing speech or text. + message SimpleResponse { + // One of text_to_speech or ssml must be provided. The plain text of the + // speech output. Mutually exclusive with ssml. + string text_to_speech = 1; + + // One of text_to_speech or ssml must be provided. Structured spoken + // response to the user in the SSML format. Mutually exclusive with + // text_to_speech. + string ssml = 2; + + // Optional. The text to display. + string display_text = 3; + } + + // The collection of simple response candidates. + // This message in `QueryResult.fulfillment_messages` and + // `WebhookResponse.fulfillment_messages` should contain only one + // `SimpleResponse`. + message SimpleResponses { + // Required. The list of simple responses. + repeated SimpleResponse simple_responses = 1; + } + + // The basic card message. Useful for displaying information. + message BasicCard { + // The button object that appears at the bottom of a card. + message Button { + // Opens the given URI. + message OpenUriAction { + // Required. The HTTP or HTTPS scheme URI. + string uri = 1; + } + + // Required. The title of the button. + string title = 1; + + // Required. Action to take when a user taps on the button. + OpenUriAction open_uri_action = 2; + } + + // Optional. The title of the card. + string title = 1; + + // Optional. The subtitle of the card. + string subtitle = 2; + + // Required, unless image is present. The body text of the card. + string formatted_text = 3; + + // Optional. The image for the card. + Image image = 4; + + // Optional. The collection of card buttons. + repeated Button buttons = 5; + } + + // The suggestion chip message that the user can tap to quickly post a reply + // to the conversation. + message Suggestion { + // Required. The text shown the in the suggestion chip. + string title = 1; + } + + // The collection of suggestions. + message Suggestions { + // Required. The list of suggested replies. + repeated Suggestion suggestions = 1; + } + + // The suggestion chip message that allows the user to jump out to the app + // or website associated with this agent. + message LinkOutSuggestion { + // Required. The name of the app or site this chip is linking to. + string destination_name = 1; + + // Required. The URI of the app or site to open when the user taps the + // suggestion chip. + string uri = 2; + } + + // The card for presenting a list of options to select from. + message ListSelect { + // An item in the list. + message Item { + // Required. Additional information about this option. + SelectItemInfo info = 1; + + // Required. The title of the list item. + string title = 2; + + // Optional. The main text describing the item. + string description = 3; + + // Optional. The image to display. + Image image = 4; + } + + // Optional. The overall title of the list. + string title = 1; + + // Required. List items. + repeated Item items = 2; + } + + // The card for presenting a carousel of options to select from. + message CarouselSelect { + // An item in the carousel. + message Item { + // Required. Additional info about the option item. + SelectItemInfo info = 1; + + // Required. Title of the carousel item. + string title = 2; + + // Optional. The body text of the card. + string description = 3; + + // Optional. The image to display. + Image image = 4; + } + + // Required. Carousel items. + repeated Item items = 1; + } + + // Additional info about the select item for when it is triggered in a + // dialog. + message SelectItemInfo { + // Required. A unique key that will be sent back to the agent if this + // response is given. + string key = 1; + + // Optional. A list of synonyms that can also be used to trigger this + // item in dialog. + repeated string synonyms = 2; + } + + // Represents different platforms that a rich message can be intended for. + enum Platform { + // Not specified. + PLATFORM_UNSPECIFIED = 0; + + // Facebook. + FACEBOOK = 1; + + // Slack. + SLACK = 2; + + // Telegram. + TELEGRAM = 3; + + // Kik. + KIK = 4; + + // Skype. + SKYPE = 5; + + // Line. + LINE = 6; + + // Viber. + VIBER = 7; + + // Actions on Google. + // When using Actions on Google, you can choose one of the specific + // Intent.Message types that mention support for Actions on Google, + // or you can use the advanced Intent.Message.payload field. + // The payload field provides access to AoG features not available in the + // specific message types. + // If using the Intent.Message.payload field, it should have a structure + // similar to the JSON message shown here. For more information, see + // [Actions on Google Webhook + // Format](https://developers.google.com/actions/dialogflow/webhook) + //
{
+      //   "expectUserResponse": true,
+      //   "isSsml": false,
+      //   "noInputPrompts": [],
+      //   "richResponse": {
+      //     "items": [
+      //       {
+      //         "simpleResponse": {
+      //           "displayText": "hi",
+      //           "textToSpeech": "hello"
+      //         }
+      //       }
+      //     ],
+      //     "suggestions": [
+      //       {
+      //         "title": "Say this"
+      //       },
+      //       {
+      //         "title": "or this"
+      //       }
+      //     ]
+      //   },
+      //   "systemIntent": {
+      //     "data": {
+      //       "@type": "type.googleapis.com/google.actions.v2.OptionValueSpec",
+      //       "listSelect": {
+      //         "items": [
+      //           {
+      //             "optionInfo": {
+      //               "key": "key1",
+      //               "synonyms": [
+      //                 "key one"
+      //               ]
+      //             },
+      //             "title": "must not be empty, but unique"
+      //           },
+      //           {
+      //             "optionInfo": {
+      //               "key": "key2",
+      //               "synonyms": [
+      //                 "key two"
+      //               ]
+      //             },
+      //             "title": "must not be empty, but unique"
+      //           }
+      //         ]
+      //       }
+      //     },
+      //     "intent": "actions.intent.OPTION"
+      //   }
+      // }
+ ACTIONS_ON_GOOGLE = 8; + } + + // Required. The rich response message. + oneof message { + // The text response. + Text text = 1; + + // The image response. + Image image = 2; + + // The quick replies response. + QuickReplies quick_replies = 3; + + // The card response. + Card card = 4; + + // Returns a response containing a custom, platform-specific payload. + // See the Intent.Message.Platform type for a description of the + // structure that may be required for your platform. + google.protobuf.Struct payload = 5; + + // The voice and text-only responses for Actions on Google. + SimpleResponses simple_responses = 7; + + // The basic card response for Actions on Google. + BasicCard basic_card = 8; + + // The suggestion chips for Actions on Google. + Suggestions suggestions = 9; + + // The link out suggestion chip for Actions on Google. + LinkOutSuggestion link_out_suggestion = 10; + + // The list card response for Actions on Google. + ListSelect list_select = 11; + + // The carousel card response for Actions on Google. + CarouselSelect carousel_select = 12; + } + + // Optional. The platform that this message is intended for. + Platform platform = 6; + } + + // Represents a single followup intent in the chain. + message FollowupIntentInfo { + // The unique identifier of the followup intent. + // Format: `projects//agent/intents/`. + string followup_intent_name = 1; + + // The unique identifier of the followup intent parent. + // Format: `projects//agent/intents/`. + string parent_followup_intent_name = 2; + } + + // Represents the different states that webhooks can be in. + enum WebhookState { + // Webhook is disabled in the agent and in the intent. + WEBHOOK_STATE_UNSPECIFIED = 0; + + // Webhook is enabled in the agent and in the intent. + WEBHOOK_STATE_ENABLED = 1; + + // Webhook is enabled in the agent and in the intent. Also, each slot + // filling prompt is forwarded to the webhook. + WEBHOOK_STATE_ENABLED_FOR_SLOT_FILLING = 2; + } + + // Required for all methods except `create` (`create` populates the name + // automatically. + // The unique identifier of this intent. + // Format: `projects//agent/intents/`. + string name = 1; + + // Required. The name of this intent. + string display_name = 2; + + // Required. Indicates whether webhooks are enabled for the intent. + WebhookState webhook_state = 6; + + // Optional. The priority of this intent. Higher numbers represent higher + // priorities. Zero or negative numbers mean that the intent is disabled. + int32 priority = 3; + + // Optional. Indicates whether this is a fallback intent. + bool is_fallback = 4; + + // Optional. Indicates whether Machine Learning is disabled for the intent. + // Note: If `ml_diabled` setting is set to true, then this intent is not + // taken into account during inference in `ML ONLY` match mode. Also, + // auto-markup in the UI is turned off. + bool ml_disabled = 19; + + // Optional. The list of context names required for this intent to be + // triggered. + // Format: `projects//agent/sessions/-/contexts/`. + repeated string input_context_names = 7; + + // Optional. The collection of event names that trigger the intent. + // If the collection of input contexts is not empty, all of the contexts must + // be present in the active user session for an event to trigger this intent. + repeated string events = 8; + + // Optional. The collection of examples/templates that the agent is + // trained on. + repeated TrainingPhrase training_phrases = 9; + + // Optional. The name of the action associated with the intent. + string action = 10; + + // Optional. The collection of contexts that are activated when the intent + // is matched. Context messages in this collection should not set the + // parameters field. Setting the `lifespan_count` to 0 will reset the context + // when the intent is matched. + // Format: `projects//agent/sessions/-/contexts/`. + repeated Context output_contexts = 11; + + // Optional. Indicates whether to delete all contexts in the current + // session when this intent is matched. + bool reset_contexts = 12; + + // Optional. The collection of parameters associated with the intent. + repeated Parameter parameters = 13; + + // Optional. The collection of rich messages corresponding to the + // `Response` field in the Dialogflow console. + repeated Message messages = 14; + + // Optional. The list of platforms for which the first response will be + // taken from among the messages assigned to the DEFAULT_PLATFORM. + repeated Message.Platform default_response_platforms = 15; + + // The unique identifier of the root intent in the chain of followup intents. + // It identifies the correct followup intents chain for this intent. + // Format: `projects//agent/intents/`. + string root_followup_intent_name = 16; + + // The unique identifier of the parent intent in the chain of followup + // intents. + // It identifies the parent followup intent. + // Format: `projects//agent/intents/`. + string parent_followup_intent_name = 17; + + // Optional. Collection of information about all followup intents that have + // name of this intent as a root_name. + repeated FollowupIntentInfo followup_intent_info = 18; +} + +// The request message for [Intents.ListIntents][google.cloud.dialogflow.v2.Intents.ListIntents]. +message ListIntentsRequest { + // Required. The agent to list all intents from. + // Format: `projects//agent`. + string parent = 1; + + // Optional. The language to list training phrases, parameters and rich + // messages for. If not specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent before they can be used. + string language_code = 2; + + // Optional. The resource view to apply to the returned intent. + IntentView intent_view = 3; + + // Optional. The maximum number of items to return in a single page. By + // default 100 and at most 1000. + int32 page_size = 4; + + // Optional. The next_page_token value returned from a previous list request. + string page_token = 5; +} + +// The response message for [Intents.ListIntents][google.cloud.dialogflow.v2.Intents.ListIntents]. +message ListIntentsResponse { + // The list of agent intents. There will be a maximum number of items + // returned based on the page_size field in the request. + repeated Intent intents = 1; + + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + string next_page_token = 2; +} + +// The request message for [Intents.GetIntent][google.cloud.dialogflow.v2.Intents.GetIntent]. +message GetIntentRequest { + // Required. The name of the intent. + // Format: `projects//agent/intents/`. + string name = 1; + + // Optional. The language to retrieve training phrases, parameters and rich + // messages for. If not specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 2; + + // Optional. The resource view to apply to the returned intent. + IntentView intent_view = 3; +} + +// The request message for [Intents.CreateIntent][google.cloud.dialogflow.v2.Intents.CreateIntent]. +message CreateIntentRequest { + // Required. The agent to create a intent for. + // Format: `projects//agent`. + string parent = 1; + + // Required. The intent to create. + Intent intent = 2; + + // Optional. The language of training phrases, parameters and rich messages + // defined in `intent`. If not specified, the agent's default language is + // used. [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 3; + + // Optional. The resource view to apply to the returned intent. + IntentView intent_view = 4; +} + +// The request message for [Intents.UpdateIntent][google.cloud.dialogflow.v2.Intents.UpdateIntent]. +message UpdateIntentRequest { + // Required. The intent to update. + // Format: `projects//agent/intents/`. + Intent intent = 1; + + // Optional. The language of training phrases, parameters and rich messages + // defined in `intent`. If not specified, the agent's default language is + // used. [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 2; + + // Optional. The mask to control which fields get updated. + google.protobuf.FieldMask update_mask = 3; + + // Optional. The resource view to apply to the returned intent. + IntentView intent_view = 4; +} + +// The request message for [Intents.DeleteIntent][google.cloud.dialogflow.v2.Intents.DeleteIntent]. +message DeleteIntentRequest { + // Required. The name of the intent to delete. + // Format: `projects//agent/intents/`. + string name = 1; +} + +// The request message for [Intents.BatchUpdateIntents][google.cloud.dialogflow.v2.Intents.BatchUpdateIntents]. +message BatchUpdateIntentsRequest { + // Required. The name of the agent to update or create intents in. + // Format: `projects//agent`. + string parent = 1; + + // Required. The source of the intent batch. + oneof intent_batch { + // The URI to a Google Cloud Storage file containing intents to update or + // create. The file format can either be a serialized proto (of IntentBatch + // type) or JSON object. Note: The URI must start with "gs://". + string intent_batch_uri = 2; + + // The collection of intents to update or create. + IntentBatch intent_batch_inline = 3; + } + + // Optional. The language of training phrases, parameters and rich messages + // defined in `intents`. If not specified, the agent's default language is + // used. [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + string language_code = 4; + + // Optional. The mask to control which fields get updated. + google.protobuf.FieldMask update_mask = 5; + + // Optional. The resource view to apply to the returned intent. + IntentView intent_view = 6; +} + +// The response message for [Intents.BatchUpdateIntents][google.cloud.dialogflow.v2.Intents.BatchUpdateIntents]. +message BatchUpdateIntentsResponse { + // The collection of updated or created intents. + repeated Intent intents = 1; +} + +// The request message for [Intents.BatchDeleteIntents][google.cloud.dialogflow.v2.Intents.BatchDeleteIntents]. +message BatchDeleteIntentsRequest { + // Required. The name of the agent to delete all entities types for. Format: + // `projects//agent`. + string parent = 1; + + // Required. The collection of intents to delete. Only intent `name` must be + // filled in. + repeated Intent intents = 2; +} + +// This message is a wrapper around a collection of intents. +message IntentBatch { + // A collection of intents. + repeated Intent intents = 1; +} + +// Represents the options for views of an intent. +// An intent can be a sizable object. Therefore, we provide a resource view that +// does not return training phrases in the response by default. +enum IntentView { + // Training phrases field is not populated in the response. + INTENT_VIEW_UNSPECIFIED = 0; + + // All fields are populated. + INTENT_VIEW_FULL = 1; +} diff --git a/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/session.proto b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/session.proto new file mode 100644 index 00000000..085e3504 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/session.proto @@ -0,0 +1,478 @@ +// Copyright 2018 Google Inc. +// +// 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. + +syntax = "proto3"; + +package google.cloud.dialogflow.v2; + +import "google/api/annotations.proto"; +import "google/cloud/dialogflow/v2/context.proto"; +import "google/cloud/dialogflow/v2/intent.proto"; +import "google/cloud/dialogflow/v2/session_entity_type.proto"; +import "google/protobuf/struct.proto"; +import "google/rpc/status.proto"; +import "google/type/latlng.proto"; + +option cc_enable_arenas = true; +option csharp_namespace = "Google.Cloud.Dialogflow.V2"; +option go_package = "google.golang.org/genproto/googleapis/cloud/dialogflow/v2;dialogflow"; +option java_multiple_files = true; +option java_outer_classname = "SessionProto"; +option java_package = "com.google.cloud.dialogflow.v2"; +option objc_class_prefix = "DF"; + + +// A session represents an interaction with a user. You retrieve user input +// and pass it to the [DetectIntent][google.cloud.dialogflow.v2.Sessions.DetectIntent] (or +// [StreamingDetectIntent][google.cloud.dialogflow.v2.Sessions.StreamingDetectIntent]) method to determine +// user intent and respond. +service Sessions { + // Processes a natural language query and returns structured, actionable data + // as a result. This method is not idempotent, because it may cause contexts + // and session entity types to be updated, which in turn might affect + // results of future queries. + rpc DetectIntent(DetectIntentRequest) returns (DetectIntentResponse) { + option (google.api.http) = { + post: "/v2/{session=projects/*/agent/sessions/*}:detectIntent" + body: "*" + }; + } + + // Processes a natural language query in audio format in a streaming fashion + // and returns structured, actionable data as a result. This method is only + // available via the gRPC API (not REST). + rpc StreamingDetectIntent(stream StreamingDetectIntentRequest) returns (stream StreamingDetectIntentResponse); +} + +// The request to detect user's intent. +message DetectIntentRequest { + // Required. The name of the session this query is sent to. Format: + // `projects//agent/sessions/`. It's up to the API + // caller to choose an appropriate session ID. It can be a random number or + // some type of user identifier (preferably hashed). The length of the session + // ID must not exceed 36 bytes. + string session = 1; + + // Optional. The parameters of this query. + QueryParameters query_params = 2; + + // Required. The input specification. It can be set to: + // + // 1. an audio config + // which instructs the speech recognizer how to process the speech audio, + // + // 2. a conversational query in the form of text, or + // + // 3. an event that specifies which intent to trigger. + QueryInput query_input = 3; + + // Optional. The natural language speech audio to be processed. This field + // should be populated iff `query_input` is set to an input audio config. + // A single request can contain up to 1 minute of speech audio data. + bytes input_audio = 5; +} + +// The message returned from the DetectIntent method. +message DetectIntentResponse { + // The unique identifier of the response. It can be used to + // locate a response in the training example set or for reporting issues. + string response_id = 1; + + // The results of the conversational query or event processing. + QueryResult query_result = 2; + + // Specifies the status of the webhook request. `webhook_status` + // is never populated in webhook requests. + google.rpc.Status webhook_status = 3; +} + +// Represents the parameters of the conversational query. +message QueryParameters { + // Optional. The time zone of this conversational query from the + // [time zone database](https://www.iana.org/time-zones), e.g., + // America/New_York, Europe/Paris. If not provided, the time zone specified in + // agent settings is used. + string time_zone = 1; + + // Optional. The geo location of this conversational query. + google.type.LatLng geo_location = 2; + + // Optional. The collection of contexts to be activated before this query is + // executed. + repeated Context contexts = 3; + + // Optional. Specifies whether to delete all contexts in the current session + // before the new ones are activated. + bool reset_contexts = 4; + + // Optional. The collection of session entity types to replace or extend + // developer entities with for this query only. The entity synonyms apply + // to all languages. + repeated SessionEntityType session_entity_types = 5; + + // Optional. This field can be used to pass custom data into the webhook + // associated with the agent. Arbitrary JSON objects are supported. + google.protobuf.Struct payload = 6; +} + +// Represents the query input. It can contain either: +// +// 1. An audio config which +// instructs the speech recognizer how to process the speech audio. +// +// 2. A conversational query in the form of text,. +// +// 3. An event that specifies which intent to trigger. +message QueryInput { + // Required. The input specification. + oneof input { + // Instructs the speech recognizer how to process the speech audio. + InputAudioConfig audio_config = 1; + + // The natural language text to be processed. + TextInput text = 2; + + // The event to be processed. + EventInput event = 3; + } +} + +// Represents the result of conversational query or event processing. +message QueryResult { + // The original conversational query text: + // - If natural language text was provided as input, `query_text` contains + // a copy of the input. + // - If natural language speech audio was provided as input, `query_text` + // contains the speech recognition result. If speech recognizer produced + // multiple alternatives, a particular one is picked. + // - If an event was provided as input, `query_text` is not set. + string query_text = 1; + + // The language that was triggered during intent detection. + // See [Language Support](https://dialogflow.com/docs/reference/language) + // for a list of the currently supported language codes. + string language_code = 15; + + // The Speech recognition confidence between 0.0 and 1.0. A higher number + // indicates an estimated greater likelihood that the recognized words are + // correct. The default of 0.0 is a sentinel value indicating that confidence + // was not set. + // + // You should not rely on this field as it isn't guaranteed to be accurate, or + // even set. In particular this field isn't set in Webhook calls and for + // StreamingDetectIntent since the streaming endpoint has separate confidence + // estimates per portion of the audio in StreamingRecognitionResult. + float speech_recognition_confidence = 2; + + // The action name from the matched intent. + string action = 3; + + // The collection of extracted parameters. + google.protobuf.Struct parameters = 4; + + // This field is set to: + // - `false` if the matched intent has required parameters and not all of + // the required parameter values have been collected. + // - `true` if all required parameter values have been collected, or if the + // matched intent doesn't contain any required parameters. + bool all_required_params_present = 5; + + // The text to be pronounced to the user or shown on the screen. + string fulfillment_text = 6; + + // The collection of rich messages to present to the user. + repeated Intent.Message fulfillment_messages = 7; + + // If the query was fulfilled by a webhook call, this field is set to the + // value of the `source` field returned in the webhook response. + string webhook_source = 8; + + // If the query was fulfilled by a webhook call, this field is set to the + // value of the `payload` field returned in the webhook response. + google.protobuf.Struct webhook_payload = 9; + + // The collection of output contexts. If applicable, + // `output_contexts.parameters` contains entries with name + // `.original` containing the original parameter values + // before the query. + repeated Context output_contexts = 10; + + // The intent that matched the conversational query. Some, not + // all fields are filled in this message, including but not limited to: + // `name`, `display_name` and `webhook_state`. + Intent intent = 11; + + // The intent detection confidence. Values range from 0.0 + // (completely uncertain) to 1.0 (completely certain). + float intent_detection_confidence = 12; + + // The free-form diagnostic info. For example, this field + // could contain webhook call latency. + google.protobuf.Struct diagnostic_info = 14; +} + +// The top-level message sent by the client to the +// `StreamingDetectIntent` method. +// +// Multiple request messages should be sent in order: +// +// 1. The first message must contain `session`, `query_input` plus optionally +// `query_params` and/or `single_utterance`. The message must not contain `input_audio`. +// +// 2. If `query_input` was set to a streaming input audio config, +// all subsequent messages must contain only `input_audio`. +// Otherwise, finish the request stream. +message StreamingDetectIntentRequest { + // Required. The name of the session the query is sent to. + // Format of the session name: + // `projects//agent/sessions/`. It’s up to the API + // caller to choose an appropriate . It can be a random number or + // some type of user identifier (preferably hashed). The length of the session + // ID must not exceed 36 characters. + string session = 1; + + // Optional. The parameters of this query. + QueryParameters query_params = 2; + + // Required. The input specification. It can be set to: + // + // 1. an audio config which instructs the speech recognizer how to process + // the speech audio, + // + // 2. a conversational query in the form of text, or + // + // 3. an event that specifies which intent to trigger. + QueryInput query_input = 3; + + // Optional. If `false` (default), recognition does not cease until the + // client closes the stream. + // If `true`, the recognizer will detect a single spoken utterance in input + // audio. Recognition ceases when it detects the audio's voice has + // stopped or paused. In this case, once a detected intent is received, the + // client should close the stream and start a new request with a new stream as + // needed. + // This setting is ignored when `query_input` is a piece of text or an event. + bool single_utterance = 4; + + // Optional. The input audio content to be recognized. Must be sent if + // `query_input` was set to a streaming input audio config. The complete audio + // over all streaming messages must not exceed 1 minute. + bytes input_audio = 6; +} + +// The top-level message returned from the +// `StreamingDetectIntent` method. +// +// Multiple response messages can be returned in order: +// +// 1. If the input was set to streaming audio, the first one or more messages +// contain `recognition_result`. Each `recognition_result` represents a more +// complete transcript of what the user said. The last `recognition_result` +// has `is_final` set to `true`. +// +// 2. The next message contains `response_id`, `query_result` +// and optionally `webhook_status` if a WebHook was called. +message StreamingDetectIntentResponse { + // The unique identifier of the response. It can be used to + // locate a response in the training example set or for reporting issues. + string response_id = 1; + + // The result of speech recognition. + StreamingRecognitionResult recognition_result = 2; + + // The result of the conversational query or event processing. + QueryResult query_result = 3; + + // Specifies the status of the webhook request. + google.rpc.Status webhook_status = 4; +} + +// Contains a speech recognition result corresponding to a portion of the audio +// that is currently being processed or an indication that this is the end +// of the single requested utterance. +// +// Example: +// +// 1. transcript: "tube" +// +// 2. transcript: "to be a" +// +// 3. transcript: "to be" +// +// 4. transcript: "to be or not to be" +// is_final: true +// +// 5. transcript: " that's" +// +// 6. transcript: " that is" +// +// 7. recognition_event_type: `RECOGNITION_EVENT_END_OF_SINGLE_UTTERANCE` +// +// 8. transcript: " that is the question" +// is_final: true +// +// Only two of the responses contain final results (#4 and #8 indicated by +// `is_final: true`). Concatenating these generates the full transcript: "to be +// or not to be that is the question". +// +// In each response we populate: +// +// * for `MESSAGE_TYPE_TRANSCRIPT`: `transcript` and possibly `is_final`. +// +// * for `MESSAGE_TYPE_END_OF_SINGLE_UTTERANCE`: only `event_type`. +message StreamingRecognitionResult { + // Type of the response message. + enum MessageType { + // Not specified. Should never be used. + MESSAGE_TYPE_UNSPECIFIED = 0; + + // Message contains a (possibly partial) transcript. + TRANSCRIPT = 1; + + // Event indicates that the server has detected the end of the user's speech + // utterance and expects no additional speech. Therefore, the server will + // not process additional audio (although it may subsequently return + // additional results). The client should stop sending additional audio + // data, half-close the gRPC connection, and wait for any additional results + // until the server closes the gRPC connection. This message is only sent if + // `single_utterance` was set to `true`, and is not used otherwise. + END_OF_SINGLE_UTTERANCE = 2; + } + + // Type of the result message. + MessageType message_type = 1; + + // Transcript text representing the words that the user spoke. + // Populated if and only if `event_type` = `RECOGNITION_EVENT_TRANSCRIPT`. + string transcript = 2; + + // The default of 0.0 is a sentinel value indicating `confidence` was not set. + // If `false`, the `StreamingRecognitionResult` represents an + // interim result that may change. If `true`, the recognizer will not return + // any further hypotheses about this piece of the audio. May only be populated + // for `event_type` = `RECOGNITION_EVENT_TRANSCRIPT`. + bool is_final = 3; + + // The Speech confidence between 0.0 and 1.0 for the current portion of audio. + // A higher number indicates an estimated greater likelihood that the + // recognized words are correct. The default of 0.0 is a sentinel value + // indicating that confidence was not set. + // + // This field is typically only provided if `is_final` is true and you should + // not rely on it being accurate or even set. + float confidence = 4; +} + +// Instructs the speech recognizer how to process the audio content. +message InputAudioConfig { + // Required. Audio encoding of the audio content to process. + AudioEncoding audio_encoding = 1; + + // Required. Sample rate (in Hertz) of the audio content sent in the query. + // Refer to [Cloud Speech API documentation](/speech/docs/basics) for more + // details. + int32 sample_rate_hertz = 2; + + // Required. The language of the supplied audio. Dialogflow does not do + // translations. See [Language + // Support](https://dialogflow.com/docs/languages) for a list of the + // currently supported language codes. Note that queries in the same session + // do not necessarily need to specify the same language. + string language_code = 3; + + // Optional. The collection of phrase hints which are used to boost accuracy + // of speech recognition. + // Refer to [Cloud Speech API documentation](/speech/docs/basics#phrase-hints) + // for more details. + repeated string phrase_hints = 4; +} + +// Represents the natural language text to be processed. +message TextInput { + // Required. The UTF-8 encoded natural language text to be processed. + // Text length must not exceed 256 bytes. + string text = 1; + + // Required. The language of this conversational query. See [Language + // Support](https://dialogflow.com/docs/languages) for a list of the + // currently supported language codes. Note that queries in the same session + // do not necessarily need to specify the same language. + string language_code = 2; +} + +// Events allow for matching intents by event name instead of the natural +// language input. For instance, input `` can trigger a personalized welcome response. +// The parameter `name` may be used by the agent in the response: +// `“Hello #welcome_event.name! What can I do for you today?”`. +message EventInput { + // Required. The unique identifier of the event. + string name = 1; + + // Optional. The collection of parameters associated with the event. + google.protobuf.Struct parameters = 2; + + // Required. The language of this query. See [Language + // Support](https://dialogflow.com/docs/languages) for a list of the + // currently supported language codes. Note that queries in the same session + // do not necessarily need to specify the same language. + string language_code = 3; +} + +// Audio encoding of the audio content sent in the conversational query request. +// Refer to the [Cloud Speech API documentation](/speech/docs/basics) for more +// details. +enum AudioEncoding { + // Not specified. + AUDIO_ENCODING_UNSPECIFIED = 0; + + // Uncompressed 16-bit signed little-endian samples (Linear PCM). + AUDIO_ENCODING_LINEAR_16 = 1; + + // [`FLAC`](https://xiph.org/flac/documentation.html) (Free Lossless Audio + // Codec) is the recommended encoding because it is lossless (therefore + // recognition is not compromised) and requires only about half the + // bandwidth of `LINEAR16`. `FLAC` stream encoding supports 16-bit and + // 24-bit samples, however, not all fields in `STREAMINFO` are supported. + AUDIO_ENCODING_FLAC = 2; + + // 8-bit samples that compand 14-bit audio samples using G.711 PCMU/mu-law. + AUDIO_ENCODING_MULAW = 3; + + // Adaptive Multi-Rate Narrowband codec. `sample_rate_hertz` must be 8000. + AUDIO_ENCODING_AMR = 4; + + // Adaptive Multi-Rate Wideband codec. `sample_rate_hertz` must be 16000. + AUDIO_ENCODING_AMR_WB = 5; + + // Opus encoded audio frames in Ogg container + // ([OggOpus](https://wiki.xiph.org/OggOpus)). + // `sample_rate_hertz` must be 16000. + AUDIO_ENCODING_OGG_OPUS = 6; + + // Although the use of lossy encodings is not recommended, if a very low + // bitrate encoding is required, `OGG_OPUS` is highly preferred over + // Speex encoding. The [Speex](https://speex.org/) encoding supported by + // Dialogflow API has a header byte in each block, as in MIME type + // `audio/x-speex-with-header-byte`. + // It is a variant of the RTP Speex encoding defined in + // [RFC 5574](https://tools.ietf.org/html/rfc5574). + // The stream is a sequence of blocks, one block per RTP packet. Each block + // starts with a byte containing the length of the block, in bytes, followed + // by one or more frames of Speex data, padded to an integral number of + // bytes (octets) as specified in RFC 5574. In other words, each RTP header + // is replaced with a single byte containing the block length. Only Speex + // wideband is supported. `sample_rate_hertz` must be 16000. + AUDIO_ENCODING_SPEEX_WITH_HEADER_BYTE = 7; +} diff --git a/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/session_entity_type.proto b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/session_entity_type.proto new file mode 100644 index 00000000..89408df6 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/session_entity_type.proto @@ -0,0 +1,184 @@ +// Copyright 2018 Google Inc. +// +// 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. + +syntax = "proto3"; + +package google.cloud.dialogflow.v2; + +import "google/api/annotations.proto"; +import "google/cloud/dialogflow/v2/entity_type.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/field_mask.proto"; + +option cc_enable_arenas = true; +option csharp_namespace = "Google.Cloud.Dialogflow.V2"; +option go_package = "google.golang.org/genproto/googleapis/cloud/dialogflow/v2;dialogflow"; +option java_multiple_files = true; +option java_outer_classname = "SessionEntityTypeProto"; +option java_package = "com.google.cloud.dialogflow.v2"; +option objc_class_prefix = "DF"; + + +// Entities are extracted from user input and represent parameters that are +// meaningful to your application. For example, a date range, a proper name +// such as a geographic location or landmark, and so on. Entities represent +// actionable data for your application. +// +// Session entity types are referred to as **User** entity types and are +// entities that are built for an individual user such as +// favorites, preferences, playlists, and so on. You can redefine a session +// entity type at the session level. +// +// For more information about entity types, see the +// [Dialogflow documentation](https://dialogflow.com/docs/entities). +service SessionEntityTypes { + // Returns the list of all session entity types in the specified session. + rpc ListSessionEntityTypes(ListSessionEntityTypesRequest) returns (ListSessionEntityTypesResponse) { + option (google.api.http) = { + get: "/v2/{parent=projects/*/agent/sessions/*}/entityTypes" + }; + } + + // Retrieves the specified session entity type. + rpc GetSessionEntityType(GetSessionEntityTypeRequest) returns (SessionEntityType) { + option (google.api.http) = { + get: "/v2/{name=projects/*/agent/sessions/*/entityTypes/*}" + }; + } + + // Creates a session entity type. + rpc CreateSessionEntityType(CreateSessionEntityTypeRequest) returns (SessionEntityType) { + option (google.api.http) = { + post: "/v2/{parent=projects/*/agent/sessions/*}/entityTypes" + body: "session_entity_type" + }; + } + + // Updates the specified session entity type. + rpc UpdateSessionEntityType(UpdateSessionEntityTypeRequest) returns (SessionEntityType) { + option (google.api.http) = { + patch: "/v2/{session_entity_type.name=projects/*/agent/sessions/*/entityTypes/*}" + body: "session_entity_type" + }; + } + + // Deletes the specified session entity type. + rpc DeleteSessionEntityType(DeleteSessionEntityTypeRequest) returns (google.protobuf.Empty) { + option (google.api.http) = { + delete: "/v2/{name=projects/*/agent/sessions/*/entityTypes/*}" + }; + } +} + +// Represents a session entity type. +// +// Extends or replaces a developer entity type at the user session level (we +// refer to the entity types defined at the agent level as "developer entity +// types"). +// +// Note: session entity types apply to all queries, regardless of the language. +message SessionEntityType { + // The types of modifications for a session entity type. + enum EntityOverrideMode { + // Not specified. This value should be never used. + ENTITY_OVERRIDE_MODE_UNSPECIFIED = 0; + + // The collection of session entities overrides the collection of entities + // in the corresponding developer entity type. + ENTITY_OVERRIDE_MODE_OVERRIDE = 1; + + // The collection of session entities extends the collection of entities in + // the corresponding developer entity type. + // Calls to `ListSessionEntityTypes`, `GetSessionEntityType`, + // `CreateSessionEntityType` and `UpdateSessionEntityType` return the full + // collection of entities from the developer entity type in the agent's + // default language and the session entity type. + ENTITY_OVERRIDE_MODE_SUPPLEMENT = 2; + } + + // Required. The unique identifier of this session entity type. Format: + // `projects//agent/sessions//entityTypes/`. + string name = 1; + + // Required. Indicates whether the additional data should override or + // supplement the developer entity type definition. + EntityOverrideMode entity_override_mode = 2; + + // Required. The collection of entities associated with this session entity + // type. + repeated EntityType.Entity entities = 3; +} + +// The request message for [SessionEntityTypes.ListSessionEntityTypes][google.cloud.dialogflow.v2.SessionEntityTypes.ListSessionEntityTypes]. +message ListSessionEntityTypesRequest { + // Required. The session to list all session entity types from. + // Format: `projects//agent/sessions/`. + string parent = 1; + + // Optional. The maximum number of items to return in a single page. By + // default 100 and at most 1000. + int32 page_size = 2; + + // Optional. The next_page_token value returned from a previous list request. + string page_token = 3; +} + +// The response message for [SessionEntityTypes.ListSessionEntityTypes][google.cloud.dialogflow.v2.SessionEntityTypes.ListSessionEntityTypes]. +message ListSessionEntityTypesResponse { + // The list of session entity types. There will be a maximum number of items + // returned based on the page_size field in the request. + repeated SessionEntityType session_entity_types = 1; + + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + string next_page_token = 2; +} + +// The request message for [SessionEntityTypes.GetSessionEntityType][google.cloud.dialogflow.v2.SessionEntityTypes.GetSessionEntityType]. +message GetSessionEntityTypeRequest { + // Required. The name of the session entity type. Format: + // `projects//agent/sessions//entityTypes/`. + string name = 1; +} + +// The request message for [SessionEntityTypes.CreateSessionEntityType][google.cloud.dialogflow.v2.SessionEntityTypes.CreateSessionEntityType]. +message CreateSessionEntityTypeRequest { + // Required. The session to create a session entity type for. + // Format: `projects//agent/sessions/`. + string parent = 1; + + // Required. The session entity type to create. + SessionEntityType session_entity_type = 2; +} + +// The request message for [SessionEntityTypes.UpdateSessionEntityType][google.cloud.dialogflow.v2.SessionEntityTypes.UpdateSessionEntityType]. +message UpdateSessionEntityTypeRequest { + // Required. The entity type to update. Format: + // `projects//agent/sessions//entityTypes/`. + SessionEntityType session_entity_type = 1; + + // Optional. The mask to control which fields get updated. + google.protobuf.FieldMask update_mask = 2; +} + +// The request message for [SessionEntityTypes.DeleteSessionEntityType][google.cloud.dialogflow.v2.SessionEntityTypes.DeleteSessionEntityType]. +message DeleteSessionEntityTypeRequest { + // Required. The name of the entity type to delete. Format: + // `projects//agent/sessions//entityTypes/`. + string name = 1; +} diff --git a/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/webhook.proto b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/webhook.proto new file mode 100644 index 00000000..24314f86 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/proto/google/cloud/dialogflow/v2/webhook.proto @@ -0,0 +1,111 @@ +// Copyright 2018 Google Inc. +// +// 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. + +syntax = "proto3"; + +package google.cloud.dialogflow.v2; + +import "google/api/annotations.proto"; +import "google/cloud/dialogflow/v2/context.proto"; +import "google/cloud/dialogflow/v2/intent.proto"; +import "google/cloud/dialogflow/v2/session.proto"; +import "google/protobuf/struct.proto"; + +option cc_enable_arenas = true; +option csharp_namespace = "Google.Cloud.Dialogflow.V2"; +option go_package = "google.golang.org/genproto/googleapis/cloud/dialogflow/v2;dialogflow"; +option java_multiple_files = true; +option java_outer_classname = "WebhookProto"; +option java_package = "com.google.cloud.dialogflow.v2"; +option objc_class_prefix = "DF"; + + +// The request message for a webhook call. +message WebhookRequest { + // The unique identifier of detectIntent request session. + // Can be used to identify end-user inside webhook implementation. + // Format: `projects//agent/sessions/`. + string session = 4; + + // The unique identifier of the response. Contains the same value as + // `[Streaming]DetectIntentResponse.response_id`. + string response_id = 1; + + // The result of the conversational query or event processing. Contains the + // same value as `[Streaming]DetectIntentResponse.query_result`. + QueryResult query_result = 2; + + // Optional. The contents of the original request that was passed to + // `[Streaming]DetectIntent` call. + OriginalDetectIntentRequest original_detect_intent_request = 3; +} + +// The response message for a webhook call. +message WebhookResponse { + // Optional. The text to be shown on the screen. This value is passed directly + // to `QueryResult.fulfillment_text`. + string fulfillment_text = 1; + + // Optional. The collection of rich messages to present to the user. This + // value is passed directly to `QueryResult.fulfillment_messages`. + repeated Intent.Message fulfillment_messages = 2; + + // Optional. This value is passed directly to `QueryResult.webhook_source`. + string source = 3; + + // Optional. This value is passed directly to `QueryResult.webhook_payload`. + // See the related `fulfillment_messages[i].payload field`, which may be used + // as an alternative to this field. + // + // This field can be used for Actions on Google responses. + // It should have a structure similar to the JSON message shown here. For more + // information, see + // [Actions on Google Webhook + // Format](https://developers.google.com/actions/dialogflow/webhook) + //
{
+  //   "google": {
+  //     "expectUserResponse": true,
+  //     "richResponse": {
+  //       "items": [
+  //         {
+  //           "simpleResponse": {
+  //             "textToSpeech": "this is a simple response"
+  //           }
+  //         }
+  //       ]
+  //     }
+  //   }
+  // }
+ google.protobuf.Struct payload = 4; + + // Optional. The collection of output contexts. This value is passed directly + // to `QueryResult.output_contexts`. + repeated Context output_contexts = 5; + + // Optional. Makes the platform immediately invoke another `DetectIntent` call + // internally with the specified event as input. + EventInput followup_event_input = 6; +} + +// Represents the contents of the original request that was passed to +// the `[Streaming]DetectIntent` call. +message OriginalDetectIntentRequest { + // The source of this request, e.g., `google`, `facebook`, `slack`. It is set + // by Dialogflow-owned servers. + string source = 1; + + // Optional. This field is set to the value of `QueryParameters.payload` field + // passed in the request. + google.protobuf.Struct payload = 3; +} diff --git a/dialogflow/Dialogflow/app/src/main/res/drawable/bubble_incoming.xml b/dialogflow/Dialogflow/app/src/main/res/drawable/bubble_incoming.xml new file mode 100644 index 00000000..3d8f0a1d --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/drawable/bubble_incoming.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + diff --git a/dialogflow/Dialogflow/app/src/main/res/drawable/bubble_outgoing.xml b/dialogflow/Dialogflow/app/src/main/res/drawable/bubble_outgoing.xml new file mode 100644 index 00000000..a9eb9b61 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/drawable/bubble_outgoing.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + diff --git a/dialogflow/Dialogflow/app/src/main/res/drawable/ic_keyboard.xml b/dialogflow/Dialogflow/app/src/main/res/drawable/ic_keyboard.xml new file mode 100644 index 00000000..28916547 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/drawable/ic_keyboard.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/dialogflow/Dialogflow/app/src/main/res/drawable/ic_mic.xml b/dialogflow/Dialogflow/app/src/main/res/drawable/ic_mic.xml new file mode 100644 index 00000000..ee17a8f2 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/drawable/ic_mic.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/dialogflow/Dialogflow/app/src/main/res/drawable/ic_send.xml b/dialogflow/Dialogflow/app/src/main/res/drawable/ic_send.xml new file mode 100644 index 00000000..573011d2 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/drawable/ic_send.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/dialogflow/Dialogflow/app/src/main/res/layout/activity_main.xml b/dialogflow/Dialogflow/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..6720d72c --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + diff --git a/dialogflow/Dialogflow/app/src/main/res/layout/item_conversation.xml b/dialogflow/Dialogflow/app/src/main/res/layout/item_conversation.xml new file mode 100644 index 00000000..39539403 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/layout/item_conversation.xml @@ -0,0 +1,37 @@ + + + + + + + diff --git a/dialogflow/Dialogflow/app/src/main/res/mipmap-hdpi/ic_launcher.png b/dialogflow/Dialogflow/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..41251130 Binary files /dev/null and b/dialogflow/Dialogflow/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/dialogflow/Dialogflow/app/src/main/res/mipmap-mdpi/ic_launcher.png b/dialogflow/Dialogflow/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..33da5569 Binary files /dev/null and b/dialogflow/Dialogflow/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/dialogflow/Dialogflow/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/dialogflow/Dialogflow/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..40897d71 Binary files /dev/null and b/dialogflow/Dialogflow/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/dialogflow/Dialogflow/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/dialogflow/Dialogflow/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..584eae61 Binary files /dev/null and b/dialogflow/Dialogflow/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/dialogflow/Dialogflow/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/dialogflow/Dialogflow/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..a171d040 Binary files /dev/null and b/dialogflow/Dialogflow/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/dialogflow/Dialogflow/app/src/main/res/values/attrs.xml b/dialogflow/Dialogflow/app/src/main/res/values/attrs.xml new file mode 100644 index 00000000..be2ccf3b --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/values/attrs.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/dialogflow/Dialogflow/app/src/main/res/values/colors.xml b/dialogflow/Dialogflow/app/src/main/res/values/colors.xml new file mode 100644 index 00000000..9742b4f5 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/values/colors.xml @@ -0,0 +1,26 @@ + + + + #FF5722 + #E64A19 + #536DFE + + #FBE9E7 + #EEEEEE + #E0E0E0 + #616161 + diff --git a/dialogflow/Dialogflow/app/src/main/res/values/dimens.xml b/dialogflow/Dialogflow/app/src/main/res/values/dimens.xml new file mode 100644 index 00000000..7e263753 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/values/dimens.xml @@ -0,0 +1,29 @@ + + + + 4dp + 8dp + 16dp + + 4dp + 48dp + 64dp + + 16dp + 16dp + 24dp + diff --git a/dialogflow/Dialogflow/app/src/main/res/values/strings.xml b/dialogflow/Dialogflow/app/src/main/res/values/strings.xml new file mode 100644 index 00000000..4676c3bf --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/values/strings.xml @@ -0,0 +1,25 @@ + + + + Dialogflow + Write a message + Speak + This app needs to record audio and recognize your speech. + Voice + Send + Keyboard + diff --git a/dialogflow/Dialogflow/app/src/main/res/values/styles.xml b/dialogflow/Dialogflow/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..1e68ac30 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/values/styles.xml @@ -0,0 +1,25 @@ + + + + + + + diff --git a/dialogflow/Dialogflow/app/src/main/res/xml/backup_scheme.xml b/dialogflow/Dialogflow/app/src/main/res/xml/backup_scheme.xml new file mode 100644 index 00000000..95e99ca6 --- /dev/null +++ b/dialogflow/Dialogflow/app/src/main/res/xml/backup_scheme.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/dialogflow/Dialogflow/build.gradle b/dialogflow/Dialogflow/build.gradle new file mode 100644 index 00000000..e531f372 --- /dev/null +++ b/dialogflow/Dialogflow/build.gradle @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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. + */ + +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.1.4' + classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.2' + } +} + +allprojects { + repositories { + jcenter() + google() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/dialogflow/Dialogflow/gradle.properties b/dialogflow/Dialogflow/gradle.properties new file mode 100644 index 00000000..d2fc6cf1 --- /dev/null +++ b/dialogflow/Dialogflow/gradle.properties @@ -0,0 +1,21 @@ +# Copyright 2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# 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. + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# Configuration for API.AI agent +dialogflowProjectName=android-docs-samples +dialogflowLanguageCode=en-US diff --git a/dialogflow/Dialogflow/gradle/wrapper/gradle-wrapper.jar b/dialogflow/Dialogflow/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..13372aef Binary files /dev/null and b/dialogflow/Dialogflow/gradle/wrapper/gradle-wrapper.jar differ diff --git a/dialogflow/Dialogflow/gradle/wrapper/gradle-wrapper.properties b/dialogflow/Dialogflow/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..c70ba129 --- /dev/null +++ b/dialogflow/Dialogflow/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Aug 23 10:15:48 JST 2018 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/dialogflow/Dialogflow/gradlew b/dialogflow/Dialogflow/gradlew new file mode 100755 index 00000000..9d82f789 --- /dev/null +++ b/dialogflow/Dialogflow/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/dialogflow/Dialogflow/gradlew.bat b/dialogflow/Dialogflow/gradlew.bat new file mode 100644 index 00000000..aec99730 --- /dev/null +++ b/dialogflow/Dialogflow/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/dialogflow/Dialogflow/settings.gradle b/dialogflow/Dialogflow/settings.gradle new file mode 100644 index 00000000..e7b4def4 --- /dev/null +++ b/dialogflow/Dialogflow/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/speech/Speech/app/build.gradle b/speech/Speech/app/build.gradle index 8399f24e..b03e8470 100644 --- a/speech/Speech/app/build.gradle +++ b/speech/Speech/app/build.gradle @@ -18,17 +18,18 @@ apply plugin: 'com.android.application' apply plugin: 'com.google.protobuf' ext { - supportLibraryVersion = '25.4.0' - grpcVersion = '1.4.0' + supportLibraryVersion = '28.0.0' + grpcVersion = '1.21.0' + protobufVersion = '3.8.0' } android { - compileSdkVersion 25 - buildToolsVersion '25.0.3' + compileSdkVersion 28 defaultConfig { applicationId "com.google.cloud.android.speech" - targetSdkVersion 25 + targetSdkVersion 28 + minSdkVersion 16 versionCode 1 versionName '1.0' } @@ -42,17 +43,6 @@ android { } } - productFlavors { - dev { - // Minimum version with platform multi-dex support - minSdkVersion 21 - } - prod { - // Minimum version that can run gRPC (TLS extension) - minSdkVersion 16 - } - } - buildTypes { debug { minifyEnabled false @@ -64,16 +54,11 @@ android { signingConfig signingConfigs.release } } - - configurations.all { - resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.2' - resolutionStrategy.force "com.android.support:support-annotations:$supportLibraryVersion" - } } protobuf { protoc { - artifact = 'com.google.protobuf:protoc:3.3.0' + artifact = "com.google.protobuf:protoc:$protobufVersion" } plugins { javalite { @@ -97,33 +82,31 @@ protobuf { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - // Support libraries - compile "com.android.support:design:$supportLibraryVersion" - compile "com.android.support:cardview-v7:$supportLibraryVersion" - compile "com.android.support:recyclerview-v7:$supportLibraryVersion" + implementation "com.android.support:design:$supportLibraryVersion" + implementation "com.android.support:cardview-v7:$supportLibraryVersion" + implementation "com.android.support:recyclerview-v7:$supportLibraryVersion" // gRPC - compile "io.grpc:grpc-okhttp:$grpcVersion" - compile "io.grpc:grpc-protobuf-lite:$grpcVersion" - compile "io.grpc:grpc-stub:$grpcVersion" - compile 'javax.annotation:javax.annotation-api:1.2' - protobuf 'com.google.protobuf:protobuf-java:3.3.1' + implementation "io.grpc:grpc-okhttp:$grpcVersion" + implementation "io.grpc:grpc-protobuf-lite:$grpcVersion" + implementation "io.grpc:grpc-stub:$grpcVersion" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + protobuf "com.google.protobuf:protobuf-java:$protobufVersion" // OAuth2 for Google API - compile('com.google.auth:google-auth-library-oauth2-http:0.7.0') { + implementation('com.google.auth:google-auth-library-oauth2-http:0.16.1') { exclude module: 'httpclient' } // Tests - testCompile 'junit:junit:4.12' - androidTestCompile 'com.android.support.test:runner:0.5' - androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } task copySecretKey(type: Copy) { - def File secretKey = file "$System.env.GOOGLE_APPLICATION_CREDENTIALS" + File secretKey = file "$System.env.GOOGLE_APPLICATION_CREDENTIALS" from secretKey.getParent() include secretKey.getName() into 'src/main/res/raw' diff --git a/speech/Speech/build.gradle b/speech/Speech/build.gradle index 75f079d1..8e67f15b 100644 --- a/speech/Speech/build.gradle +++ b/speech/Speech/build.gradle @@ -22,8 +22,8 @@ buildscript { maven { url 'https://maven.google.com' } } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' - classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0' + classpath 'com.android.tools.build:gradle:3.4.1' + classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/speech/Speech/gradle/wrapper/gradle-wrapper.properties b/speech/Speech/gradle/wrapper/gradle-wrapper.properties index 618ded6a..26028d52 100644 --- a/speech/Speech/gradle/wrapper/gradle-wrapper.properties +++ b/speech/Speech/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Apr 03 14:01:53 JST 2017 +#Tue Jun 11 10:38:36 JST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip