Esempio n. 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DialogContext"/> class from the turn context.
        /// </summary>
        /// <param name="dialogs">The dialog set to create the dialog context for.</param>
        /// <param name="turnContext">The current turn context.</param>
        /// <param name="state">The state property from which to retrieve the dialog context.</param>
        public DialogContext(DialogSet dialogs, ITurnContext turnContext, DialogState state)
        {
            Dialogs  = dialogs ?? throw new ArgumentNullException(nameof(dialogs));
            Context  = turnContext ?? throw new ArgumentNullException(nameof(turnContext));
            Stack    = state.DialogStack;
            State    = new DialogStateManager(this);
            Services = new TurnContextStateCollection();

            ObjectPath.SetPathValue(turnContext.TurnState, TurnPath.Activity, Context.Activity);
        }
Esempio n. 2
0
 /// <inheritdoc/>
 protected override void PopulateParameters(DialogStateManager state, Dictionary <string, object> parameters)
 {
     parameters.Add("StartProperty", this.Start.GetValue(state));
     parameters.Add("EndProperty", this.End.GetValue(state));
     parameters.Add("TimezoneProperty", this.TimeZone.GetValue(state));
     parameters.Add("DateTimeTypeProperty", this.DateTimeType.GetValue(state));
     parameters.Add("FutureEventsOnlyProperty", this.FutureEventsOnly.GetValue(state));
     parameters.Add("MaxResultsProperty", this.MaxResults.GetValue(state));
     parameters.Add("UserEmailProperty", this.UserEmail.GetValue(state));
 }
Esempio n. 3
0
        /// <inheritdoc />
        protected override void PopulateParameters(DialogStateManager state, Dictionary <string, object> parameters)
        {
            if (this.UserId == null)
            {
                throw new InvalidOperationException($"GetPhoto requires UserId property populated.");
            }

            string userId = this.UserId.GetValue(state);

            parameters.Add("UserId", userId);
        }
        internal static async Task <DialogTurnResult> InternalRunAsync(ITurnContext turnContext, string dialogId, DialogContext dialogContext, DialogStateManagerConfiguration stateConfiguration, CancellationToken cancellationToken)
        {
            // map TurnState into root dialog context.services
            foreach (var service in turnContext.TurnState)
            {
                dialogContext.Services[service.Key] = service.Value;
            }

            var dialogStateManager = new DialogStateManager(dialogContext, stateConfiguration);
            await dialogStateManager.LoadAllScopesAsync(cancellationToken).ConfigureAwait(false);

            dialogContext.Context.TurnState.Add(dialogStateManager);

            DialogTurnResult dialogTurnResult = null;

            // Loop as long as we are getting valid OnError handled we should continue executing the actions for the turn.
            //
            // NOTE: We loop around this block because each pass through we either complete the turn and break out of the loop
            // or we have had an exception AND there was an OnError action which captured the error.  We need to continue the
            // turn based on the actions the OnError handler introduced.
            var endOfTurn = false;

            while (!endOfTurn)
            {
                try
                {
                    dialogTurnResult = await InnerRunAsync(turnContext, dialogId, dialogContext, cancellationToken).ConfigureAwait(false);

                    // turn successfully completed, break the loop
                    endOfTurn = true;
                }
                catch (Exception err)
                {
                    // fire error event, bubbling from the leaf.
                    var handled = await dialogContext.EmitEventAsync(DialogEvents.Error, err, bubble : true, fromLeaf : true, cancellationToken : cancellationToken).ConfigureAwait(false);

                    if (!handled)
                    {
                        // error was NOT handled, throw the exception and end the turn. (This will trigger the Adapter.OnError handler and end the entire dialog stack)
                        throw;
                    }
                }
            }

            // save all state scopes to their respective botState locations.
            await dialogStateManager.SaveAllChangesAsync(cancellationToken).ConfigureAwait(false);

            // return the redundant result because the DialogManager contract expects it
            return(dialogTurnResult);
        }
Esempio n. 5
0
        [Ignore] // NOTE: This needs to be revisited
        public void TestComplexPathExpressions()
        {
            var dialogs = new DialogSet();
            var dc      = new DialogContext(dialogs, new TurnContext(new TestAdapter(), new Schema.Activity()), (DialogState) new DialogState());
            DialogStateManager state = new DialogStateManager(dc);

            // complex type paths
            state.SetValue("user.name", "joe");
            state.SetValue("conversation.stuff[user.name]", "test");
            var value = state.GetValue <string>("conversation.stuff.joe");

            Assert.AreEqual("test", value, "complex set should set");
            value = state.GetValue <string>("conversation.stuff[user.name]");
            Assert.AreEqual("test", value, "complex get should get");
        }
Esempio n. 6
0
        public void TestHashResolver()
        {
            var dialogs = new DialogSet();
            var dc      = new DialogContext(dialogs, new TurnContext(new TestAdapter(), new Schema.Activity()), (DialogState) new DialogState());
            DialogStateManager state = new DialogStateManager(dc);

            // test HASH
            state.SetValue($"turn.recognized.intents.test", "intent1");
            state.SetValue($"#test2", "intent2");

            Assert.AreEqual("intent1", state.GetValue <string>("turn.recognized.intents.test"));
            Assert.AreEqual("intent1", state.GetValue <string>("#test"));
            Assert.AreEqual("intent2", state.GetValue <string>("turn.recognized.intents.test2"));
            Assert.AreEqual("intent2", state.GetValue <string>("#test2"));
        }
        /// <inheritdoc />
        protected override void PopulateParameters(DialogStateManager state, Dictionary <string, object> parameters)
        {
            int maxCount = DefaultMaxCount;

            if (this.MaxCount != null)
            {
                // The TryParse will reset the value to 0 if parse fail
                maxCount = this.MaxCount.GetValue(state);
            }

            string userId = this.UserId.GetValue(state);

            parameters.Add("UserId", userId);
            parameters.Add("MaxResults", maxCount);
        }
Esempio n. 8
0
        internal static string GetValueOrNull(this StringExpression expression, DialogStateManager state)
        {
            if (expression != null)
            {
                var(value, valueError) = expression.TryGetValue(state);
                if (valueError != null)
                {
                    throw new InvalidOperationException($"Expression evaluation resulted in an error. Expression: {expression.ExpressionText}. Error: {valueError}");
                }

                return(value as string);
            }

            return(null);
        }
Esempio n. 9
0
        public void TestPathResolverNullChecks()
        {
            var config = DialogStateManager.CreateStandardConfiguration();

            foreach (var resolver in config.PathResolvers)
            {
                try
                {
                    resolver.TransformPath(null);
                    Assert.Fail($"Should have thrown exception with null for matches() {resolver.GetType().Name}");
                }
                catch (ArgumentNullException)
                {
                }
            }
        }
Esempio n. 10
0
        public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            var dsm = new DialogStateManager(dc);

            foreach (var scope in dsm.Configuration.MemoryScopes.Where(ms => !(ms is DialogMemoryScope) && ms.IncludeInSnapshot == true).Select(ms => ms.Name))
            {
                var path = $"{scope}.test";
                Assert.IsNull(dc.State.GetValue <string>(path), $"{path} should be null");
                dc.State.SetValue(path, scope);
                Assert.IsNotNull(dc.State.GetValue <string>(path), $"{path} should not be null");
                Assert.AreEqual(scope, dc.State.GetValue <string>(path), $"{path} should be {scope}");
            }

            await dc.Context.SendActivityAsync("next");

            return(await dc.EndDialogAsync());
        }
Esempio n. 11
0
        public void TestGetValueT()
        {
            var dialogs = new DialogSet();
            var dc      = new DialogContext(dialogs, new TurnContext(new TestAdapter(), new Schema.Activity()), (DialogState) new DialogState());
            DialogStateManager state = new DialogStateManager(dc);

            // complex type paths
            state.SetValue("UseR.fOo", foo);
            Assert.AreEqual(state.GetValue <Foo>("user.foo").SubName.Name, "bob");

            // complex type paths
            state.SetValue("ConVerSation.FOo", foo);
            Assert.AreEqual(state.GetValue <Foo>("conversation.foo").SubName.Name, "bob");

            // complex type paths
            state.SetValue("TurN.fOo", foo);
            Assert.AreEqual(state.GetValue <Foo>("turn.foo").SubName.Name, "bob");
        }
Esempio n. 12
0
        public void TestComplexValuePaths()
        {
            var dialogs = new DialogSet();
            var dc      = new DialogContext(dialogs, new TurnContext(new TestAdapter(), new Schema.Activity()), (DialogState) new DialogState());
            DialogStateManager state = new DialogStateManager(dc);

            // complex type paths
            state.SetValue("UseR.fOo", foo);
            Assert.AreEqual("bob", state.GetValue <string>("user.foo.SuBname.name"));

            // complex type paths
            state.SetValue("ConVerSation.FOo", foo);
            Assert.AreEqual("bob", state.GetValue <string>("conversation.foo.SuBname.name"));

            // complex type paths
            state.SetValue("TurN.fOo", foo);
            Assert.AreEqual("bob", state.GetValue <string>("TuRN.foo.SuBname.name"));
        }
Esempio n. 13
0
        public void TestGetValue()
        {
            var dialogs = new DialogSet();
            var dc      = new DialogContext(dialogs, new TurnContext(new TestAdapter(), new Schema.Activity()), (DialogState) new DialogState());
            DialogStateManager state = new DialogStateManager(dc);

            // complex type paths
            state.SetValue("user.name.first", "joe");
            Assert.AreEqual("joe", state.GetValue <string>("user.name.first"));

            Assert.AreEqual(null, state.GetValue <string>("user.xxx"));
            Assert.AreEqual("default", state.GetValue <string>("user.xxx", () => "default"));

            foreach (var key in state.Keys)
            {
                Assert.AreEqual(state.GetValue <object>(key), state[key]);
            }
        }
Esempio n. 14
0
        public void IsDialogActive_Variations()
        {
            var config = new DialogStateManagerConfiguration()
            {
                MemoryScopes = new List <MemoryScope>()
                {
                    new MockMemoryScope("dialogContext", new { stack = new[] { "a", "d", "F" } })
                }
            };
            var dc = new DialogContext(new DialogSet(), new TurnContext(new TestAdapter(), new Schema.Activity()), new DialogState());
            DialogStateManager dsm = new DialogStateManager(dc, config);

            Assert.AreEqual(true, Expression.Parse("isDialogActive('a')").TryEvaluate(dsm).value);
            Assert.AreEqual(true, Expression.Parse("isDialogActive('b','c','d')").TryEvaluate(dsm).value);
            Assert.AreEqual(false, Expression.Parse("isDialogActive('b','c','e')").TryEvaluate(dsm).value);
            Assert.AreEqual(false, Expression.Parse("isDialogActive('c')").TryEvaluate(dsm).value);
            Assert.AreEqual(false, Expression.Parse("isDialogActive('f')").TryEvaluate(dsm).value);
            Assert.AreEqual(true, Expression.Parse("isDialogActive('F')").TryEvaluate(dsm).value);
        }
Esempio n. 15
0
 public async Task TestMemorySnapshot()
 {
     await CreateDialogContext(async (context, ct) =>
     {
         JObject snapshot = context.State.GetMemorySnapshot();
         var dsm          = new DialogStateManager(context);
         foreach (var memoryScope in dsm.Configuration.MemoryScopes)
         {
             if (memoryScope.IncludeInSnapshot)
             {
                 Assert.IsNotNull(snapshot.Property(memoryScope.Name));
             }
             else
             {
                 Assert.IsNull(snapshot.Property(memoryScope.Name));
             }
         }
     })
     .StartTestAsync();
 }
Esempio n. 16
0
        public void TestMemorySnapshot()
        {
            var dialogs = new DialogSet();
            var dc      = new DialogContext(dialogs, new TurnContext(new TestAdapter(), new Schema.Activity()), (DialogState) new DialogState());
            DialogStateManager state = new DialogStateManager(dc);

            JObject snapshot = state.GetMemorySnapshot();

            foreach (var memoryScope in DialogStateManager.MemoryScopes.Where(ms => ms.Name != "dialog" && ms.Name != "this"))
            {
                if (memoryScope.IsReadOnly)
                {
                    Assert.IsNull(snapshot.Property(memoryScope.Name));
                }
                else
                {
                    Assert.IsNotNull(snapshot.Property(memoryScope.Name));
                }
            }
        }
Esempio n. 17
0
        public void TestMemoryScopeNullChecks()
        {
            var dialogs = new DialogSet();
            var dc      = new DialogContext(dialogs, new TurnContext(new TestAdapter(), new Schema.Activity()), (DialogState) new DialogState());
            DialogStateManager state = new DialogStateManager(dc);

            foreach (var memoryScope in DialogStateManager.MemoryScopes)
            {
                try
                {
                    memoryScope.GetMemory(null);
                    Assert.Fail($"Should have thrown exception with null for {memoryScope.Name}");
                }
                catch (ArgumentNullException)
                {
                }

                if (!memoryScope.IsReadOnly)
                {
                    try
                    {
                        memoryScope.SetMemory(null, new object());
                        Assert.Fail($"Should have thrown exception with null dc for SetMemory {memoryScope.Name}");
                    }
                    catch (ArgumentNullException)
                    {
                    }

                    try
                    {
                        memoryScope.SetMemory(dc, null);
                        Assert.Fail($"Should have thrown exception with null memory for SetMemory {memoryScope.Name}");
                    }
                    catch (ArgumentNullException)
                    {
                    }
                }
            }
        }
Esempio n. 18
0
        public void TestEntityResolvers()
        {
            var dialogs = new DialogSet();
            var dc      = new DialogContext(dialogs, new TurnContext(new TestAdapter(), new Schema.Activity()), (DialogState) new DialogState());
            DialogStateManager state = new DialogStateManager(dc);

            // test @ and @@
            var testEntities  = new string[] { "entity1", "entity2" };
            var testEntities2 = new string[] { "entity3", "entity4" };

            state.SetValue($"turn.recognized.entities.test", testEntities);
            state.SetValue($"@@test2", testEntities2);

            Assert.AreEqual(testEntities.First(), state.GetValue <string>("turn.recognized.entities.test[0]"));
            Assert.AreEqual(testEntities.First(), state.GetValue <string>("@test"));
            Assert.IsTrue(testEntities.SequenceEqual(state.GetValue <string[]>("turn.recognized.entities.test")));
            Assert.IsTrue(testEntities.SequenceEqual(state.GetValue <string[]>("@@test")));

            Assert.AreEqual(testEntities2.First(), state.GetValue <string>("turn.recognized.entities.test2[0]"));
            Assert.AreEqual(testEntities2.First(), state.GetValue <string>("@test2"));
            Assert.IsTrue(testEntities2.SequenceEqual(state.GetValue <string[]>("turn.recognized.entities.test2")));
            Assert.IsTrue(testEntities2.SequenceEqual(state.GetValue <string[]>("@@test2")));
        }
        /// <summary>
        /// Runs dialog system in the context of an ITurnContext.
        /// </summary>
        /// <param name="context">turn context.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>result of the running the logic against the activity.</returns>
        public async Task <DialogManagerResult> OnTurnAsync(ITurnContext context, CancellationToken cancellationToken = default)
        {
            var botStateSet = new BotStateSet();

            // Preload TurnState with DM TurnState.
            foreach (var pair in TurnState)
            {
                context.TurnState.Set(pair.Key, pair.Value);
            }

            if (ConversationState == null)
            {
                ConversationState = context.TurnState.Get <ConversationState>() ?? throw new ArgumentNullException(nameof(ConversationState));
            }
            else
            {
                context.TurnState.Set(ConversationState);
            }

            botStateSet.Add(ConversationState);

            if (UserState == null)
            {
                UserState = context.TurnState.Get <UserState>();
            }

            if (UserState != null)
            {
                botStateSet.Add(UserState);
            }

            // create property accessors
            var lastAccessProperty = ConversationState.CreateProperty <DateTime>(LastAccess);
            var lastAccess         = await lastAccessProperty.GetAsync(context, () => DateTime.UtcNow, cancellationToken).ConfigureAwait(false);

            // Check for expired conversation
            if (ExpireAfter.HasValue && (DateTime.UtcNow - lastAccess) >= TimeSpan.FromMilliseconds((double)ExpireAfter))
            {
                // Clear conversation state
                await ConversationState.ClearStateAsync(context, cancellationToken).ConfigureAwait(false);
            }

            lastAccess = DateTime.UtcNow;
            await lastAccessProperty.SetAsync(context, lastAccess, cancellationToken).ConfigureAwait(false);

            // get dialog stack
            var dialogsProperty = ConversationState.CreateProperty <DialogState>(_dialogStateProperty);
            var dialogState     = await dialogsProperty.GetAsync(context, () => new DialogState(), cancellationToken).ConfigureAwait(false);

            // Create DialogContext
            var dc = new DialogContext(Dialogs, context, dialogState);

            // get the DialogStateManager configuration
            var dialogStateManager = new DialogStateManager(dc, StateConfiguration);
            await dialogStateManager.LoadAllScopesAsync(cancellationToken).ConfigureAwait(false);

            dc.Context.TurnState.Add(dialogStateManager);

            DialogTurnResult turnResult = null;

            // Loop as long as we are getting valid OnError handled we should continue executing the actions for the turn.
            //
            // NOTE: We loop around this block because each pass through we either complete the turn and break out of the loop
            // or we have had an exception AND there was an OnError action which captured the error.  We need to continue the
            // turn based on the actions the OnError handler introduced.
            var endOfTurn = false;

            while (!endOfTurn)
            {
                try
                {
                    if (context.TurnState.Get <IIdentity>(BotAdapter.BotIdentityKey) is ClaimsIdentity claimIdentity && SkillValidation.IsSkillClaim(claimIdentity.Claims))
                    {
                        // The bot is running as a skill.
                        turnResult = await HandleSkillOnTurnAsync(dc, cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        // The bot is running as root bot.
                        turnResult = await HandleBotOnTurnAsync(dc, cancellationToken).ConfigureAwait(false);
                    }

                    // turn successfully completed, break the loop
                    endOfTurn = true;
                }
        /// <summary>
        /// Runs dialog system in the context of an ITurnContext.
        /// </summary>
        /// <param name="context">turn context.</param>
        /// <param name="cancellationToken">cancelation token.</param>
        /// <returns>result of the running the logic against the activity.</returns>
        public async Task <DialogManagerResult> OnTurnAsync(ITurnContext context, CancellationToken cancellationToken = default(CancellationToken))
        {
            var botStateSet = new BotStateSet();

            // preload turnstate with DM turnstate
            foreach (var pair in this.TurnState)
            {
                context.TurnState.Set(pair.Key, pair.Value);
            }

            if (this.ConversationState == null)
            {
                this.ConversationState = context.TurnState.Get <ConversationState>() ?? throw new ArgumentNullException(nameof(this.ConversationState));
            }
            else
            {
                context.TurnState.Set(this.ConversationState);
            }

            botStateSet.Add(this.ConversationState);

            if (this.UserState == null)
            {
                this.UserState = context.TurnState.Get <UserState>();
            }

            if (this.UserState != null)
            {
                botStateSet.Add(this.UserState);
            }

            // create property accessors
            var lastAccessProperty = ConversationState.CreateProperty <DateTime>(LASTACCESS);
            var lastAccess         = await lastAccessProperty.GetAsync(context, () => DateTime.UtcNow, cancellationToken : cancellationToken).ConfigureAwait(false);

            // Check for expired conversation
            var now = DateTime.UtcNow;

            if (this.ExpireAfter.HasValue && (DateTime.UtcNow - lastAccess) >= TimeSpan.FromMilliseconds((double)this.ExpireAfter))
            {
                // Clear conversation state
                await ConversationState.ClearStateAsync(context, cancellationToken : cancellationToken).ConfigureAwait(false);
            }

            lastAccess = DateTime.UtcNow;
            await lastAccessProperty.SetAsync(context, lastAccess, cancellationToken : cancellationToken).ConfigureAwait(false);

            // get dialog stack
            var         dialogsProperty = ConversationState.CreateProperty <DialogState>(this.dialogStateProperty);
            DialogState dialogState     = await dialogsProperty.GetAsync(context, () => new DialogState(), cancellationToken : cancellationToken).ConfigureAwait(false);

            // Create DialogContext
            var dc = new DialogContext(this.Dialogs, context, dialogState);

            // get the dialogstatemanager configuration
            var dialogStateManager = new DialogStateManager(dc, this.StateConfiguration);
            await dialogStateManager.LoadAllScopesAsync(cancellationToken).ConfigureAwait(false);

            dc.Context.TurnState.Add(dialogStateManager);

            DialogTurnResult turnResult = null;

            // Loop as long as we are getting valid OnError handled we should continue executing the actions for the turn.
            //
            // NOTE: We loop around this block because each pass through we either complete the turn and break out of the loop
            // or we have had an exception AND there was an OnError action which captured the error.  We need to continue the
            // turn based on the actions the OnError handler introduced.
            while (true)
            {
                try
                {
                    if (dc.ActiveDialog == null)
                    {
                        // start root dialog
                        turnResult = await dc.BeginDialogAsync(this.rootDialogId, cancellationToken : cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        // Continue execution
                        // - This will apply any queued up interruptions and execute the current/next step(s).
                        turnResult = await dc.ContinueDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false);

                        if (turnResult.Status == DialogTurnStatus.Empty)
                        {
                            // restart root dialog
                            turnResult = await dc.BeginDialogAsync(this.rootDialogId, cancellationToken : cancellationToken).ConfigureAwait(false);
                        }
                    }

                    // turn successfully completed, break the loop
                    break;
                }
                catch (Exception err)
                {
                    // fire error event, bubbling from the leaf.
                    var handled = await dc.EmitEventAsync(DialogEvents.Error, err, bubble : true, fromLeaf : true, cancellationToken : cancellationToken).ConfigureAwait(false);

                    if (!handled)
                    {
                        // error was NOT handled, throw the exception and end the turn. (This will trigger the Adapter.OnError handler and end the entire dialog stack)
                        throw;
                    }
                }
            }

            // save all state scopes to their respective botState locations.
            await dialogStateManager.SaveAllChangesAsync(cancellationToken).ConfigureAwait(false);

            // save botstate changes
            await botStateSet.SaveAllChangesAsync(dc.Context, false, cancellationToken).ConfigureAwait(false);

            // send trace of memory
            var snapshot      = dc.GetState().GetMemorySnapshot();
            var traceActivity = (Activity)Activity.CreateTraceActivity("BotState", "https://www.botframework.com/schemas/botState", snapshot, "Bot State");
            await dc.Context.SendActivityAsync(traceActivity).ConfigureAwait(false);

            return(new DialogManagerResult()
            {
                TurnResult = turnResult
            });
        }
Esempio n. 21
0
        /// <summary>
        /// Inspects a dialogs memory.
        /// </summary>
        /// <param name="context">turn context.</param>
        /// <param name="inspector">Inspector for analyzing/modifying dialog context.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>result of the running the logic against the activity.</returns>
        public async Task InspectAsync(ITurnContext context, DialogContextInspector inspector, CancellationToken cancellationToken = default)
        {
            // This class just lets you load & save memory in parallel
            var botStateSet = new BotStateSet();

            // Some of the memory scopes expect to find things like storage in the turn state
            foreach (var pair in InitialTurnState)
            {
                context.TurnState.Set(pair.Key, pair.Value);
            }

            // register DialogManager with TurnState.
            context.TurnState.Set(this);

            // At a minimum you need ConversationState. UserState is optional
            if (ConversationState == null)
            {
                ConversationState = context.TurnState.Get <ConversationState>() ?? throw new NullReferenceException(nameof(ConversationState));
            }
            else
            {
                context.TurnState.Set(ConversationState);
            }

            // Add conversation state & user state to our parallel class
            botStateSet.Add(ConversationState);
            if (UserState == null)
            {
                UserState = context.TurnState.Get <UserState>();
            }
            else
            {
                context.TurnState.Set(UserState);
            }

            if (UserState != null)
            {
                botStateSet.Add(UserState);
            }

            // get dialog stack
            var dialogsProperty = ConversationState.CreateProperty <DialogState>(_dialogStateProperty);
            var dialogState     = await dialogsProperty.GetAsync(context, () => new DialogState(), cancellationToken).ConfigureAwait(false);

            // Create DialogContext
            var dc = new DialogContext(Dialogs, context, dialogState);

            // promote initial TurnState into dc.services for contextual services
            foreach (var service in dc.Services)
            {
                dc.Services[service.Key] = service.Value;
            }

            // map TurnState into root dialog context.services
            foreach (var service in context.TurnState)
            {
                dc.Services[service.Key] = service.Value;
            }

            // get the DialogStateManager configuration
            // - this configures all of the memory scopes and makes sure all of their memory has been loaded.
            var dialogStateManager = new DialogStateManager(dc, StateConfiguration);
            await dialogStateManager.LoadAllScopesAsync(cancellationToken).ConfigureAwait(false);

            dc.Context.TurnState.Add(dialogStateManager);

            // Find the DC for the active dialog
            var activeDc = GetActiveDialogContext(dc);

            inspector(activeDc);

            // save all state scopes to their respective botState locations.
            await dialogStateManager.SaveAllChangesAsync(cancellationToken).ConfigureAwait(false);

            await botStateSet.SaveAllChangesAsync(dc.Context, false, cancellationToken).ConfigureAwait(false);
        }
 /// <inheritdoc/>
 protected override void PopulateParameters(DialogStateManager state, Dictionary <string, object> parameters)
 {
     parameters.Add("EventId", this.EventId.GetValue(state));
 }
Esempio n. 23
0
 /// <summary>
 /// Constructs a new instance of SampleBot
 /// </summary>
 /// <param name="conversationState"></param>
 /// <param name="userState"></param>
 /// <param name="dialog"></param>
 /// <param name="cardService"></param>
 /// <param name="logger"></param>
 public SampleBot(DialogStateManager dialogStateManager, IntentDialog dialog, JsonAdaptiveCardService cardService, ILogger <SampleBot> logger)
     : base(dialogStateManager, dialog, logger)
 {
     this.cardService = cardService;
 }
Esempio n. 24
0
 /// <inheritdoc/>
 protected override void PopulateParameters(DialogStateManager state, Dictionary <string, object> parameters)
 {
     parameters.Add("CalendarSkillEvent", this.EventToUpdate.GetValue(state));
 }
        /// <summary>
        /// Runs dialog system in the context of an ITurnContext.
        /// </summary>
        /// <param name="context">turn context.</param>
        /// <param name="cancellationToken">cancelation token.</param>
        /// <returns>result of the running the logic against the activity.</returns>
        public async Task <DialogManagerResult> OnTurnAsync(ITurnContext context, CancellationToken cancellationToken = default(CancellationToken))
        {
            BotStateSet       botStateSet       = new BotStateSet();
            ConversationState conversationState = this.ConversationState ?? context.TurnState.Get <ConversationState>() ?? throw new ArgumentNullException($"{nameof(ConversationState)} is not found in the turn context. Have you called adapter.UseState() with a configured ConversationState object?");
            UserState         userState         = this.UserState ?? context.TurnState.Get <UserState>();

            if (conversationState != null)
            {
                botStateSet.Add(conversationState);
            }

            if (userState != null)
            {
                botStateSet.Add(userState);
            }

            // create property accessors
            var lastAccessProperty = conversationState.CreateProperty <DateTime>(LASTACCESS);
            var lastAccess         = await lastAccessProperty.GetAsync(context, () => DateTime.UtcNow, cancellationToken : cancellationToken).ConfigureAwait(false);

            // Check for expired conversation
            var now = DateTime.UtcNow;

            if (this.ExpireAfter.HasValue && (DateTime.UtcNow - lastAccess) >= TimeSpan.FromMilliseconds((double)this.ExpireAfter))
            {
                // Clear conversation state
                await conversationState.ClearStateAsync(context, cancellationToken : cancellationToken).ConfigureAwait(false);
            }

            lastAccess = DateTime.UtcNow;
            await lastAccessProperty.SetAsync(context, lastAccess, cancellationToken : cancellationToken).ConfigureAwait(false);

            // get dialog stack
            var         dialogsProperty = conversationState.CreateProperty <DialogState>(DIALOGS);
            DialogState dialogState     = await dialogsProperty.GetAsync(context, () => new DialogState(), cancellationToken : cancellationToken).ConfigureAwait(false);

            // Create DialogContext
            var dc = new DialogContext(this.dialogSet, context, dialogState);

            // set DSM configuration
            dc.SetStateConfiguration(this.StateConfiguration ?? DialogStateManager.CreateStandardConfiguration(conversationState, userState));

            // load scopes
            await dc.GetState().LoadAllScopesAsync(cancellationToken).ConfigureAwait(false);

            DialogTurnResult turnResult = null;

            if (dc.ActiveDialog == null)
            {
                // start root dialog
                turnResult = await dc.BeginDialogAsync(this.rootDialogId, cancellationToken : cancellationToken).ConfigureAwait(false);
            }
            else
            {
                // Continue execution
                // - This will apply any queued up interruptions and execute the current/next step(s).
                turnResult = await dc.ContinueDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false);

                if (turnResult.Status == DialogTurnStatus.Empty)
                {
                    // restart root dialog
                    turnResult = await dc.BeginDialogAsync(this.rootDialogId, cancellationToken : cancellationToken).ConfigureAwait(false);
                }
            }

            // save all state scopes to their respective stores.
            await dc.GetState().SaveAllChangesAsync(cancellationToken).ConfigureAwait(false);

            // save botstate changes
            await botStateSet.SaveAllChangesAsync(dc.Context, false, cancellationToken).ConfigureAwait(false);

            // send trace of memory
            var snapshot      = dc.GetState().GetMemorySnapshot();
            var traceActivity = (Activity)Activity.CreateTraceActivity("BotState", "https://www.botframework.com/schemas/botState", snapshot, "Bot State");
            await dc.Context.SendActivityAsync(traceActivity).ConfigureAwait(false);

            return(new DialogManagerResult()
            {
                TurnResult = turnResult
            });
        }
Esempio n. 26
0
 /// <inheritdoc />
 protected override void PopulateParameters(DialogStateManager state, Dictionary <string, object> parameters)
 {
     parameters.Add("Attendees", this.Attendees.GetValue(state));
     parameters.Add("Duration", this.Duration.GetValue(state));
     parameters.Add("Timezone", this.TimeZone.GetValue(state));
 }
 /// <summary>
 /// Populates the dictionary of parameter for the operation to run.
 /// </summary>
 /// <param name="state">Dialog state.</param>
 /// <param name="parameters">Dictionary of the parameters.</param>
 protected virtual void PopulateParameters(DialogStateManager state, Dictionary <string, object> parameters)
 {
     // Do nothing in default implementation.
 }