/// <summary>
        /// Changes the backing object for the memory scope.
        /// </summary>
        /// <param name="dc">The <see cref="DialogContext"/> object for this turn.</param>
        /// <param name="memory">Memory object to set for the scope.</param>
        public override void SetMemory(DialogContext dc, object memory)
        {
            if (dc == null)
            {
                throw new ArgumentNullException(nameof(dc));
            }

            if (memory == null)
            {
                throw new ArgumentNullException(nameof(memory));
            }

            // if active dialog is a container dialog then "dialog" binds to it
            if (dc.ActiveDialog != null)
            {
                var dialog = dc.FindDialog(dc.ActiveDialog.Id);
                if (dialog is DialogContainer)
                {
                    dc.ActiveDialog.State = (IDictionary <string, object>)memory;
                    return;
                }
            }
            else if (dc.Parent?.ActiveDialog != null)
            {
                dc.Parent.ActiveDialog.State = (IDictionary <string, object>)memory;
                return;
            }
            else if (dc.ActiveDialog != null)
            {
                dc.ActiveDialog.State = (IDictionary <string, object>)memory;
            }

            throw new Exception("Cannot set DialogMemoryScope. There is no active dialog dialog or parent dialog in the context");
        }
예제 #2
0
        /// <summary>
        /// Gets the backing memory for this scope.
        /// </summary>
        /// <param name="dc">The <see cref="DialogContext"/> object for this turn.</param>
        /// <returns>Memory for the scope.</returns>
        public override object GetMemory(DialogContext dc)
        {
            if (dc == null)
            {
                throw new ArgumentNullException(nameof(dc));
            }

            // if active dialog is a container dialog then "dialogclass" binds to it.
            if (dc.ActiveDialog != null)
            {
                var dialog = dc.FindDialog(dc.ActiveDialog.Id);
                if (dialog is DialogContainer container && !container.IgnoreMemoryScopeBinding)
                {
                    return(new ReadOnlyObject(dialog));
                }
            }

            // Otherwise we always bind to parent, or if there is no parent the active dialog
            return(new ReadOnlyObject(dc.FindDialog(dc.Parent?.ActiveDialog?.Id ?? dc.ActiveDialog?.Id)));
        }
예제 #3
0
        protected Dialog ResolveDialog(DialogContext dc)
        {
            if (this.Dialog != null)
            {
                return(this.Dialog);
            }

            var dialogId = this.dialogIdToCall ?? throw new Exception($"{this.GetType().Name} requires a dialog to be called.");

            return(dc.FindDialog(dialogId) ?? throw new Exception($"{dialogId} not found."));
        }
        public override object GetMemory(DialogContext dc)
        {
            if (dc == null)
            {
                throw new ArgumentNullException(nameof(dc));
            }

            // if active dialog is a container dialog then "dialogclass" binds to it.
            if (dc.ActiveDialog != null)
            {
                var dialog = dc.FindDialog(dc.ActiveDialog.Id);
                if (dialog is DialogContainer)
                {
                    return(new ExpressionPropertyBinder(dc, dialog));
                }
            }

            // Otherwise we always bind to parent, or if there is no parent the active dialog
            return(new ExpressionPropertyBinder(dc, dc.FindDialog(dc.Parent?.ActiveDialog?.Id ?? dc.ActiveDialog?.Id)));
        }
예제 #5
0
        public override object GetMemory(DialogContext dc)
        {
            if (dc == null)
            {
                throw new ArgumentNullException(nameof(dc));
            }

            // if active dialog is a container dialog then "dialog" binds to it.
            if (dc.ActiveDialog != null)
            {
                var dialog = dc.FindDialog(dc.ActiveDialog.Id);
                if (dialog != null)
                {
                    return(new ReadOnlyObject(dialog));
                }
            }

            return(null);
        }
예제 #6
0
        IReadOnlyList <ICodePoint> ICodeModel.PointsFor(DialogContext dialogContext, object item, string more)
        {
            var frames = new List <CodePoint>();

            if (item != null)
            {
                var frame = new CodePoint(this, dialogContext, item, more);
                frames.Add(frame);
            }

            while (dialogContext != null)
            {
                foreach (var instance in dialogContext.Stack)
                {
                    var dialog = dialogContext.FindDialog(instance.Id);
                    var frame  = new CodePoint(this, dialogContext, dialog, null);
                    frames.Add(frame);
                }

                dialogContext = dialogContext.Parent;
            }

            return(frames);
        }
예제 #7
0
        private async Task <bool> InterruptDialogAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            var interrupted = false;
            var activity    = innerDc.Context.Activity;
            var dialog      = innerDc.ActiveDialog?.Id != null?innerDc.FindDialog(innerDc.ActiveDialog?.Id) : null;

            if (activity.Type == ActivityTypes.Message && !string.IsNullOrEmpty(activity.Text))
            {
                // Check if the active dialog is a skill for conditional interruption.
                var isSkill = dialog is TeamsSkillDialog;
                EnhancedBotFrameworkSkill identifiedSkill;
                var skillId = innerDc.Context.Activity.GetSkillId();
                // Get Dispatch LUIS result from turn state.
                var dispatchResult = innerDc.Context.TurnState.Get <DispatchLuis>(StateProperties.DispatchResult);
                (var dispatchIntent, var dispatchScore) = dispatchResult.TopIntent();

                // Check if skill id is present in activity payload
                if (!string.IsNullOrWhiteSpace(skillId))
                {
                    identifiedSkill = _skillsConfig.Skills.Where(s => s.Value.AppId == skillId).FirstOrDefault().Value;

                    // Check if skill identified through activity payload is not the current active skill
                    if (isSkill && !dialog.Id.Equals(identifiedSkill.Id))
                    {
                        await SwitchSkillPrompt(innerDc, identifiedSkill);

                        interrupted = true;
                    }
                }
                else
                {
                    // Check if we need to switch skills.
                    if (isSkill && IsSkillIntent(dispatchIntent) && dispatchIntent.ToString() != dialog.Id && dispatchScore > 0.9)
                    {
                        if (_skillsConfig.Skills.TryGetValue(dispatchIntent.ToString(), out identifiedSkill))
                        {
                            await SwitchSkillPrompt(innerDc, identifiedSkill);

                            interrupted = true;
                        }
                        else
                        {
                            throw new ArgumentException($"{dispatchIntent.ToString()} is not in the skills configuration");
                        }
                    }
                }

                if (dispatchIntent == DispatchLuis.Intent.l_General)
                {
                    // Get connected LUIS result from turn state.
                    var generalResult = innerDc.Context.TurnState.Get <GeneralLuis>(StateProperties.GeneralResult);
                    (var generalIntent, var generalScore) = generalResult.TopIntent();

                    if (generalScore > 0.5)
                    {
                        switch (generalIntent)
                        {
                        case GeneralLuis.Intent.Cancel:
                        {
                            if (!isSkill)
                            {
                                await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("CancelledMessage"));

                                await innerDc.CancelAllDialogsAsync();

                                interrupted = true;
                            }

                            break;
                        }

                        case GeneralLuis.Intent.Escalate:
                        {
                            await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("EscalateMessage"));

                            await innerDc.RepromptDialogAsync();

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Help:
                        {
                            if (!isSkill)
                            {
                                // If current dialog is a skill, allow it to handle its own help intent.
                                await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("HelpCard"));

                                await innerDc.RepromptDialogAsync();

                                interrupted = true;
                            }

                            break;
                        }

                        case GeneralLuis.Intent.Logout:
                        {
                            if (!isSkill)
                            {
                                // Log user out of all accounts.
                                await LogUserOut(innerDc);

                                await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("LogoutMessage"));

                                await innerDc.CancelAllDialogsAsync();

                                interrupted = true;
                            }

                            break;
                        }

                        case GeneralLuis.Intent.Repeat:
                        {
                            // Sends the activities since the last user message again.
                            var previousResponse = await _previousResponseAccessor.GetAsync(innerDc.Context, () => new List <Activity>());

                            foreach (var response in previousResponse)
                            {
                                // Reset id of original activity so it can be processed by the channel.
                                response.Id = string.Empty;
                                await innerDc.Context.SendActivityAsync(response);
                            }

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.StartOver:
                        {
                            await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("StartOverMessage"));

                            // Cancel all dialogs on the stack.
                            await innerDc.CancelAllDialogsAsync();

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Stop:
                        {
                            // Use this intent to send an event to your device that can turn off the microphone in speech scenarios.
                            break;
                        }
                        }
                    }
                }
            }

            return(interrupted);
        }
예제 #8
0
        // Runs on every turn of the conversation to check if the conversation should be interrupted.
        protected override async Task <InterruptionAction> OnInterruptDialogAsync(DialogContext dc, CancellationToken cancellationToken)
        {
            var activity    = dc.Context.Activity;
            var userProfile = await _userProfileState.GetAsync(dc.Context, () => new UserProfileState());

            var dialog = dc.ActiveDialog?.Id != null?dc.FindDialog(dc.ActiveDialog?.Id) : null;

            if (activity.Type == ActivityTypes.Message && !string.IsNullOrEmpty(activity.Text))
            {
                // Check if the active dialog is a skill for conditional interruption.
                var isSkill = dialog is SkillDialog;

                // Get Dispatch LUIS result from turn state.
                var dispatchResult = dc.Context.TurnState.Get <DispatchLuis>(StateProperties.DispatchResult);
                (var dispatchIntent, var dispatchScore) = dispatchResult.TopIntent();

                // Check if we need to switch skills.
                if (isSkill)
                {
                    if (dispatchIntent.ToString() != dialog.Id && dispatchScore > 0.9)
                    {
                        var identifiedSkill = SkillRouter.IsSkill(_settings.Skills, dispatchResult.TopIntent().intent.ToString());

                        if (identifiedSkill != null)
                        {
                            var prompt = _templateEngine.GenerateActivityForLocale("SkillSwitchPrompt", new { Skill = identifiedSkill.Name });
                            await dc.BeginDialogAsync(_switchSkillDialog.Id, new SwitchSkillDialogOptions(prompt, identifiedSkill));

                            return(InterruptionAction.Waiting);
                        }
                    }
                }

                if (dispatchIntent == DispatchLuis.Intent.l_General)
                {
                    // Get connected LUIS result from turn state.
                    var generalResult = dc.Context.TurnState.Get <GeneralLuis>(StateProperties.GeneralResult);
                    (var generalIntent, var generalScore) = generalResult.TopIntent();

                    if (generalScore > 0.5)
                    {
                        switch (generalIntent)
                        {
                        case GeneralLuis.Intent.Cancel:
                        {
                            // Suppress completion message for utility functions.
                            dc.SuppressCompletionMessage(true);

                            await dc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("CancelledMessage", userProfile));

                            await dc.CancelAllDialogsAsync();

                            return(InterruptionAction.End);
                        }

                        case GeneralLuis.Intent.Escalate:
                        {
                            await dc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("EscalateMessage", userProfile));

                            return(InterruptionAction.Resume);
                        }

                        case GeneralLuis.Intent.Help:
                        {
                            // Suppress completion message for utility functions.
                            dc.SuppressCompletionMessage(true);

                            if (isSkill)
                            {
                                // If current dialog is a skill, allow it to handle its own help intent.
                                await dc.ContinueDialogAsync(cancellationToken);

                                break;
                            }
                            else
                            {
                                await dc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("HelpCard", userProfile));

                                return(InterruptionAction.Resume);
                            }
                        }

                        case GeneralLuis.Intent.Logout:
                        {
                            // Suppress completion message for utility functions.
                            dc.SuppressCompletionMessage(true);

                            // Log user out of all accounts.
                            await LogUserOut(dc);

                            await dc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("LogoutMessage", userProfile));

                            return(InterruptionAction.End);
                        }

                        case GeneralLuis.Intent.Repeat:
                        {
                            // No need to send the usual dialog completion message for utility capabilities such as these.
                            dc.SuppressCompletionMessage(true);

                            // Sends the activities since the last user message again.
                            var previousResponse = await _previousResponseAccessor.GetAsync(dc.Context, () => new List <Activity>());

                            foreach (var response in previousResponse)
                            {
                                // Reset id of original activity so it can be processed by the channel.
                                response.Id = string.Empty;
                                await dc.Context.SendActivityAsync(response);
                            }

                            return(InterruptionAction.Waiting);
                        }

                        case GeneralLuis.Intent.StartOver:
                        {
                            // Suppresss completion message for utility functions.
                            dc.SuppressCompletionMessage(true);

                            await dc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("StartOverMessage", userProfile));

                            // Cancel all dialogs on the stack.
                            await dc.CancelAllDialogsAsync();

                            return(InterruptionAction.End);
                        }

                        case GeneralLuis.Intent.Stop:
                        {
                            // Use this intent to send an event to your device that can turn off the microphone in speech scenarios.
                            break;
                        }
                        }
                    }
                }
            }

            return(InterruptionAction.NoAction);
        }
예제 #9
0
        private async Task <bool> InterruptDialogAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            var interrupted = false;
            var activity    = innerDc.Context.Activity;
            var userProfile = await _userProfileState.GetAsync(innerDc.Context, () => new UserProfileState());

            var dialog = innerDc.ActiveDialog?.Id != null?innerDc.FindDialog(innerDc.ActiveDialog?.Id) : null;

            if (activity.Type == ActivityTypes.Message && !string.IsNullOrEmpty(activity.Text))
            {
                // Check if the active dialog is a skill for conditional interruption.
                var isSkill = dialog is SkillDialog;

                // Get Dispatch LUIS result from turn state.
                var dispatchResult = innerDc.Context.TurnState.Get <DispatchLuis>(StateProperties.DispatchResult);
                (var dispatchIntent, var dispatchScore) = dispatchResult.TopIntent();

                // Check if we need to switch skills.
                if (isSkill && IsSkillIntent(dispatchIntent) && dispatchIntent.ToString() != dialog.Id && dispatchScore > 0.9)
                {
                    EnhancedBotFrameworkSkill identifiedSkill;
                    if (_skillsConfig.Skills.TryGetValue(dispatchIntent.ToString(), out identifiedSkill))
                    {
                        var prompt = MessageFactory.Text($"Would you like to switch to the {identifiedSkill.Name}?");//_templateEngine.GenerateActivityForLocale("SkillSwitchPrompt", new { Skill = identifiedSkill.Name });
                        await innerDc.BeginDialogAsync(_switchSkillDialog.Id, new SwitchSkillDialogOptions(prompt, identifiedSkill));

                        interrupted = true;
                    }
                    else
                    {
                        throw new ArgumentException($"{dispatchIntent.ToString()} is not in the skills configuration");
                    }
                }

                if (dispatchIntent == DispatchLuis.Intent.l_General)
                {
                    // Get connected LUIS result from turn state.
                    var generalResult = innerDc.Context.TurnState.Get <GeneralLuis>(StateProperties.GeneralResult);
                    (var generalIntent, var generalScore) = generalResult.TopIntent();

                    if (generalScore > 0.5)
                    {
                        switch (generalIntent)
                        {
                        case GeneralLuis.Intent.Cancel:
                        {
                            await innerDc.Context.SendActivityAsync("CANCEL");

                            await innerDc.CancelAllDialogsAsync();

                            await innerDc.BeginDialogAsync(InitialDialogId);

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Escalate:
                        {
                            await innerDc.Context.SendActivityAsync("ESCALLATE");

                            await innerDc.RepromptDialogAsync();

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Help:
                        {
                            if (!isSkill)
                            {
                                // If current dialog is a skill, allow it to handle its own help intent.
                                await innerDc.Context.SendActivityAsync("HELP");

                                await innerDc.RepromptDialogAsync();

                                interrupted = true;
                            }

                            break;
                        }

                        case GeneralLuis.Intent.Logout:
                        {
                            // Log user out of all accounts.
                            await LogUserOut(innerDc);

                            await innerDc.Context.SendActivityAsync("LOGOUT");

                            await innerDc.CancelAllDialogsAsync();

                            await innerDc.BeginDialogAsync(InitialDialogId);

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Repeat:
                        {
                            // Sends the activities since the last user message again.
                            var previousResponse = await _previousResponseAccessor.GetAsync(innerDc.Context, () => new List <Activity>());

                            foreach (var response in previousResponse)
                            {
                                // Reset id of original activity so it can be processed by the channel.
                                response.Id = string.Empty;
                                await innerDc.Context.SendActivityAsync(response);
                            }

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.StartOver:
                        {
                            await innerDc.Context.SendActivityAsync("START OVER");

                            // Cancel all dialogs on the stack.
                            await innerDc.CancelAllDialogsAsync();

                            await innerDc.BeginDialogAsync(InitialDialogId);

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Stop:
                        {
                            // Use this intent to send an event to your device that can turn off the microphone in speech scenarios.
                            break;
                        }
                        }
                    }
                }
            }

            return(interrupted);
        }
예제 #10
0
        private async Task <bool> InterruptDialogAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            var interrupted = false;
            var activity    = innerDc.Context.Activity;
            var userProfile = await _userProfileState.GetAsync(innerDc.Context, () => new UserProfileState(), cancellationToken);

            var dialog = innerDc.ActiveDialog?.Id != null?innerDc.FindDialog(innerDc.ActiveDialog?.Id) : null;

            if (activity.Type == ActivityTypes.Message && !string.IsNullOrEmpty(activity.Text))
            {
                // Check if the active dialog is a skill for conditional interruption.
                var isSkill = dialog is SkillDialog;

                // Get Dispatch LUIS result from turn state.
                var dispatchResult = innerDc.Context.TurnState.Get <DispatchLuis>(StateProperties.DispatchResult);
                (var dispatchIntent, var dispatchScore) = dispatchResult.TopIntent();

                // Check if we need to switch skills.
                if (isSkill && IsSkillIntent(dispatchIntent) && dispatchIntent.ToString() != dialog.Id && dispatchScore > 0.9)
                {
                    if (_skillsConfig.Skills.TryGetValue(dispatchIntent.ToString(), out var identifiedSkill))
                    {
                        var prompt = _templateManager.GenerateActivityForLocale("SkillSwitchPrompt", new { Skill = identifiedSkill.Name });
                        await innerDc.BeginDialogAsync(_switchSkillDialog.Id, new SwitchSkillDialogOptions(prompt, identifiedSkill), cancellationToken);

                        interrupted = true;
                    }
                    else
                    {
                        throw new ArgumentException($"{dispatchIntent.ToString()} is not in the skills configuration");
                    }
                }

                if (dispatchIntent == DispatchLuis.Intent.l_General)
                {
                    // Get connected LUIS result from turn state.
                    var generalResult = innerDc.Context.TurnState.Get <GeneralLuis>(StateProperties.GeneralResult);
                    (var generalIntent, var generalScore) = generalResult.TopIntent();

                    if (generalScore > 0.5)
                    {
                        switch (generalIntent)
                        {
                        case GeneralLuis.Intent.Cancel:
                        {
                            await innerDc.Context.SendActivityAsync(_templateManager.GenerateActivityForLocale("CancelledMessage", userProfile), cancellationToken);

                            await innerDc.CancelAllDialogsAsync(cancellationToken);

                            await innerDc.BeginDialogAsync(InitialDialogId, cancellationToken : cancellationToken);

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Escalate:
                        {
                            var conversationState          = _serviceProvider.GetService <ConversationState>();
                            var conversationStateAccessors = conversationState.CreateProperty <LoggingConversationData>(nameof(LoggingConversationData));
                            var conversationData           = await conversationStateAccessors.GetAsync(innerDc.Context, () => new LoggingConversationData());

                            await innerDc.Context.SendActivityAsync(_templateManager.GenerateActivityForLocale("EscalateMessage", userProfile), cancellationToken);

                            var transcript = new Transcript(conversationData.ConversationLog.Where(a => a.Type == ActivityTypes.Message).ToList());

                            var evnt = EventFactory.CreateHandoffInitiation(innerDc.Context,
                                                                            new
                                {
                                    Skill = "Expert Help",
                                    EngagementAttributes = new EngagementAttribute[]
                                    {
                                        new EngagementAttribute {
                                            Type = "ctmrinfo", CustomerType = "vip", SocialId = "123456789"
                                        },
                                        new EngagementAttribute {
                                            Type = "personal", FirstName = innerDc.Context.Activity.From.Name
                                        }
                                    }
                                },
                                                                            transcript);

                            await innerDc.Context.SendActivityAsync(evnt);

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Help:
                        {
                            if (!isSkill)
                            {
                                // If current dialog is a skill, allow it to handle its own help intent.
                                await innerDc.Context.SendActivityAsync(_templateManager.GenerateActivityForLocale("HelpCard", userProfile), cancellationToken);

                                await innerDc.RepromptDialogAsync(cancellationToken);

                                interrupted = true;
                            }

                            break;
                        }

                        case GeneralLuis.Intent.Logout:
                        {
                            // Log user out of all accounts.
                            await LogUserOutAsync(innerDc, cancellationToken);

                            await innerDc.Context.SendActivityAsync(_templateManager.GenerateActivityForLocale("LogoutMessage", userProfile), cancellationToken);

                            await innerDc.CancelAllDialogsAsync(cancellationToken);

                            await innerDc.BeginDialogAsync(InitialDialogId, cancellationToken : cancellationToken);

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Repeat:
                        {
                            // Sends the activities since the last user message again.
                            var previousResponse = await _previousResponseAccessor.GetAsync(innerDc.Context, () => new List <Activity>(), cancellationToken);

                            foreach (var response in previousResponse)
                            {
                                // Reset id of original activity so it can be processed by the channel.
                                response.Id = string.Empty;
                                await innerDc.Context.SendActivityAsync(response, cancellationToken);
                            }

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.StartOver:
                        {
                            await innerDc.Context.SendActivityAsync(_templateManager.GenerateActivityForLocale("StartOverMessage", userProfile), cancellationToken);

                            // Cancel all dialogs on the stack.
                            await innerDc.CancelAllDialogsAsync(cancellationToken);

                            await innerDc.BeginDialogAsync(InitialDialogId, cancellationToken : cancellationToken);

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Stop:
                        {
                            // Use this intent to send an event to your device that can turn off the microphone in speech scenarios.
                            break;
                        }
                        }
                    }
                }
            }

            return(interrupted);
        }