Пример #1
0
        /// <summary>
        /// Every conversation turn calls this method.
        /// </summary>
        /// <param name="turnContext">A <see cref="ITurnContext"/> containing all the data needed
        /// for processing this conversation turn. </param>
        /// <param name="cancellationToken">(Optional) A <see cref="CancellationToken"/> that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> that represents the work queued to execute.</returns>
        /// <seealso cref="BotStateSet"/>
        /// <seealso cref="ConversationState"/>
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentException(nameof(turnContext));
            }

            // Handle Message activity type, which is the main activity type for shown within a conversational interface
            // Message activities may contain text, speech, interactive cards, and binary or unknown attachments.
            // see https://aka.ms/about-bot-activity-message to learn more about the message and other activity types
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                DialogContext dialogContext = await _dialogSet.CreateContextAsync(turnContext, cancellationToken);

                DialogTurnResult results = await dialogContext.ContinueDialogAsync(cancellationToken);

                switch (results.Status)
                {
                case DialogTurnStatus.Cancelled:
                case DialogTurnStatus.Empty:
                    // If there is no active dialog, we should clear the user info and start a new dialog.
                    await _botAccessor.UserProfileAccessor.SetAsync(turnContext, new IcMProfile(), cancellationToken);

                    await _botAccessor.UserState.SaveChangesAsync(turnContext, false, cancellationToken);

                    await dialogContext.BeginDialogAsync(TopLevelDialog, null, cancellationToken);

                    break;

                case DialogTurnStatus.Complete:
                    // If we just finished the dialog, capture and display the results.
                    IcMProfile icMInfo = results.Result as IcMProfile;
                    string     status  = "Thanks for the chat";
                    await turnContext.SendActivityAsync(status);

                    await _botAccessor.UserProfileAccessor.SetAsync(turnContext, icMInfo, cancellationToken);

                    await _botAccessor.UserState.SaveChangesAsync(turnContext, false, cancellationToken);

                    break;

                case DialogTurnStatus.Waiting:
                    // If there is an active dialog, we don't need to do anything here.
                    break;
                }

                await _botAccessor.ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);

                // Echo back to the user whatever they typed.
                //await turnContext.SendActivityAsync("Hello World", cancellationToken: cancellationToken);
            }
            if (turnContext.Activity.Type == ActivityTypes.ConversationUpdate)
            {
                await turnContext.SendActivityAsync("Welcome to Online Support Engineer Bots", cancellationToken : cancellationToken);
            }
        }
Пример #2
0
        protected override async Task CompleteAsync(DialogContext dc, DialogTurnResult result = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            var response = dc.Context.Activity.CreateReply();

            response.Type = ActivityTypes.EndOfConversation;

            await dc.Context.SendActivityAsync(response);

            await dc.EndDialogAsync(result);
        }
Пример #3
0
        protected override async Task CompleteAsync(DialogContext dc, DialogTurnResult result = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            // The active dialog's stack ended with a complete status
            await _responder.ReplyWith(dc.Context, MainResponses.ResponseIds.Completed);

            // Request feedback on the last activity.
            if (Id != nameof(OnboardingDialog))
            {
                await FeedbackMiddleware.RequestFeedbackAsync(dc.Context, Id);
            }
        }
        // Runs on every turn of the conversation to check if the conversation should be interrupted.
        protected async Task <DialogTurnResult> InterruptDialogAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            DialogTurnResult interrupted = null;
            var activity = innerDc.Context.Activity;

            if (activity.Type == ActivityTypes.Message && !string.IsNullOrEmpty(activity.Text))
            {
            }

            return(interrupted);
        }
Пример #5
0
        private async Task <DialogTurnResult> entityPrompt(
            WaterfallStepContext step,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            DialogTurnResult returnResult = new DialogTurnResult(0);

            if (step.Options == null)
            {
                FoundChoice module = (FoundChoice)step.Result;
                ((BotUserEntityContext)step.Values[DialogKey]).module = module.Value;
                List <string> entities = _navigationEntityData.NavigationEntitiesForModule(module.Value.ToString());

                returnResult = await step.PromptAsync(
                    ChoicesPromptId,
                    new PromptOptions
                {
                    Prompt      = MessageFactory.Text($"The {module.Value} area has the following topics that I know about. Please choose one that I can help with."),
                    RetryPrompt = MessageFactory.Text("Please choose an option from the list."),
                    Choices     = ChoiceFactory.ToChoices(entities),
                },
                    cancellationToken);
            }
            else
            {
                FoundChoice branchChoice = (FoundChoice)step.Result;
                if (branchChoice.Value == "Choose an area")
                {
                    ((BotUserEntityContext)step.Values[DialogKey]).module = branchChoice.Value;

                    returnResult = await step.EndDialogAsync(
                        (BotUserEntityContext)step.Values[DialogKey],
                        cancellationToken);
                }
                else
                {
                    ((BotUserEntityContext)step.Values[DialogKey]).module = ((BotUserEntityContext)step.Values[DialogKeyOptions]).module;
                    ((BotUserEntityContext)step.Values[DialogKey]).entity = branchChoice.Value;
                    List <string> entityIntents = _navigationEntityData.CrudActionForEntities(branchChoice.Value.ToString());
                    entityIntents.Add("Find");

                    returnResult = await step.PromptAsync(
                        ChoicesPromptId,
                        new PromptOptions
                    {
                        Prompt      = MessageFactory.Text($"With the {branchChoice.Value} I can do the following things.Please select one."),
                        RetryPrompt = MessageFactory.Text("Please choose an option from the list."),
                        Choices     = ChoiceFactory.ToChoices(entityIntents),
                    },
                        cancellationToken);
                }
            }
            return(returnResult);
        }
Пример #6
0
        protected override async Task CompleteAsync(DialogContext dc, DialogTurnResult result = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            // workaround. if connect skill directly to teams, the following response does not work.
            if (dc.Context.Adapter is IRemoteUserTokenProvider remoteInvocationAdapter || Channel.GetChannelId(dc.Context) != Channels.Msteams)
            {
                var response = dc.Context.Activity.CreateReply();
                response.Type = ActivityTypes.EndOfConversation;

                await dc.Context.SendActivityAsync(response);
            }
            await dc.EndDialogAsync(result);
        }
Пример #7
0
        // Runs on every turn of the conversation to check if the conversation should be interrupted.
        protected async Task <DialogTurnResult> InterruptDialogAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            DialogTurnResult interrupted = null;
            var activity = innerDc.Context.Activity;

            if (activity.Type == ActivityTypes.Message && !string.IsNullOrEmpty(activity.Text))
            {
                // Get connected LUIS result from turn state.
                var generalResult = innerDc.Context.TurnState.Get <General>(StateProperties.GeneralLuisResult);
                (var generalIntent, var generalScore) = generalResult.TopIntent();

                if (generalScore > 0.5)
                {
                    switch (generalIntent)
                    {
                    case General.Intent.Cancel:
                    {
                        var state = await _conversationStateAccessor.GetAsync(innerDc.Context, () => new RestaurantBookingState(), cancellationToken);

                        state.Clear();

                        await innerDc.Context.SendActivityAsync(_localeTemplateManager.GenerateActivity(RestaurantBookingSharedResponses.CancellingMessage), cancellationToken);

                        await innerDc.CancelAllDialogsAsync(cancellationToken);

                        if (innerDc.Context.IsSkill())
                        {
                            interrupted = await innerDc.EndDialogAsync(state.IsAction?new ActionResult { ActionSuccess = false } : null, cancellationToken);
                        }
                        else
                        {
                            interrupted = await innerDc.BeginDialogAsync(InitialDialogId, cancellationToken : cancellationToken);
                        }

                        break;
                    }

                    case General.Intent.Help:
                    {
                        await innerDc.Context.SendActivityAsync(_localeTemplateManager.GenerateActivity(RestaurantBookingMainResponses.HelpMessage), cancellationToken);

                        await innerDc.RepromptDialogAsync(cancellationToken);

                        interrupted = EndOfTurn;
                        break;
                    }
                    }
                }
            }

            return(interrupted);
        }
Пример #8
0
        // Runs on every turn of the conversation to check if the conversation should be interrupted.
        protected async Task <DialogTurnResult> InterruptDialogAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            DialogTurnResult interrupted = null;
            var activity = innerDc.Context.Activity;

            if (activity.Type == ActivityTypes.Message && !string.IsNullOrEmpty(activity.Text))
            {
                // Get connected LUIS result from turn state.
                var generalResult = innerDc.Context.TurnState.Get <General>(StateProperties.GeneralLuisResult);
                (var generalIntent, var generalScore) = generalResult.TopIntent();

                if (generalScore > 0.5)
                {
                    switch (generalIntent)
                    {
                    case General.Intent.Cancel:
                    {
                        await innerDc.Context.SendActivityAsync(_templateManager.GenerateActivityForLocale(MainStrings.CANCELLED), cancellationToken);

                        await innerDc.CancelAllDialogsAsync(cancellationToken);

                        if (innerDc.Context.IsSkill())
                        {
                            var state = await _stateAccessor.GetAsync(innerDc.Context, () => new NewsSkillState(), cancellationToken : cancellationToken);

                            interrupted = await innerDc.EndDialogAsync(state.IsAction?new ActionResult(false) : null, cancellationToken : cancellationToken);
                        }
                        else
                        {
                            interrupted = await innerDc.BeginDialogAsync(InitialDialogId, cancellationToken : cancellationToken);
                        }

                        break;
                    }

                    case General.Intent.Help:
                    {
                        await innerDc.Context.SendActivityAsync(HeroCardResponses.SendHelpCard(innerDc.Context, _templateManager), cancellationToken);

                        await innerDc.RepromptDialogAsync(cancellationToken);

                        interrupted = EndOfTurn;
                        break;
                    }
                    }
                }
            }

            return(interrupted);
        }
Пример #9
0
        protected override async Task RouteAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
        {
            // get current activity locale
            var locale       = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
            var localeConfig = _services.CognitiveModelSets[locale];

            // Populate state from SkillContext slots as required
            await PopulateStateFromSkillContext(dc.Context);

            // Get skill LUIS model from configuration
            localeConfig.LuisServices.TryGetValue("BingSearchSkill", out var luisService);

            if (luisService == null)
            {
                throw new Exception("The specified LUIS Model could not be found in your Bot Services configuration.");
            }
            else
            {
                var turnResult = EndOfTurn;
                var result     = await luisService.RecognizeAsync <BingSearchSkillLuis>(dc.Context, CancellationToken.None);

                var intent = result?.TopIntent().intent;

                switch (intent)
                {
                case BingSearchSkillLuis.Intent.GetCelebrityInfo:
                case BingSearchSkillLuis.Intent.SearchMovieInfo:
                case BingSearchSkillLuis.Intent.None:
                {
                    turnResult = await dc.BeginDialogAsync(nameof(SearchDialog));

                    break;
                }

                default:
                {
                    // intent was identified but not yet implemented
                    await dc.Context.SendActivityAsync(_responseManager.GetResponse(MainResponses.FeatureNotAvailable));

                    turnResult = new DialogTurnResult(DialogTurnStatus.Complete);
                    break;
                }
                }

                if (turnResult != EndOfTurn)
                {
                    await CompleteAsync(dc);
                }
            }
        }
        public static async Task Run(this Dialog dialog, ITurnContext turnContext, IStatePropertyAccessor <DialogState> dialogAccessor, CancellationToken cancellationToken = default(CancellationToken))
        {
            DialogSet dialogSet = new DialogSet(dialogAccessor);

            dialogSet.Add(dialog);

            DialogContext dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken);

            DialogTurnResult results = await dialogContext.ContinueDialogAsync(cancellationToken);

            if (results.Status == DialogTurnStatus.Empty)
            {
                await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken);
            }
        }
Пример #11
0
        protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            DialogSet dialogSet = new DialogSet(_conversationState.CreateProperty <DialogState>("HeroState"));

            dialogSet.Add(_dialog);
            DialogContext dialogContext =
                await dialogSet.CreateContextAsync(turnContext, cancellationToken);

            DialogTurnResult results =
                await dialogContext.ContinueDialogAsync(cancellationToken);

            if (results.Status == DialogTurnStatus.Empty)
            {
                await dialogContext.BeginDialogAsync(_dialog.Id, null, cancellationToken);
            }
        }
Пример #12
0
        protected TestFlow CreateTestFlow(string dialogName, bool userConsentGiven = true)
        {
            return(new TestFlow(this.adapter, async(turnContext, cancellationToken) =>
            {
                this.turnContext = turnContext;
                this.cancellationToken = cancellationToken;

                if (turnContext.Activity.Type == ActivityTypes.Message)
                {
                    // Initialize the dialog context.
                    DialogContext dialogContext = await this.dialogs.CreateContextAsync(turnContext, cancellationToken);

                    // Make sure this channel is supported.
                    if (!Phrases.ValidChannels.Contains(turnContext.Activity.ChannelId))
                    {
                        await Messages.SendAsync(Phrases.Greeting.InvalidChannel(turnContext), turnContext, cancellationToken);
                        return;
                    }

                    // Create the master dialog.
                    var masterDialog = new MasterDialog(this.state, this.dialogs, this.Api, this.Configuration);

                    // If the user sends the update keyword, clear the dialog stack and start a new update.
                    if (string.Equals(turnContext.Activity.Text, Phrases.Keywords.Update, StringComparison.OrdinalIgnoreCase))
                    {
                        dialogName = MasterDialog.Name;
                        await dialogContext.CancelAllDialogsAsync(cancellationToken);
                    }

                    // Attempt to continue any existing conversation.
                    DialogTurnResult result = await masterDialog.ContinueDialogAsync(dialogContext, cancellationToken);

                    // Start a new conversation if there isn't one already.
                    if (result.Status == DialogTurnStatus.Empty)
                    {
                        // Clear the user context when a new conversation begins.
                        await this.state.ClearUserContext(dialogContext.Context, cancellationToken);

                        // Tests must init the user once there is a turn context.
                        await InitUser(userConsentGiven);

                        // Difference for tests here is beginning the given dialog instead of master so that individual dialog flows can be tested.
                        await masterDialog.BeginDialogAsync(dialogContext, dialogName, null, cancellationToken);
                    }
                }
            }));
        }
Пример #13
0
        protected override async Task CompleteAsync(DialogContext dc, DialogTurnResult result = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (_skillMode)
            {
                var response = dc.Context.Activity.CreateReply();
                response.Type = ActivityTypes.EndOfConversation;

                await dc.Context.SendActivityAsync(response);
            }
            else
            {
                await dc.Context.SendActivityAsync(dc.Context.Activity.CreateReply(EmailSharedResponses.ActionEnded));
            }

            // End active dialog
            await dc.EndDialogAsync(result);
        }
Пример #14
0
        /// <summary>
        /// Complete the conversation.
        /// </summary>
        /// <param name="dc">Current dialog context.</param>
        /// <param name="result">Result returned when dialog completed.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Completed Task.</returns>
        protected override async Task CompleteAsync(DialogContext dc, DialogTurnResult result = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (result?.Result != null && result.Result.ToString() == "StartNew")
            {
                await this.RouteAsync(dc);
            }
            else
            {
                var response = dc.Context.Activity.CreateReply();
                response.Type = ActivityTypes.EndOfConversation;

                await dc.Context.SendActivityAsync(response);

                // End active dialog
                await dc.EndDialogAsync(result);
            }
        }
        /// <summary>
        /// Forward an inbound activity on to the Skill. This is a synchronous operation whereby all response activities are aggregated and returned in one batch.
        /// </summary>
        /// <param name="innerDc">Inner DialogContext.</param>
        /// <param name="activity">Activity.</param>
        /// <returns>DialogTurnResult.</returns>
        private async Task <DialogTurnResult> ForwardToSkillAsync(DialogContext innerDc, Activity activity)
        {
            try
            {
                var handoffActivity = await _skillTransport.ForwardToSkillAsync(_skillManifest, _serviceClientCredentials, innerDc.Context, activity, GetTokenRequestCallback(innerDc)).ConfigureAwait(false);

                if (handoffActivity != null)
                {
                    await innerDc.Context.SendActivityAsync(new Activity(type : ActivityTypes.Trace, text : $"<--Ending the skill conversation with the {_skillManifest.Name} Skill and handing off to Parent Bot.")).ConfigureAwait(false);

                    return(await innerDc.EndDialogAsync(handoffActivity.SemanticAction?.Entities).ConfigureAwait(false));
                }
                else if (_authDialogCancelled)
                {
                    // cancel remote skill dialog if AuthDialog is cancelled
                    await _skillTransport.CancelRemoteDialogsAsync(_skillManifest, _serviceClientCredentials, innerDc.Context).ConfigureAwait(false);

                    await innerDc.Context.SendActivityAsync(new Activity(type : ActivityTypes.Trace, text : $"<--Ending the skill conversation with the {_skillManifest.Name} Skill and handing off to Parent Bot due to unable to obtain token for user.")).ConfigureAwait(false);

                    return(await innerDc.EndDialogAsync().ConfigureAwait(false));
                }
                else
                {
                    var dialogResult = new DialogTurnResult(DialogTurnStatus.Waiting);

                    // if there's any response we need to send to the skill queued
                    // forward to skill and start a new turn
                    while (_queuedResponses.Count > 0)
                    {
                        var lastEvent = _queuedResponses.Dequeue();
                        dialogResult = await ForwardToSkillAsync(innerDc, lastEvent).ConfigureAwait(false);
                    }

                    return(dialogResult);
                }
            }
            catch
            {
                // Something went wrong forwarding to the skill, so end dialog cleanly and throw so the error is logged.
                // NOTE: errors within the skill itself are handled by the OnTurnError handler on the adapter.
                await innerDc.EndDialogAsync().ConfigureAwait(false);

                throw;
            }
        }
Пример #16
0
        private async Task <DialogTurnResult> entityIntentPrompt(
            WaterfallStepContext step,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            DialogTurnResult returnResult = new DialogTurnResult(0);

            if (step.Options == null)
            {
                FoundChoice entity = (FoundChoice)step.Result;
                ((BotUserEntityContext)step.Values[DialogKey]).entity = entity.Value;
                //Custom Code Start | Removed Block
                //List<string> entityIntents = _navigationEntityData.CrudActionForEntities(entity.Value.ToString());
                //entityIntents.Add("Find");

                //returnResult = await step.PromptAsync(
                //    ChoicesPromptId,
                //    new PromptOptions
                //    {
                //        Prompt = MessageFactory.Text($"With the {entity.Value} I can do the following things.Please select one."),
                //        RetryPrompt = MessageFactory.Text("Please choose an option from the list."),
                //        Choices = ChoiceFactory.ToChoices(entityIntents),
                //    },
                //    cancellationToken);
                //Custom Code End
                //Custom Code Start | Added Code Block
                ((BotUserEntityContext)step.Values[DialogKey]).entityIntent = "Create";
                return(await step.EndDialogAsync(
                           (BotUserEntityContext)step.Values[DialogKey],
                           cancellationToken));

                //Custom Code End
            }
            else
            {
                FoundChoice entityintent = (FoundChoice)step.Result;
                ((BotUserEntityContext)step.Values[DialogKey]).entityIntent = entityintent.Value;


                returnResult = await step.EndDialogAsync(
                    (BotUserEntityContext)step.Values[DialogKey],
                    cancellationToken);
            }

            return(returnResult);
        }
Пример #17
0
        /// <summary>
        /// Every conversation turn for our Echo Bot will call this method.
        /// There are no dialogs used, since it's "single turn" processing, meaning a single
        /// request and response.
        /// </summary>
        /// <param name="turnContext">A <see cref="ITurnContext"/> containing all the data needed
        /// for processing this conversation turn. </param>
        /// <param name="cancellationToken">(Optional) A <see cref="CancellationToken"/> that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> that represents the work queued to execute.</returns>
        /// <seealso cref="BotStateSet"/>
        /// <seealso cref="ConversationState"/>
        /// <seealso cref="IMiddleware"/>

        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                DialogContext dc = await _dialogs.CreateContextAsync(turnContext, cancellationToken);

                // Get the state properties from the turn context.
                CustomerInfo userProfile =
                    await _accessors.CustomerInfoAccessor.GetAsync(turnContext, () => new CustomerInfo());

                // Continue any current dialog.
                DialogTurnResult dialogTurnResult = await dc.ContinueDialogAsync();

                if (dialogTurnResult.Result is null)
                {
                    // Get the intent recognition result
                    var recognizerResult = await botServices.LuisServices["AMAAirlinesDispatch"].RecognizeAsync(turnContext, cancellationToken);
                    var topIntent        = recognizerResult?.GetTopScoringIntent();

                    if (topIntent == null)
                    {
                        await turnContext.SendActivityAsync("Unable to get the top intent.");
                    }
                    else
                    {
                        await DispatchToTopIntentAsync(turnContext, dc, topIntent, cancellationToken);
                    }
                }
            }
            else if (turnContext.Activity.Type == ActivityTypes.ConversationUpdate)
            {
                // Send a welcome message to the user and tell them what actions they may perform to use this bot
                if (turnContext.Activity.MembersAdded != null)
                {
                    await SendWelcomeMessageAsync(turnContext, cancellationToken);
                }
            }

            // Save the new turn count into the conversation state.
            await _accessors.UserState.SaveChangesAsync(turnContext, false, cancellationToken);

            await _accessors.ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
        }
Пример #18
0
        protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            DialogContext dc = await Dialogs.CreateContextAsync(turnContext, cancellationToken);

            // Continue any current dialog.
            DialogTurnResult dialogTurnResult = await dc.ContinueDialogAsync();

            if (dialogTurnResult.Result is null)
            {
                // First, we use the dispatch model to determine which cognitive service (LUIS or QnA) to use.
                var recognizerResult = await _botServices.FoodDispatch.RecognizeAsync(turnContext, cancellationToken);

                // Top intent tell us which cognitive service to use.
                var topIntent = recognizerResult.GetTopScoringIntent();

                // Next, we call the dispatcher with the top intent.
                await DispatchToTopIntentAsync(turnContext, dc, topIntent.intent, recognizerResult, cancellationToken);
            }
        }
Пример #19
0
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
        {
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                // Establish context for our dialog from the turn context.
                DialogContext dialogContext = await this.dialogs.CreateContextAsync(turnContext, cancellationToken);

                // Make sure this channel is supported.
                if (!Phrases.ValidChannels.Contains(turnContext.Activity.ChannelId))
                {
                    await Messages.SendAsync(Phrases.Greeting.InvalidChannel(turnContext), turnContext, cancellationToken);

                    return;
                }

                var schemaError = Helpers.ValidateSchema();
                if (!string.IsNullOrEmpty(schemaError))
                {
                    await Messages.SendAsync(Phrases.Greeting.InvalidSchema(schemaError), turnContext, cancellationToken);

                    return;
                }

                // Create the master dialog.
                var masterDialog = new MasterDialog(this.state, this.dialogs, this.api, this.configuration);

                // If the user sends the update keyword, clear the dialog stack and start a new session.
                if (string.Equals(turnContext.Activity.Text, Phrases.Keywords.Update, StringComparison.OrdinalIgnoreCase))
                {
                    await dialogContext.CancelAllDialogsAsync(cancellationToken);
                }

                // Attempt to continue any existing conversation.
                DialogTurnResult result = await masterDialog.ContinueDialogAsync(dialogContext, cancellationToken);

                // Start a new conversation if there isn't one already.
                if (result.Status == DialogTurnStatus.Empty)
                {
                    await masterDialog.BeginDialogAsync(dialogContext, MasterDialog.Name, null, cancellationToken);
                }
            }
        }
Пример #20
0
        /// <summary>
        /// Every conversation turn calls this method.
        /// </summary>
        /// <param name="turnContext">A <see cref="ITurnContext"/> containing all the data needed
        /// for processing this conversation turn. </param>
        /// <param name="cancellationToken">(Optional) A <see cref="CancellationToken"/> that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> that represents the work queued to execute.</returns>
        /// <seealso cref="BotStateSet"/>
        /// <seealso cref="ConversationState"/>
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            // Handle Message activity type, which is the main activity type for shown within a conversational interface
            // Message activities may contain text, speech, interactive cards, and binary or unknown attachments.
            // see https://aka.ms/about-bot-activity-message to learn more about the message and other activity types
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                DialogContext dialogContext = await _dialogs.CreateContextAsync(turnContext, cancellationToken);

                DialogTurnResult results = await dialogContext.ContinueDialogAsync(cancellationToken);

                switch (results.Status)
                {
                case DialogTurnStatus.Cancelled:
                case DialogTurnStatus.Empty:
                    await dialogContext.BeginDialogAsync(_dialogHelper.ActiveLearningDialogName, _qnaMakerOptions, cancellationToken);

                    break;

                case DialogTurnStatus.Complete:
                    break;

                case DialogTurnStatus.Waiting:
                    // If there is an active dialog, we don't need to do anything here.
                    break;
                }

                await _accessors.ConversationState.SaveChangesAsync(turnContext);
            }
            else if (turnContext.Activity.Type == ActivityTypes.ConversationUpdate)
            {
                if (turnContext.Activity.MembersAdded != null)
                {
                    // Send a welcome message to the user and tell them what actions they may perform to use this bot
                    await SendWelcomeMessageAsync(turnContext, cancellationToken);
                }
            }
            else
            {
                await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected", cancellationToken : cancellationToken);
            }
        }
Пример #21
0
        public static async Task Run(this Dialog dialog, ITurnContext turnContext, IStatePropertyAccessor <DialogState> accessor, CancellationToken cancellationToken)
        {
            //Creo un dialog set a partir del accesor de state
            DialogSet dialogSet = new DialogSet(accessor);

            //Agrego el dialogo actual al set
            dialogSet.Add(dialog);

            //Creo un dialo context a parti del turn
            DialogContext dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken);

            //Obtengo el resultado de continuar con el dialogo actual
            DialogTurnResult result = await dialogContext.ContinueDialogAsync(cancellationToken);

            //Si no hay ningun dialogo corriendo, iniciamos el actual
            if (result.Status == DialogTurnStatus.Empty)
            {
                await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken);
            }
        }
Пример #22
0
        private async Task <DialogTurnResult> modulePrompt(
            WaterfallStepContext step,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            step.Values[DialogKey] = _botUserEntityContext;
            DialogTurnResult returnResult = new DialogTurnResult(0);

            if (step.Options == null)
            {
                List <string> modules = new List <string>();
                _navigationEntityData.NavigationModules().ToList()
                .ForEach(k => modules.Add(k.ToString()));

                returnResult = await step.PromptAsync(
                    ChoicesPromptId,
                    new PromptOptions
                {
                    Prompt      = MessageFactory.Text("I know about the following areas. Please choose one that I can help with."),
                    RetryPrompt = MessageFactory.Text("Please choose an option from the list."),
                    Choices     = ChoiceFactory.ToChoices(modules),
                },
                    cancellationToken);
            }
            else
            {
                step.Values[DialogKeyOptions] = (BotUserEntityContext)step.Options;
                List <string> branchOptions = _navigationEntityData.BranchEntitiesForEntity(((BotUserEntityContext)step.Options).entity);

                returnResult = await step.PromptAsync(
                    ChoicesPromptId,
                    new PromptOptions
                {
                    Prompt      = MessageFactory.Text("What would like to do next?."),
                    RetryPrompt = MessageFactory.Text("Please choose an option from the list."),
                    Choices     = ChoiceFactory.ToChoices(branchOptions),
                },
                    cancellationToken);
            }
            return(returnResult);
        }
Пример #23
0
        private bool ShouldEndDialog(DialogTurnResult turnResult, out DialogTurnResult finalTurnResult)
        {
            finalTurnResult = turnResult;

            // Insure BreakLoop ends the dialog
            if (finalTurnResult.Status == DialogTurnStatus.Complete &&
                finalTurnResult.Result is ActionScopeResult asr &&
                asr.ActionScopeCommand == ActionScopeCommands.BreakLoop)
            {
                return(true);
            }

            // If a descendant dialog multiple levels below this container ended stack processing,
            // the result will be nested.
            while (finalTurnResult.Result != null &&
                   finalTurnResult.Result is DialogTurnResult dtr &&
                   dtr.ParentEnded && dtr.Status == DialogTurnStatus.Complete)
            {
                finalTurnResult = dtr;
            }

            return(finalTurnResult.ParentEnded && finalTurnResult.Status == DialogTurnStatus.Complete);
        }
Пример #24
0
        public async override Task <DialogTurnResult> ContinueDialogAsync(DialogContext outerDc, CancellationToken cancellationToken = default(CancellationToken))
        {
            DialogTurnResult turnResult = null;

            try
            {
                turnResult = await base.ContinueDialogAsync(outerDc, cancellationToken);

                if (turnResult.Status == DialogTurnStatus.Complete)
                {
                    await ResumeAfterHotelsFormDialog(outerDc, turnResult.Result as HotelsQuery);
                }
            }
            catch (FormCanceledException <HotelsQuery> )
            {
                //user cancelled, ignore the exception
                await outerDc.Context.SendActivityAsync("Okay, cancelled.");

                turnResult = new DialogTurnResult(DialogTurnStatus.Cancelled);
                await outerDc.EndDialogAsync(cancellationToken);
            }
            return(turnResult);
        }
Пример #25
0
        private async Task Complete(DialogTurnResult dialogResult, DialogContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            switch (dialogResult.Status)
            {
            case DialogTurnStatus.Waiting:
                // The active dialog is waiting for a response from the user, so do nothing.
                break;

            case DialogTurnStatus.Complete:
                await context.EndDialogAsync();

                break;

            default:
                await context.CancelAllDialogsAsync();

                break;
            }
        }
Пример #26
0
        /// <summary>
        /// Every conversation turn calls this method.
        /// </summary>
        /// <param name="turnContext">A <see cref="ITurnContext"/> containing all the data needed
        /// for processing this conversation turn. </param>
        /// <param name="cancellationToken">(Optional) A <see cref="CancellationToken"/> that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> that represents the work queued to execute.</returns>
        /// <seealso cref="BotStateSet"/>
        /// <seealso cref="ConversationState"/>
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            // Get the state properties from the turn context.

            ConversationData conversationData = await _accessors.ConversationDataAccessor.GetAsync(turnContext, () => new ConversationData());

            // Get the user's info.
            UserInfo userInfo = await _accessors.UserInfoAccessor.GetAsync(turnContext, () => new UserInfo(), cancellationToken);

            _logger.LogInformation(turnContext.Activity.Type);

            // Establish dialog state from the conversation state.
            DialogContext dc = await _dialogs.CreateContextAsync(turnContext, cancellationToken);

            // Handle Message activity type, which is the main activity type for shown within a conversational interface
            // Message activities may contain text, speech, interactive cards, and binary or unknown attachments.
            // see https://aka.ms/about-bot-activity-message to learn more about the message and other activity types
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                // Continue any current dialog.
                DialogTurnResult dialogTurnResult = await dc.ContinueDialogAsync();

                // Process the result of any complete dialog.
                if (dialogTurnResult.Status is DialogTurnStatus.Complete)
                {
                    switch (dialogTurnResult.Result)
                    {
                    case GuestInfo guestInfo:
                        // Store the results of the greeting dialog.
                        userInfo.Guest = guestInfo;
                        await _accessors.UserInfoAccessor.SetAsync(turnContext, userInfo, cancellationToken);

                        // Show the main menu dialog
                        await dc.BeginDialogAsync(MainDialogId, null, cancellationToken);

                        break;

                    default:
                        // We shouldn't get here, since the main dialog is designed to loop.
                        break;
                    }
                }

                // Every dialog step sends a response, so if no response was sent,
                // then no dialog is currently active.
                else if (!turnContext.Responded)
                {
                    // Otherwise, start our bot's main dialog.
                    await dc.BeginDialogAsync(MainDialogId, null, cancellationToken);
                }
            }
            // Greet when users are added to the conversation.
            // Note that all channels do not send the conversation update activity.
            // If you find that this bot works in the emulator, but does not in
            // another channel the reason is most likely that the channel does not
            // send this activity.
            else if (turnContext.Activity.Type == ActivityTypes.ConversationUpdate)
            {
                _logger.LogInformation("Welcome Message Area");

                if (turnContext.Activity.MembersAdded != null)
                {
                    // Iterate over all new members added to the conversation
                    foreach (var member in turnContext.Activity.MembersAdded)
                    {
                        // Greet anyone that was not the target (recipient) of this message
                        // the 'bot' is the recipient for events from the channel,
                        // turnContext.Activity.MembersAdded == turnContext.Activity.Recipient.Id indicates the
                        // bot was added to the conversation.
                        if (member.Id != turnContext.Activity.Recipient.Id)
                        {
                            await turnContext.SendActivityAsync($"Hi there - {member.Name}. {WelcomeMessage}", cancellationToken : cancellationToken);

                            //await turnContext.SendActivityAsync($"What's your name?", cancellationToken: cancellationToken);

                            await dc.BeginDialogAsync(GreetingDialogId, null, cancellationToken);

                            // Can't start a dialog from ConversationUpdated
                            //await dc.BeginDialogAsync(MainDialogId, null, cancellationToken);
                        }
                    }
                }
            }

            // Save the new turn count into the conversation state.
            await _accessors.ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);

            await _accessors.UserState.SaveChangesAsync(turnContext, false, cancellationToken);
        }
Пример #27
0
        protected override async Task RouteAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await _toDoStateAccessor.GetAsync(dc.Context, () => new ToDoSkillState());

            // get current activity locale
            var locale       = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
            var localeConfig = _services.CognitiveModelSets[locale];

            // Initialize the PageSize and ReadSize parameters in state from configuration
            InitializeConfig(state);

            // If dispatch result is general luis model
            localeConfig.LuisServices.TryGetValue("todo", out var luisService);

            if (luisService == null)
            {
                throw new Exception("The specified LUIS Model could not be found in your Bot Services configuration.");
            }
            else
            {
                var turnResult       = EndOfTurn;
                var intent           = state.LuisResult?.TopIntent().intent;
                var generalTopIntent = state.GeneralLuisResult?.TopIntent().intent;

                // switch on general intents
                switch (intent)
                {
                case todoLuis.Intent.AddToDo:
                {
                    turnResult = await dc.BeginDialogAsync(nameof(AddToDoItemDialog));

                    break;
                }

                case todoLuis.Intent.MarkToDo:
                {
                    turnResult = await dc.BeginDialogAsync(nameof(MarkToDoItemDialog));

                    break;
                }

                case todoLuis.Intent.DeleteToDo:
                {
                    turnResult = await dc.BeginDialogAsync(nameof(DeleteToDoItemDialog));

                    break;
                }

                case todoLuis.Intent.ShowNextPage:
                case todoLuis.Intent.ShowPreviousPage:
                case todoLuis.Intent.ShowToDo:
                {
                    turnResult = await dc.BeginDialogAsync(nameof(ShowToDoItemDialog));

                    break;
                }

                case todoLuis.Intent.None:
                {
                    if (generalTopIntent == General.Intent.ShowNext ||
                        generalTopIntent == General.Intent.ShowPrevious)
                    {
                        turnResult = await dc.BeginDialogAsync(nameof(ShowToDoItemDialog));
                    }
                    else
                    {
                        // No intent was identified, send confused message
                        await dc.Context.SendActivityAsync(_responseManager.GetResponse(ToDoMainResponses.DidntUnderstandMessage));

                        turnResult = new DialogTurnResult(DialogTurnStatus.Complete);
                    }

                    break;
                }

                default:
                {
                    // intent was identified but not yet implemented
                    await dc.Context.SendActivityAsync(_responseManager.GetResponse(ToDoMainResponses.FeatureNotAvailable));

                    turnResult = new DialogTurnResult(DialogTurnStatus.Complete);

                    break;
                }
                }

                if (turnResult != EndOfTurn)
                {
                    await CompleteAsync(dc);
                }
            }
        }
Пример #28
0
 protected override async Task CompleteAsync(DialogContext dc, DialogTurnResult result = null, CancellationToken cancellationToken = default(CancellationToken))
 {
     // The active dialog's stack ended with a complete status
     await _responder.ReplyWith(dc.Context, MainResponses.ResponseIds.Completed);
 }
 /// <summary>
 /// Called when the inner dialog stack is complete.
 /// </summary>
 /// <param name="innerDc">The dialog context for the component.</param>
 /// <param name="result">The dialog result when inner dialog completed.</param>
 /// <param name="cancellationToken">The cancellation token.</param>
 /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
 protected virtual Task CompleteAsync(DialogContext innerDc, DialogTurnResult result = null, CancellationToken cancellationToken = default(CancellationToken))
 {
     innerDc.EndDialogAsync(result).Wait(cancellationToken);
     return(Task.CompletedTask);
 }
Пример #30
0
        // Every conversation turn for our Echo Bot will call this method.
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            // Handle Message activity type, which is the main activity type for shown within a conversational interface
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                // Establish dialog state from the conversation state.
                DialogContext dc = await _dialogs.CreateContextAsync(turnContext, cancellationToken);

                // Get the user's info.
                UserProfile userInfo = await _accessors.UserProfile.GetAsync(turnContext, () => new UserProfile(), cancellationToken);

                // ONGOING DIALOG CASE: Continue any current dialog.
                DialogTurnResult dialogTurnResult = await dc.ContinueDialogAsync();

                // COMPLETED DIALOG CASE: last result was EndDialogAsync, process the result of any complete dialog
                if (dialogTurnResult.Status is DialogTurnStatus.Complete)
                {
                    switch (dialogTurnResult.Result)
                    {
                    case UserProfile upResult:
                        // Store the results of FFHelloDialog
                        await _accessors.UserProfile.SetAsync(turnContext, upResult, cancellationToken);

                        //await _accessors.UserProfile.SetAsync(turnContext, upResult);

                        // now start our bot's main dialog.
                        await dc.BeginDialogAsync(MainDialogId, null, cancellationToken);

                        break;

                    default:
                        // We shouldn't get here, since the main dialog is designed to loop.
                        break;
                    }
                }

                // INACTIVE DIALOG CASE: Every dialog step sends a response, so if no response was sent,
                //      then no dialog is currently active.
                else if (!turnContext.Responded)
                {
                    if (string.IsNullOrEmpty(userInfo.UserName)) //string.IsNullOrEmpty(userInfo.Guest?.Name))
                    {
                        // If we don't yet have the guest's info, start the check-in dialog.
                        await dc.BeginDialogAsync(FFHelloDialogId, null, cancellationToken);
                    }
                    else
                    {
                        // Otherwise, start our bot's main dialog.
                        await dc.BeginDialogAsync(MainDialogId, null, cancellationToken);
                    }
                }

                // Save the new turn count into the conversation state.
                await _accessors.ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);

                await _accessors.UserState.SaveChangesAsync(turnContext, false, cancellationToken);
            }
            else
            {
                await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected");
            }
        }