/// <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"); }
/// <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))); }
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))); }
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); }
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); }
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); }
// 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); }
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); }
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); }