public void StartConversation( Topic[] topics ) { // Verify topics we gave us aren't bunk // need to have a start topic // and the start topic needs to have options Topic start = null; foreach ( Topic topic in topics ) { if ( topic._topicName == TopicName.START ) { start = topic; break; } } if ( start == null ) { Debug.LogError("Topics don't contain a START topic!"); return; } _state = new ConversationState { _topics = topics, _currentTopicName = TopicName.START, _currentTopic = start }; OnConversationStart(); }
// Player Responded, set the next topic public void ChooseOption( ConversationOption option ) { TopicName next_topic_name = option._nextTopic; // Special Handling for END if ( next_topic_name == TopicName.END ) { option.OnOptionChosen(); // End Topic OnConversationEnd(); _state = null; return; } // don't do anything, just a warning, if the topic they chose doesn't exist as a valid option bool found = false; foreach ( ConversationOption curr_option in _state._currentTopic._options ) { if ( curr_option == option ) { found = true; break; } } if ( ! found ) { Debug.LogError("TOPIC IS NOT A VALID OPTION: " + next_topic_name); return; } // Make sure there is a mapping to this topic name in our topics collection Topic next_topic = null; foreach ( Topic topic in _state._topics ) { if ( topic._topicName == next_topic_name ) { next_topic = topic; break; } } if ( next_topic == null ) { Debug.LogError("FAILED TO FIND FIND TOPIC IN TOPIC NAME: " + next_topic_name ); return; } // Trigger Event option.OnOptionChosen(); // Update State _state._currentTopicName = next_topic_name; _state._currentTopic = next_topic; _topicChanged.Invoke(); }
public ConversationContext RunStep(ConversationState state, string message) { if (state.ConversationStep > Steps.Count) throw new ArgumentOutOfRangeException("stepNumber"); var result = Steps[state.ConversationStep - 1].Execute(state, message); return result; }
private void ChangeBot(string user, ChatterBotType type) { user = user.ToLower(); if (!conversations.ContainsKey(user)) conversations.Add(user, new ConversationState(this, type)); else conversations[user] = new ConversationState(this, type); }
public void Close() { CheckState(ConversationState.Opened); foreach(ISessionFactory sessionFactory in _map.Keys.ToArray()) { _map[sessionFactory].Close(); _map[sessionFactory].Dispose(); _map[sessionFactory] = null; } _state = ConversationState.Closed; }
public override void Load(System.Xml.XmlReader reader) { while (reader.Read()) { if (reader.MoveToContent() == System.Xml.XmlNodeType.Element) { if (reader.Name == "ConversationState") { string user = reader.GetAttribute("user"); var state = new ConversationState(this, (ChatterBotType)Enum.Parse(typeof(ChatterBotType), reader.GetAttribute("type"))); conversations.Add(user, state); } } } }
public async Task ConfirmPrompt_Locale_Override_ChoiceDefaults(string defaultLocale, string prompt, string utterance, string expectedResponse) { var convoState = new ConversationState(new MemoryStorage()); var dialogState = convoState.CreateProperty <DialogState>("dialogState"); var adapter = new TestAdapter() .Use(new AutoSaveStateMiddleware(convoState)); // Create new DialogSet. var dialogs = new DialogSet(dialogState); var culture = new PromptCultureModel() { InlineOr = " customOr ", InlineOrMore = " customOrMore ", Locale = "custom-custom", Separator = "customSeparator", NoInLanguage = "customNo", YesInLanguage = "customYes", }; var customDict = new Dictionary <string, (Choice, Choice, ChoiceFactoryOptions)>() { { culture.Locale, (new Choice(culture.YesInLanguage), new Choice(culture.NoInLanguage), new ChoiceFactoryOptions(culture.Separator, culture.InlineOr, culture.InlineOrMore, true)) }, }; // Prompt should default to English if locale is a non-supported value dialogs.Add(new ConfirmPrompt("ConfirmPrompt", customDict, null, defaultLocale)); await new TestFlow(adapter, async(turnContext, cancellationToken) => { turnContext.Activity.Locale = culture.Locale; var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken); var results = await dc.ContinueDialogAsync(cancellationToken); if (results.Status == DialogTurnStatus.Empty) { await dc.PromptAsync("ConfirmPrompt", new PromptOptions { Prompt = new Activity { Type = ActivityTypes.Message, Text = "Prompt." } }, cancellationToken); } else if (results.Status == DialogTurnStatus.Complete) { if ((bool)results.Result) { await turnContext.SendActivityAsync(MessageFactory.Text("1"), cancellationToken); } else { await turnContext.SendActivityAsync(MessageFactory.Text("0"), cancellationToken); } } }) .Send("hello") .AssertReply("Prompt. " + prompt) .Send(utterance) .AssertReply(expectedResponse) .StartTestAsync(); }
public SampleBot(IConfiguration configuration, ConversationState conversationState) { Configuration = configuration; this.conversationState = conversationState; dialog = new BasicDialog(conversationState); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers().AddNewtonsoftJson(); services.AddSingleton<IConfiguration>(this.Configuration); // Load settings var settings = new BotSettings(); Configuration.Bind(settings); // Create the credential provider to be used with the Bot Framework Adapter. services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>(); services.AddSingleton<BotAdapter>(sp => (BotFrameworkHttpAdapter)sp.GetService<IBotFrameworkHttpAdapter>()); // Register AuthConfiguration to enable custom claim validation for skills. services.AddSingleton(sp => new AuthenticationConfiguration { ClaimsValidator = new AllowedCallersClaimsValidator(settings.SkillConfiguration) }); // register components. ComponentRegistration.Add(new DialogsComponentRegistration()); ComponentRegistration.Add(new DeclarativeComponentRegistration()); ComponentRegistration.Add(new AdaptiveComponentRegistration()); ComponentRegistration.Add(new LanguageGenerationComponentRegistration()); ComponentRegistration.Add(new QnAMakerComponentRegistration()); ComponentRegistration.Add(new LuisComponentRegistration()); // This is for custom action component registration. //ComponentRegistration.Add(new CustomActionComponentRegistration()); // Register the skills client and skills request handler. services.AddSingleton<SkillConversationIdFactoryBase, SkillConversationIdFactory>(); services.AddHttpClient<BotFrameworkClient, SkillHttpClient>(); services.AddSingleton<ChannelServiceHandler, SkillHandler>(); // Register telemetry client, initializers and middleware services.AddApplicationInsightsTelemetry(settings?.ApplicationInsights?.InstrumentationKey ?? string.Empty); services.AddSingleton<ITelemetryInitializer, OperationCorrelationTelemetryInitializer>(); services.AddSingleton<ITelemetryInitializer, TelemetryBotIdInitializer>(); services.AddSingleton<IBotTelemetryClient, BotTelemetryClient>(); services.AddSingleton<TelemetryLoggerMiddleware>(sp => { var telemetryClient = sp.GetService<IBotTelemetryClient>(); return new TelemetryLoggerMiddleware(telemetryClient, logPersonalInformation: settings?.Telemetry?.LogPersonalInformation ?? false); }); services.AddSingleton<TelemetryInitializerMiddleware>(sp => { var httpContextAccessor = sp.GetService<IHttpContextAccessor>(); var telemetryLoggerMiddleware = sp.GetService<TelemetryLoggerMiddleware>(); return new TelemetryInitializerMiddleware(httpContextAccessor, telemetryLoggerMiddleware, settings?.Telemetry?.LogActivities ?? false); }); var storage = ConfigureStorage(settings); services.AddSingleton(storage); var userState = new UserState(storage); var conversationState = new ConversationState(storage); services.AddSingleton(userState); services.AddSingleton(conversationState); // Configure bot loading path var botDir = settings.Bot; var resourceExplorer = new ResourceExplorer().AddFolder(botDir); var rootDialog = GetRootDialog(botDir); var defaultLocale = Configuration.GetValue<string>("defaultLanguage") ?? "en-us"; services.AddSingleton(resourceExplorer); resourceExplorer.RegisterType<OnQnAMatch>("Microsoft.OnQnAMatch"); services.AddSingleton<IBotFrameworkHttpAdapter, BotFrameworkHttpAdapter>(s => GetBotAdapter(storage, settings, userState, conversationState, s)); var removeRecipientMention = settings?.Feature?.RemoveRecipientMention ?? false; services.AddSingleton<IBot>(s => new ComposerBot( s.GetService<ConversationState>(), s.GetService<UserState>(), s.GetService<ResourceExplorer>(), s.GetService<BotFrameworkClient>(), s.GetService<SkillConversationIdFactoryBase>(), s.GetService<IBotTelemetryClient>(), rootDialog, defaultLocale, removeRecipientMention)); }
public void ConfigureServices(IServiceCollection services) { // Load the connected services from .bot file. var botFilePath = Configuration.GetSection("botFilePath")?.Value; var botFileSecret = Configuration.GetSection("botFileSecret")?.Value; var botConfig = BotConfiguration.Load(botFilePath ?? @".\EmailSkill.bot", botFileSecret); services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded.")); // Initializes your bot service clients and adds a singleton that your Bot can access through dependency injection. var parameters = Configuration.GetSection("Parameters")?.Get <string[]>(); var configuration = Configuration.GetSection("Configuration")?.GetChildren()?.ToDictionary(x => x.Key, y => y.Value as object); var supportedProviders = Configuration.GetSection("SupportedProviders")?.Get <string[]>(); ISkillConfiguration connectedServices = new SkillConfiguration(botConfig, supportedProviders, parameters, configuration); services.AddSingleton(sp => connectedServices); var defaultLocale = Configuration.GetSection("defaultLocale").Get <string>(); // Initialize Bot State var cosmosDbService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.CosmosDB) ?? throw new Exception("Please configure your CosmosDb service in your .bot file."); var cosmosDb = cosmosDbService as CosmosDbService; var cosmosOptions = new CosmosDbStorageOptions() { CosmosDBEndpoint = new Uri(cosmosDb.Endpoint), AuthKey = cosmosDb.Key, CollectionId = cosmosDb.Collection, DatabaseId = cosmosDb.Database, }; var dataStore = new CosmosDbStorage(cosmosOptions); var userState = new UserState(dataStore); var conversationState = new ConversationState(dataStore); services.AddSingleton(dataStore); services.AddSingleton(userState); services.AddSingleton(conversationState); services.AddSingleton(new BotStateSet(userState, conversationState)); // Initialize Email client services.AddSingleton <IServiceManager, ServiceManager>(); // Add the bot with options services.AddBot <EmailSkill>(options => { // Load the connected services from .bot file. var environment = _isProduction ? "production" : "development"; var service = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.Endpoint && s.Name == environment); if (!(service is EndpointService endpointService)) { throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); } options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); // Telemetry Middleware (logs activity messages in Application Insights) var appInsightsService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.AppInsights) ?? throw new Exception("Please configure your AppInsights connection in your .bot file."); var instrumentationKey = (appInsightsService as AppInsightsService).InstrumentationKey; var appInsightsLogger = new TelemetryLoggerMiddleware(instrumentationKey, logUserName: true, logOriginalMessage: true); options.Middleware.Add(appInsightsLogger); // Catches any errors that occur during a conversation turn and logs them to AppInsights. options.OnTurnError = async(context, exception) => { await context.SendActivityAsync(context.Activity.CreateReply(EmailSharedResponses.EmailErrorMessage)); await context.SendActivityAsync(new Activity(type: ActivityTypes.Trace, text: $"Email Skill Error: {exception.Message} | {exception.StackTrace}")); connectedServices.TelemetryClient?.TrackException(exception); }; // Transcript Middleware (saves conversation history in a standard format) var storageService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.BlobStorage) ?? throw new Exception("Please configure your Azure Storage service in your .bot file."); var blobStorage = storageService as BlobStorageService; var transcriptStore = new AzureBlobTranscriptStore(blobStorage.ConnectionString, blobStorage.Container); var transcriptMiddleware = new TranscriptLoggerMiddleware(transcriptStore); options.Middleware.Add(transcriptMiddleware); // Typing Middleware (automatically shows typing when the bot is responding/working) var typingMiddleware = new ShowTypingMiddleware(); options.Middleware.Add(typingMiddleware); options.Middleware.Add(new SetLocaleMiddleware(defaultLocale ?? "en-us")); options.Middleware.Add(new AutoSaveStateMiddleware(userState, conversationState)); }); }
public DialogAndWelcomeBot(ConversationState conversationState, UserState userState, T dialog, ILogger <DialogBot <T> > logger) : base(conversationState, userState, dialog, logger) { }
public CitaIMQBotAccessors(ConversationState conversationState, UserState userState) { ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState)); UserState = userState ?? throw new ArgumentNullException(nameof(userState)); }
public SkillAdapterWithErrorHandler(IConfiguration configuration, ICredentialProvider credentialProvider, AuthenticationConfiguration authConfig, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState) : base(configuration, credentialProvider, authConfig, logger: logger) { _conversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); OnTurnError = HandleTurnError; // Add autosave middleware for SSO. Use(new SsoSaveStateMiddleware(_conversationState)); }
public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null) : base(configuration, logger) { OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); // Send a message to the user await turnContext.SendActivityAsync("The bot encounted an error or bug."); await turnContext.SendActivityAsync("To run this sample make sure you have the LUIS and QnA models deployed."); await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code."); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } catch (Exception e) { logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}"); } } // Send a trace activity, which will be displayed in the Bot Framework Emulator await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError"); }; }
public test(ConversationState conversationState, UserState userState) { _conversationState = conversationState; _userState = userState; }
public NHibernateConversation(IDictionary<ISessionFactory, ISession> map) { _map = map; _state = ConversationState.Opened; }
public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null, SkillHttpClient skillClient = null, SkillsConfiguration skillsConfig = null) : base(configuration, logger) { _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _conversationState = conversationState; _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _skillClient = skillClient; _skillsConfig = skillsConfig; OnTurnError = HandleTurnError; }
public async void RecognizeTest() { // arrage var expectedAnswer = "answer"; var expectedScore = 100; var expectedId = 10; List <Metadata> metadata = new List <Metadata>(); metadata.Add(new Metadata() { Name = "sample", Value = "value" }); List <string> questions = new List <string>(); questions.Add("hello"); List <QueryResult> listQueryResults = new List <QueryResult>(); listQueryResults.Add(new QueryResult() { Id = expectedId, Answer = expectedAnswer, Score = expectedScore, Metadata = metadata.ToArray(), Questions = questions.ToArray() }); QueryResults queryResults = new QueryResults(); queryResults.Answers = listQueryResults.ToArray(); var jsonRecognizerResult = JsonConvert.SerializeObject(queryResults); var handlerMock = new Mock <HttpMessageHandler>(MockBehavior.Strict); handlerMock .Protected() .Setup <Task <HttpResponseMessage> >( "SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>() ) .ReturnsAsync(new HttpResponseMessage() { StatusCode = HttpStatusCode.OK, Content = new StringContent(jsonRecognizerResult), }) .Verifiable(); var httpClient = new HttpClient(handlerMock.Object) { BaseAddress = new Uri("http://localhost/") }; var storage = new MemoryStorage(); var userState = new UserState(storage); var conversationState = new ConversationState(storage); var adapter = new TestAdapter().Use(new AutoSaveStateMiddleware(conversationState)); var dialogState = conversationState.CreateProperty <DialogState>("dialogState"); var dialogs = new DialogSet(dialogState); var steps = new WaterfallStep[] { async(step, cancellationToken) => { await step.Context.SendActivityAsync("response"); // act IQnAMakerService qnAMakerService = new QnAMakerService(httpClient, EnvironmentName, ContentRootPath); var result = await qnAMakerService.QnAMakerServices["name"].GetAnswersAsync(step.Context); var item = result.FirstOrDefault(); // assert Assert.Equal(expectedId, item.Id); Assert.Equal(expectedAnswer, item.Answer); Assert.Equal(expectedScore / 100, item.Score); return(Dialog.EndOfTurn); } }; dialogs.Add(new WaterfallDialog( "test", steps)); await new TestFlow(adapter, async(turnContext, cancellationToken) => { var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken); await dc.ContinueDialogAsync(cancellationToken); if (!turnContext.Responded) { await dc.BeginDialogAsync("test", null, cancellationToken); } }) .Send("ask") .AssertReply("response") .StartTestAsync(); }
public void ConfigureServices(IServiceCollection services) { // Load the connected services from .bot file. var botFilePath = Configuration.GetSection("botFilePath")?.Value; var botFileSecret = Configuration.GetSection("botFileSecret")?.Value; var botConfig = BotConfiguration.Load(botFilePath ?? @".\$safeprojectname$.bot", botFileSecret); services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded.")); // Initializes your bot service clients and adds a singleton that your Bot can access through dependency injection. var connectedServices = new BotServices(botConfig); services.AddSingleton(sp => connectedServices); // Initialize Bot State var cosmosDbService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.CosmosDB) ?? throw new Exception("Please configure your CosmosDb service in your .bot file."); var cosmosDb = cosmosDbService as CosmosDbService; var cosmosOptions = new CosmosDbStorageOptions() { CosmosDBEndpoint = new Uri(cosmosDb.Endpoint), AuthKey = cosmosDb.Key, CollectionId = cosmosDb.Collection, DatabaseId = cosmosDb.Database, }; var dataStore = new CosmosDbStorage(cosmosOptions); var userState = new UserState(dataStore); var conversationState = new ConversationState(dataStore); services.AddSingleton(dataStore); services.AddSingleton(userState); services.AddSingleton(conversationState); services.AddSingleton(new BotStateSet(userState, conversationState)); // Add the bot with options services.AddBot <$safeprojectname$>(options => { // Load the connected services from .bot file. var environment = _isProduction ? "production" : "development"; var service = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.Endpoint && s.Name == environment); if (!(service is EndpointService endpointService)) { throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); } options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); // Telemetry Middleware (logs activity messages in Application Insights) var appInsightsService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.AppInsights) ?? throw new Exception("Please configure your AppInsights connection in your .bot file."); var instrumentationKey = (appInsightsService as AppInsightsService).InstrumentationKey; var appInsightsLogger = new TelemetryLoggerMiddleware(instrumentationKey, logUserName: true, logOriginalMessage: true); options.Middleware.Add(appInsightsLogger); // Catches any errors that occur during a conversation turn and logs them to AppInsights. options.OnTurnError = async(context, exception) => { await context.SendActivityAsync("Sorry, it looks like something went wrong."); connectedServices.TelemetryClient.TrackException(exception); }; // Transcript Middleware (saves conversation history in a standard format) var storageService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.BlobStorage) ?? throw new Exception("Please configure your Azure Storage service in your .bot file."); var blobStorage = storageService as BlobStorageService; var transcriptStore = new AzureBlobTranscriptStore(blobStorage.ConnectionString, blobStorage.Container); var transcriptMiddleware = new TranscriptLoggerMiddleware(transcriptStore); options.Middleware.Add(transcriptMiddleware); // Typing Middleware (automatically shows typing when the bot is responding/working) var typingMiddleware = new ShowTypingMiddleware(); options.Middleware.Add(typingMiddleware); options.Middleware.Add(new AutoSaveStateMiddleware(userState, conversationState)); }); }
public JoinEventDialog( BotSettings settings, BotServices services, ConversationState conversationState, LocaleTemplateEngineManager localeTemplateEngineManager, IServiceManager serviceManager, IBotTelemetryClient telemetryClient, MicrosoftAppCredentials appCredentials) : base(nameof(JoinEventDialog), settings, services, conversationState, localeTemplateEngineManager, serviceManager, telemetryClient, appCredentials) { TelemetryClient = telemetryClient; var joinMeeting = new WaterfallStep[] { GetAuthToken, AfterGetAuthToken, CheckFocusedEvent, ConfirmNumber, AfterConfirmNumber }; var findEvent = new WaterfallStep[] { SearchEventsWithEntities, GetEvents, AddConflictFlag, ChooseEvent }; var getEvents = new WaterfallStep[] { GetEventsPrompt, AfterGetEventsPrompt, CheckValid, }; var chooseEvent = new WaterfallStep[] { ChooseEventPrompt, AfterChooseEvent }; AddDialog(new WaterfallDialog(Actions.ConnectToMeeting, joinMeeting) { TelemetryClient = telemetryClient }); AddDialog(new WaterfallDialog(Actions.GetEvents, getEvents) { TelemetryClient = telemetryClient }); AddDialog(new WaterfallDialog(Actions.FindEvent, findEvent) { TelemetryClient = telemetryClient }); AddDialog(new WaterfallDialog(Actions.ChooseEvent, chooseEvent) { TelemetryClient = telemetryClient }); // Set starting dialog for component InitialDialogId = Actions.ConnectToMeeting; }
public BeerBot(ConversationState conversationState, UserState userState) { _conversationState = conversationState; _userState = userState; }
/// <summary> /// This method gets called by the runtime. Use this method to add services to the container. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> specifies the contract for a collection of service descriptors.</param> /// <seealso cref="IStatePropertyAccessor{T}"/> /// <seealso cref="https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection"/> /// <seealso cref="https://docs.microsoft.com/en-us/azure/bot-service/bot-service-manage-channels?view=azure-bot-service-4.0"/> public void ConfigureServices(IServiceCollection services) { var secretKey = Configuration.GetSection("botFileSecret")?.Value; var botFilePath = Configuration.GetSection("botFilePath")?.Value; if (!File.Exists(botFilePath)) { throw new FileNotFoundException($"The .bot configuration file was not found. botFilePath: {botFilePath}"); } // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection. BotConfiguration botConfig = null; try { botConfig = BotConfiguration.Load(botFilePath, secretKey); } catch { var msg = @"Error reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment. - You can find the botFilePath and botFileSecret in the Azure App Service application settings. - If you are running this bot locally, consider adding a appsettings.json file with botFilePath and botFileSecret. - See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration. "; throw new InvalidOperationException(msg); } services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot configuration file could not be loaded. botFilePath: {botFilePath}")); // Retrieve current endpoint. var environment = _isProduction ? "production" : "development"; var service = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment); if (service == null && _isProduction) { // Attempt to load development environment service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == "development").FirstOrDefault(); } if (!(service is EndpointService endpointService)) { throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); } // Memory Storage is for local bot debugging only. When the bot // is restarted, everything stored in memory will be gone. IStorage dataStore = new MemoryStorage(); // For production bots use the Azure Blob or // Azure CosmosDB storage providers. For the Azure // based storage providers, add the Microsoft.Bot.Builder.Azure // Nuget package to your solution. That package is found at: // https://www.nuget.org/packages/Microsoft.Bot.Builder.Azure/ // Un-comment the following lines to use Azure Blob Storage // // Storage configuration name or ID from the .bot file. // const string StorageConfigurationId = "<STORAGE-NAME-OR-ID-FROM-BOT-FILE>"; // var blobConfig = botConfig.FindServiceByNameOrId(StorageConfigurationId); // if (!(blobConfig is BlobStorageService blobStorageConfig)) // { // throw new InvalidOperationException($"The .bot file does not contain an blob storage with name '{StorageConfigurationId}'."); // } // // Default container name. // const string DefaultBotContainer = "<DEFAULT-CONTAINER>"; // var storageContainer = string.IsNullOrWhiteSpace(blobStorageConfig.Container) ? DefaultBotContainer : blobStorageConfig.Container; // IStorage dataStore = new Microsoft.Bot.Builder.Azure.AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer); // Create and add conversation state. var conversationState = new ConversationState(dataStore); services.AddSingleton(conversationState); services.AddBot <$safeprojectname$Bot> (options => { options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); // Catches any errors that occur during a conversation turn and logs them to currently // configured ILogger. ILogger logger = _loggerFactory.CreateLogger <$safeprojectname$Bot>(); options.OnTurnError = async(context, exception) => { logger.LogError($"Exception caught : {exception}"); await context.SendActivityAsync("Sorry, it looks like something went wrong."); }; }); }
/// <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 InitialTurnState) { context.TurnState.Set(pair.Key, pair.Value); } // register DialogManager with TurnState. context.TurnState.Set(this); if (ConversationState == null) { ConversationState = context.TurnState.Get <ConversationState>() ?? throw new InvalidOperationException($"Unable to get an instance of {nameof(ConversationState)} from turnContext."); } else { context.TurnState.Set(ConversationState); } botStateSet.Add(ConversationState); if (UserState == null) { UserState = context.TurnState.Get <UserState>(); } else { context.TurnState.Set(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); // Call the common dialog "continue/begin" execution pattern shared with the classic RunAsync extension method var turnResult = await DialogExtensions.InternalRunAsync(context, _rootDialogId, dc, cancellationToken).ConfigureAwait(false); // save BotState changes await botStateSet.SaveAllChangesAsync(dc.Context, false, cancellationToken).ConfigureAwait(false); return(new DialogManagerResult { TurnResult = turnResult }); }
/// <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 InitialTurnState) { context.TurnState.Set(pair.Key, pair.Value); } // register DialogManager with TurnState. context.TurnState.Set(this); if (ConversationState == null) { ConversationState = context.TurnState.Get <ConversationState>() ?? throw new InvalidOperationException($"Unable to get an instance of {nameof(ConversationState)} from turnContext."); } else { context.TurnState.Set(ConversationState); } botStateSet.Add(ConversationState); if (UserState == null) { UserState = context.TurnState.Get <UserState>(); } else { context.TurnState.Set(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); // 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 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; }
public void ConfigureServices(IServiceCollection services) { // Load the connected services from .bot file. var botFilePath = Configuration.GetSection("botFilePath")?.Value; var botFileSecret = Configuration.GetSection("botFileSecret")?.Value; var botConfig = BotConfiguration.Load(botFilePath ?? @".\CustomAssistant.bot", botFileSecret); services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded.")); // Initializes your bot service clients and adds a singleton that your Bot can access through dependency injection. var skills = Configuration.GetSection("skills").Get <List <SkillDefinition> >(); var connectedServices = new BotServices(botConfig, skills); services.AddSingleton(sp => connectedServices); var defaultLocale = Configuration.GetSection("defaultLocale").Get <string>(); // Initialize Bot State var cosmosDbService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.CosmosDB) ?? throw new Exception("Please configure your CosmosDb service in your .bot file."); var cosmosDb = cosmosDbService as CosmosDbService; var cosmosOptions = new CosmosDbStorageOptions() { CosmosDBEndpoint = new Uri(cosmosDb.Endpoint), AuthKey = cosmosDb.Key, CollectionId = cosmosDb.Collection, DatabaseId = cosmosDb.Database, }; var dataStore = new CosmosDbStorage(cosmosOptions); var userState = new UserState(dataStore); var conversationState = new ConversationState(dataStore); services.AddSingleton(dataStore); services.AddSingleton(userState); services.AddSingleton(conversationState); services.AddSingleton(new BotStateSet(userState, conversationState)); var environment = _isProduction ? "production" : "development"; var service = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.Endpoint && s.Name == environment); if (!(service is EndpointService endpointService)) { throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); } services.AddSingleton(endpointService); // Add the bot with options services.AddBot <VirtualAssistant>(options => { // Load the connected services from .bot file. options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); // Telemetry Middleware (logs activity messages in Application Insights) var appInsightsService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.AppInsights) ?? throw new Exception("Please configure your AppInsights connection in your .bot file."); var instrumentationKey = (appInsightsService as AppInsightsService).InstrumentationKey; var appInsightsLogger = new TelemetryLoggerMiddleware(instrumentationKey, logUserName: true, logOriginalMessage: true); options.Middleware.Add(appInsightsLogger); // Catches any errors that occur during a conversation turn and logs them to AppInsights. options.OnTurnError = async(context, exception) => { CultureInfo.CurrentUICulture = new CultureInfo(context.Activity.Locale); var responseBuilder = new MainResponses(); await responseBuilder.ReplyWith(context, MainResponses.ResponseIds.Error); await context.SendActivityAsync(new Activity(type: ActivityTypes.Trace, text: $"Virtual Assistant Error: {exception.Message} | {exception.StackTrace}")); connectedServices.TelemetryClient.TrackException(exception); }; // Transcript Middleware (saves conversation history in a standard format) var storageService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.BlobStorage) ?? throw new Exception("Please configure your Azure Storage service in your .bot file."); var blobStorage = storageService as BlobStorageService; var transcriptStore = new AzureBlobTranscriptStore(blobStorage.ConnectionString, blobStorage.Container); var transcriptMiddleware = new TranscriptLoggerMiddleware(transcriptStore); options.Middleware.Add(transcriptMiddleware); // Typing Middleware (automatically shows typing when the bot is responding/working) options.Middleware.Add(new ShowTypingMiddleware()); options.Middleware.Add(new SetLocaleMiddleware(defaultLocale ?? "en-us")); options.Middleware.Add(new EventDebuggerMiddleware()); options.Middleware.Add(new AutoSaveStateMiddleware(userState, conversationState)); //// Translator is an optional component for scenarios when an Assistant needs to work beyond native language support // var translatorKey = Configuration.GetValue<string>("translatorKey"); // if (!string.IsNullOrEmpty(translatorKey)) // { // options.Middleware.Add(new TranslationMiddleware(new string[] { "en", "fr", "it", "de", "es" }, translatorKey, false)); // } // else // { // throw new InvalidOperationException("Microsoft Text Translation API key is missing. Please add your translation key to the 'translatorKey' setting."); // } }); }
public async Task EnsureCancelDialogCalled() { var convoState = new ConversationState(new MemoryStorage()); var adapter = new TestAdapter(TestAdapter.CreateConversation(TestContext.TestName)) .Use(new AutoSaveStateMiddleware(convoState)); var dialogState = convoState.CreateProperty <DialogState>("dialogState"); var dialogs = new DialogSet(dialogState); var telemetryClient = new Mock <IBotTelemetryClient>(); var saved_properties = new Dictionary <string, IDictionary <string, string> >(); var counter = 0; // Set up the client to save all logged property names and associated properties (in "saved_properties"). telemetryClient.Setup(c => c.TrackEvent(It.IsAny <string>(), It.IsAny <IDictionary <string, string> >(), It.IsAny <IDictionary <string, double> >())) .Callback <string, IDictionary <string, string>, IDictionary <string, double> >((name, properties, metrics) => saved_properties.Add($"{name}_{counter++}", properties)) .Verifiable(); var steps = new WaterfallStep[] { async(step, cancellationToken) => { await step.Context.SendActivityAsync("step1"); return(Dialog.EndOfTurn); }, async(step, cancellationToken) => { await step.Context.SendActivityAsync("step2"); return(Dialog.EndOfTurn); }, async(step, cancellationToken) => { await step.CancelAllDialogsAsync(); return(Dialog.EndOfTurn); }, }; var waterfallDialog = new MyWaterfallDialog("test", steps); dialogs.Add(waterfallDialog); dialogs.TelemetryClient = telemetryClient.Object; await new TestFlow(adapter, async(turnContext, cancellationToken) => { var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken); await dc.ContinueDialogAsync(cancellationToken); if (!turnContext.Responded) { await dc.BeginDialogAsync("test", null, cancellationToken); } }) .Send("hello") .AssertReply("step1") .Send("hello") .AssertReply("step2") .Send("hello") .AssertReply("step1") .StartTestAsync(); telemetryClient.Verify(m => m.TrackEvent(It.IsAny <string>(), It.IsAny <IDictionary <string, string> >(), It.IsAny <IDictionary <string, double> >()), Times.Exactly(7)); // Verify: // Event name is "WaterfallCancel" // Event occurs on the 4th event logged // Event contains DialogId // Event DialogId is set correctly. Assert.IsTrue(saved_properties["WaterfallStart_0"].ContainsKey("DialogId")); Assert.IsTrue(saved_properties["WaterfallStart_0"].ContainsKey("InstanceId")); Assert.IsTrue(saved_properties["WaterfallCancel_4"].ContainsKey("DialogId")); Assert.IsTrue(saved_properties["WaterfallCancel_4"]["DialogId"] == "test"); Assert.IsTrue(saved_properties["WaterfallCancel_4"].ContainsKey("StepName")); Assert.IsTrue(saved_properties["WaterfallCancel_4"].ContainsKey("InstanceId")); // Event contains "StepName" // Event naming on lambda's is "StepXofY" Assert.IsTrue(saved_properties["WaterfallCancel_4"]["StepName"] == "Step3of3"); Assert.IsTrue(waterfallDialog.CancelDialogCalled); Assert.IsFalse(waterfallDialog.EndDialogCalled); }
public TestInspectionMiddleware(InspectionState inspectionState, UserState userState, ConversationState conversationState, HttpClient httpClient) : base(inspectionState, userState, conversationState) { _httpClient = httpClient; }
public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, SentimentMiddleware sentimentMiddleware, ConversationState conversationState = null) : base(configuration, logger) { if (sentimentMiddleware == null) { throw new NullReferenceException(nameof(sentimentMiddleware)); } // Add translation middleware to the adapter's middleware pipeline Use(sentimentMiddleware); OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); // Send a message to the user await turnContext.SendActivityAsync("The bot encounted an error or bug."); await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code."); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } catch (Exception e) { logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}"); } } // Send a trace activity, which will be displayed in the Bot Framework Emulator await SendTraceActivityAsync(turnContext, exception); }; }
public async Task ScenarioWithInspectionMiddlwareOpenAttach() { // Arrange // any bot state should be returned as trace messages per turn var storage = new MemoryStorage(); var inspectionState = new InspectionState(storage); var userState = new UserState(storage); var conversationState = new ConversationState(storage); // set up the middleware with an http client that will just record the traffic - we are expecting the trace activities here var recordingHttpClient = new RecordingHttpMessageHandler(); var inspectionMiddleware = new TestInspectionMiddleware( inspectionState, userState, conversationState, new HttpClient(recordingHttpClient)); // Act // (1) send the /INSPECT open command from the emulator to the middleware var openActivity = MessageFactory.Text("/INSPECT open"); var inspectionAdapter = new TestAdapter(Channels.Test, true); await inspectionAdapter.ProcessActivityAsync(openActivity, async (turnContext, cancellationToken) => { await inspectionMiddleware.ProcessCommandAsync(turnContext); }); var inspectionOpenResultActivity = inspectionAdapter.ActiveQueue.Dequeue(); // (2) send the resulting /INSPECT attach command from the channel to the middleware var applicationAdapter = new TestAdapter(Channels.Test, true); applicationAdapter.Use(inspectionMiddleware); var attachCommand = inspectionOpenResultActivity.Value.ToString(); await applicationAdapter.ProcessActivityAsync(MessageFactory.Text(attachCommand), async (turnContext, cancellationToken) => { // nothing happens - just attach the inspector await Task.CompletedTask; }); var attachResponse = applicationAdapter.ActiveQueue.Dequeue(); // (3) send an application messaage from the channel, it should get the reply and then so should the emulator http endpioint await applicationAdapter.ProcessActivityAsync(MessageFactory.Text("hi"), async (turnContext, cancellationToken) => { await turnContext.SendActivityAsync(MessageFactory.Text($"echo: {turnContext.Activity.Text}")); (await userState.CreateProperty <Scratch>("x").GetAsync(turnContext, () => new Scratch())).Property = "hello"; (await conversationState.CreateProperty <Scratch>("y").GetAsync(turnContext, () => new Scratch())).Property = "world"; await userState.SaveChangesAsync(turnContext); await conversationState.SaveChangesAsync(turnContext); }); // Assert var outboundActivity = applicationAdapter.ActiveQueue.Dequeue(); Assert.Equal("echo: hi", outboundActivity.Text); Assert.Equal(3, recordingHttpClient.Requests.Count); var inboundTrace = JObject.Parse(recordingHttpClient.Requests[0]); Assert.Equal("trace", inboundTrace["type"].ToString()); Assert.Equal("ReceivedActivity", inboundTrace["name"].ToString()); Assert.Equal("message", inboundTrace["value"]["type"].ToString()); Assert.Equal("hi", inboundTrace["value"]["text"].ToString()); var outboundTrace = JObject.Parse(recordingHttpClient.Requests[1]); Assert.Equal("trace", outboundTrace["type"].ToString()); Assert.Equal("SentActivity", outboundTrace["name"].ToString()); Assert.Equal("message", outboundTrace["value"]["type"].ToString()); Assert.Equal("echo: hi", outboundTrace["value"]["text"].ToString()); var stateTrace = JObject.Parse(recordingHttpClient.Requests[2]); Assert.Equal("trace", stateTrace["type"].ToString()); Assert.Equal("BotState", stateTrace["name"].ToString()); Assert.Equal("hello", stateTrace["value"]["userState"]["x"]["Property"].ToString()); Assert.Equal("world", stateTrace["value"]["conversationState"]["y"]["Property"].ToString()); }
public BotFrameworkHttpAdapter GetBotAdapter(IStorage storage, BotSettings settings, UserState userState, ConversationState conversationState, IServiceProvider s) { var adapter = IsSkill(settings) ? new BotFrameworkHttpAdapter(new ConfigurationCredentialProvider(this.Configuration), s.GetService<AuthenticationConfiguration>()) : new BotFrameworkHttpAdapter(new ConfigurationCredentialProvider(this.Configuration)); adapter .UseStorage(storage) .UseBotState(userState, conversationState) .Use(new RegisterClassMiddleware<IConfiguration>(Configuration)) .Use(s.GetService<TelemetryInitializerMiddleware>()); // Configure Middlewares ConfigureTranscriptLoggerMiddleware(adapter, settings); ConfigureInspectionMiddleWare(adapter, settings, storage); ConfigureShowTypingMiddleWare(adapter, settings); ConfigureSetSpeakMiddleWare(adapter, settings); adapter.OnTurnError = async (turnContext, exception) => { await turnContext.SendActivityAsync(exception.Message).ConfigureAwait(false); await conversationState.ClearStateAsync(turnContext).ConfigureAwait(false); await conversationState.SaveChangesAsync(turnContext).ConfigureAwait(false); }; return adapter; }
public void ConfigureServices(IServiceCollection services) { var environment = _isProduction ? "production" : "development"; // Load the connected services from .bot file. var botFilePath = Configuration.GetSection("botFilePath")?.Value; //var botFileSecret = Configuration.GetSection("botFileSecret")?.Value; var botFileSecret = "dTonuuzS+krI6S69RITRAII7T/hAqtLYM1BLN7/eqAI="; var botConfig = BotConfiguration.Load(botFilePath, botFileSecret); services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded.")); // Get default locale from appsettings.json var defaultLocale = Configuration.GetSection("defaultLocale").Get <string>(); // Use Application Insights services.AddBotApplicationInsights(botConfig); // Initializes your bot service clients and adds a singleton that your Bot can access through dependency injection. var connectedServices = new BotServices(botConfig); services.AddSingleton(sp => connectedServices); // Initialize Bot State var cosmosDbService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.CosmosDB) ?? throw new Exception("Please configure your CosmosDb service in your .bot file."); var cosmosDb = cosmosDbService as CosmosDbService; var cosmosOptions = new CosmosDbStorageOptions() { CosmosDBEndpoint = new Uri(cosmosDb.Endpoint), AuthKey = cosmosDb.Key, CollectionId = cosmosDb.Collection, DatabaseId = cosmosDb.Database, }; var dataStore = new CosmosDbStorage(cosmosOptions); var userState = new UserState(dataStore); var conversationState = new ConversationState(dataStore); var jobState = new JobState(dataStore); services.AddSingleton(sp => jobState); services.AddSingleton(dataStore); services.AddSingleton(userState); services.AddSingleton(conversationState); services.AddSingleton(new BotStateSet(userState, conversationState)); // Add the bot with options services.AddBot <Bot>(options => { var service = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.Endpoint && s.Name == environment); if (!(service is EndpointService endpointService)) { throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); } options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); // Telemetry Middleware (logs activity messages in Application Insights) var sp = services.BuildServiceProvider(); var telemetryClient = sp.GetService <IBotTelemetryClient>(); var appInsightsLogger = new TelemetryLoggerMiddleware(telemetryClient, logPersonalInformation: true); options.Middleware.Add(appInsightsLogger); // Catches any errors that occur during a conversation turn and logs them to AppInsights. options.OnTurnError = async(context, exception) => { telemetryClient.TrackException(exception); await context.SendActivityAsync(MainStrings.ERROR); }; // Transcript Middleware (saves conversation history in a standard format) var storageService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.BlobStorage) ?? throw new Exception("Please configure your Azure Storage service in your .bot file."); var blobStorage = storageService as BlobStorageService; var transcriptStore = new AzureBlobTranscriptStore(blobStorage.ConnectionString, blobStorage.Container); var transcriptMiddleware = new TranscriptLoggerMiddleware(transcriptStore); options.Middleware.Add(transcriptMiddleware); // Typing Middleware (automatically shows typing when the bot is responding/working) options.Middleware.Add(new ShowTypingMiddleware()); // Locale Middleware (sets UI culture based on Activity.Locale) options.Middleware.Add(new SetLocaleMiddleware(defaultLocale ?? "en-us")); // Autosave State Middleware (saves bot state after each turn) options.Middleware.Add(new AutoSaveStateMiddleware(userState, conversationState)); }); services.AddSingleton(sp => { var service = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment); if (!(service is EndpointService endpointService)) { throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); } return((EndpointService)service); }); }
/// <summary> /// Initializes a new instance of the <see cref="RewardAndRecognitionAdapterWithErrorHandler"/> class. /// </summary> /// <param name="configuration">Application configurations.</param> /// <param name="logger">Instance to send logs to the Application Insights service.</param> /// <param name="rewardAndRecognitionActivityMiddleWare">Represents middle ware that can operate on incoming activities.</param> /// <param name="localizer">The current cultures' string localizer.</param> /// <param name="conversationState">conversationState.</param> public RewardAndRecognitionAdapterWithErrorHandler(IConfiguration configuration, ILogger <IBotFrameworkHttpAdapter> logger, RewardAndRecognitionActivityMiddleware rewardAndRecognitionActivityMiddleWare, IStringLocalizer <Strings> localizer, ConversationState conversationState = null) : base(configuration) { if (rewardAndRecognitionActivityMiddleWare == null) { throw new NullReferenceException(nameof(rewardAndRecognitionActivityMiddleWare)); } // Add activity middle ware to the adapter's middle ware pipeline this.Use(rewardAndRecognitionActivityMiddleWare); this.OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. logger.LogError(exception, $"Exception caught : {exception.Message}"); // Send a catch-all apology to the user. await turnContext.SendActivityAsync(localizer.GetString("ErrorMessage")); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { logger.LogError(ex, $"Exception caught on attempting to Delete ConversationState : {ex.Message}"); } } }; }
protected void GoToNode(int index) { currentNode = index; lastDialogueTick = Time.time; _state = ConversationState.DIALOGUE_PAUSE; }
public GetReminderController(IBotFrameworkHttpAdapter adapter, IConfiguration configuration, ConversationState conversationState, ILogger <MainDialog> logger, ConcurrentDictionary <string, ConversationReference> conversationReferences, ICredentialProvider credentialProvider, IBot bot) { this.bot = bot as DialogBot <MainDialog>; _adapter = adapter; _conversationReferences = conversationReferences; ConversationState = conversationState; _appId = configuration["MicrosoftAppId"]; _appPassword = configuration["MicrosoftAppPassword"]; _botId = configuration["BotId"]; _botName = configuration["BotName"]; _logger = logger; _configuration = configuration; _credentialProvider = credentialProvider; // If the channel is the Emulator, and authentication is not in use, // the AppId will be null. We generate a random AppId for this case only. // This is not required for production, since the AppId will have a value. if (string.IsNullOrEmpty(_appId)) { _appId = Guid.NewGuid().ToString(); //if no AppId, use a random Guid } }
void HandleKeyPress() { if (Input.GetKeyUp(KeyCode.E)) { if (!InteractingWith) { //interactie met iets NPC closest = null; float c = float.MaxValue; bool looping = true; while (looping) { foreach (NPC npc in (NPC[])GameObject.FindObjectsOfType<NPC>()) { bool nothit = true; float dist = Vector3.Distance(this.transform.position, npc.gameObject.transform.position); if (dist < c) { closest = npc; c = dist; nothit = true; } if (nothit) looping = false; } } if (c < 3.5f) //interact range!!! { if (closest.Interact()) { //zoom in camera InteractingWith = true; InteractingNPC = closest; } } } else { //volgende regel? if (ConvState == ConversationState.NPC) ConvState = ConversationState.Player; else ConvState = ConversationState.NPC; InteractingNPC.NextConversationLine(); } } SetItemMoving(false); if (Input.GetKey(KeyCode.W)) { SetItemMoving(true); TargetPosition += new Vector3(0, 0, 1.0f / MoveSpeed); SetItemFacing(ItemFacing.Up); if (Facing != FacingDirection.Front) { GetComponent<Renderer>().material.mainTexture = textures[0]; Facing = FacingDirection.Front; } } if (Input.GetKey(KeyCode.S)) { SetItemMoving(true); TargetPosition += new Vector3(0, 0, -1.0f / MoveSpeed); SetItemFacing(ItemFacing.Down); if (Facing != FacingDirection.Back) { //change sprite GetComponent<Renderer>().material.mainTexture = textures[1]; Facing = FacingDirection.Back; } } if (Input.GetKey(KeyCode.A)) { SetItemMoving(true); TargetPosition += new Vector3(-1.0f / MoveSpeed, 0, 0); SetItemFacing(ItemFacing.Left); if (Facing != FacingDirection.Left) { GetComponent<Renderer>().material.mainTexture = textures[2]; Facing = FacingDirection.Left; } } if (Input.GetKey(KeyCode.D)) { SetItemMoving(true); TargetPosition += new Vector3(1.0f / MoveSpeed, 0, 0); SetItemFacing(ItemFacing.Right); if (Facing != FacingDirection.Right) { GetComponent<Renderer>().material.mainTexture = textures[3]; Facing = FacingDirection.Right; } } }
public async Task ChoicePrompt() { var dialogs = new DialogSet(); dialogs.Add("test-prompt", new Dialogs.ChoicePrompt(Culture.English) { Style = ListStyle.Inline }); var promptOptions = new ChoicePromptOptions { Choices = new List <Choice> { new Choice { Value = "red" }, new Choice { Value = "green" }, new Choice { Value = "blue" }, }, RetryPromptString = "I didn't catch that. Select a color from the list." }; dialogs.Add("test", new WaterfallStep[] { async(dc, args, next) => { await dc.PromptAsync("test-prompt", "favorite color?", promptOptions); }, async(dc, args, next) => { var choiceResult = (ChoiceResult)args; await dc.Context.SendActivityAsync($"Bot received the choice '{choiceResult.Value.Value}'."); await dc.EndAsync(); } } ); var activities = TranscriptUtilities.GetFromTestContext(TestContext); var convState = new ConversationState(new MemoryStorage()); var testProperty = convState.CreateProperty <Dictionary <string, object> >("test", () => new Dictionary <string, object>()); TestAdapter adapter = new TestAdapter() .Use(convState); await new TestFlow(adapter, async(turnContext) => { if (turnContext.Activity.Type == ActivityTypes.Message) { var state = await testProperty.GetAsync(turnContext); var dc = dialogs.CreateContext(turnContext, state); await dc.ContinueAsync(); if (!turnContext.Responded) { await dc.BeginAsync("test"); } } }) .Test(activities) .StartTestAsync(); }
public void ResetCurrent() { CheckState(ConversationState.InContext); CurrentConversationHolder.Instance.UnBind(_map); foreach(ISession session in _map.Values) { session.Transaction.Commit(); } _state = ConversationState.Opened; }
// Update is called once per frame protected virtual void Update() { if (!_conversationIsRunning) return; switch(_state) { case ConversationState.DIALOGUE_PAUSE: Debug.Log ("DialoguePause"); // Pause between two conversation nodes if (!endTimerHasBeenSet) { endTimer = Time.time; endTimerHasBeenSet = true; } if (HasRenderedCompleteDialogueLine && (Time.time - endTimer) > CurrentNode.NextNodeDelay) { _state = ConversationState.RENDERING_DIALOGUE; textBubble.gameObject.SetActive(true); henryBubble.gameObject.SetActive(false); endTimerHasBeenSet = false; lastDialogueTick = Time.time; } break; case ConversationState.RENDERING_DIALOGUE: Debug.Log ("RenderingDialogue"); if (HasRenderedCompleteDialogueLine || Input.GetKeyDown(KeyCode.Return)) // ...The player wants to skip the JRPG thang? { _state = ConversationState.ANSWERING_APPERANCE_DELAY; lastDialogueTick = -1000; // minus a lot, because if lastTick = 0 the time difference may not be big enough to cause the entire string to be rendered. } break; case ConversationState.ANSWERING_APPERANCE_DELAY: Debug.Log ("AnsweringDelay"); // Wait before showing the responses and start listening for player input if (!endTimerHasBeenSet) { endTimer = Time.time; endTimerHasBeenSet = true; } if (HasRenderedCompleteDialogueLine && (Time.time - endTimer) > CurrentNode.AnswerAppearanceDelay) { _state = ConversationState.SELECTION_TIME; endTimerHasBeenSet = false; } break; case ConversationState.SELECTION_TIME: Debug.Log ("SelectionTime"); // Controls // This state will wait for player input if ( (Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.W)) && _highlightedResponse != 0) { _highlightedResponse--; } if ( (Input.GetKeyDown(KeyCode.DownArrow) || Input.GetKeyDown(KeyCode.S)) && _highlightedResponse != CurrentNode.Responses.Length-1) { _highlightedResponse++; } if (Input.GetKeyDown (KeyCode.Return) && !CurrentNode.IsEndNode) { // When player selects a response, transition to the AWKWARD state, where the response will eventually be chosen after awkward silence _state = ConversationState.AWKWARD; henryBubble.gameObject.SetActive(true); lastDialogueTick = Time.time; if (CurrentNode.IsEndNode) endTimer = Time.time; } // Check whether conversation should skip ahead if no answer is selected if (CurrentNode.SilentResponse > 0.0) { if (!nodeTimerHasBeenSet) { nodeTimer = Time.time; nodeTimerHasBeenSet = true; } if (Time.time - nodeTimer > CurrentNode.SilentResponse) { nodeTimerHasBeenSet = false; GoToNode(CurrentNode.SilentGoto); } } int endConvoNodeDisplayTime = 3; if (CurrentNode.IsEndNode && CurrentNode.SilentResponse <= 0.0 && (Time.time - endTimer) > endConvoNodeDisplayTime) StopConversation(); break; case ConversationState.AWKWARD: // The AWKWARD state will wait awkwardly after the player selects a response before actually selecting the response and moving to next node // When the waiting time is 0, the response will be selected instantly. That is why SELECTION_TIME doesn't select responses directly. Debug.Log("Awkward"); if ( Time.time - endTimer > CurrentNode.AnsweringDelay) { textBubble.gameObject.SetActive(false); endTimer = Time.time; _state = ConversationState.DIALOGUE_PAUSE; lastDialogueTick = Time.time; SelectResponse(_highlightedResponse); } break; } }
public AdapterWithErrorHandler(IConfiguration configuration, IHttpClientFactory httpClientFactory, ILogger<IBotFrameworkHttpAdapter> logger, ConversationState conversationState = default) : base(configuration, httpClientFactory, logger) { OnTurnError = async (turnContext, exception) => { // Log any leaked exception from the application. // NOTE: In production environment, you should consider logging this to // Azure Application Insights. Visit https://aka.ms/bottelemetry to see how // to add telemetry capture to your bot. logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); // Send a message to the user await turnContext.SendActivityAsync("The bot encountered an error or bug."); await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code."); // Send a trace activity, which will be displayed in the Bot Framework Emulator await SendTraceActivityAsync(turnContext, exception); }; }
// Update is called once per frame void Update () { HandleKeyPress(); Animate(); if (!InteractingWith) { if (transform.position != TargetPosition) { bool valid = true; Vector3 newpos = Vector3.Lerp(this.transform.position, TargetPosition, Time.deltaTime * 10); foreach (NPC npc in (NPC[])GameObject.FindObjectsOfType<NPC>()) { float dist = Vector3.Distance(newpos, npc.gameObject.transform.position); if (dist < 3.0f) { valid = false; break; } } if (valid) this.transform.position = newpos; } } else { string n = InteractingNPC.GetConversationLine(); if (n != "END") DisplayText(n); else { ConvState = ConversationState.NPC; InteractingWith = false; InteractingNPC.SetConversationLine(true); PlayerConvText.GetComponent<TextMesh>().text = ""; } } ((Weapon)activeItem).UpdatePosition(this.transform); }
public AdaptiveBotAdapter(ICredentialProvider credentialProvider, IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, IStorage storage, UserState userState, ConversationState conversationState, ResourceExplorer resourceExplorer) { this.Use(new RegisterClassMiddleware <IConfiguration>(configuration)); this.UseStorage(storage); this.UseState(userState, conversationState); this.UseResourceExplorer(resourceExplorer); this.UseLanguageGeneration(resourceExplorer); this.UseAdaptiveDialogs(); this.OnTurnError = async(turnContext, exception) => { if (conversationState != null) { // clear the conversationState to ensure that the next request for user will be routed to a new conversation await conversationState.DeleteAsync(turnContext); } }; }
public AlexaHeroBot(T dialog, ILogger <HeroBot <T> > logger, ConversationState conversationState) { _dialog = dialog; _logger = logger; _conversationState = conversationState; }
public IDisposable SetAsCurrent() { CheckState(ConversationState.Opened); foreach(ISession session in _map.Values) { session.BeginTransaction(); } CurrentConversationHolder.Instance.Bind(_map); _state = ConversationState.InContext; return new DisposeAction(ResetCurrent); }