Update VA template
This commit is contained in:
Родитель
5509384a9b
Коммит
a1655dbe43
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
@ -16,8 +17,11 @@ using Microsoft.Bot.Solutions;
|
|||
using Microsoft.Bot.Solutions.Responses;
|
||||
using Microsoft.Bot.Solutions.Skills.Dialogs;
|
||||
using Microsoft.Bot.Solutions.Testing;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using $ext_safeprojectname$.Bots;
|
||||
using $ext_safeprojectname$.Dialogs;
|
||||
using $ext_safeprojectname$.Models;
|
||||
|
@ -53,7 +57,7 @@ namespace $safeprojectname$
|
|||
[TestInitialize]
|
||||
public virtual void Initialize()
|
||||
{
|
||||
Services = new ServiceCollection();
|
||||
Services = new ServiceCollection().AddLogging(config => config.AddConsole());
|
||||
Services.AddSingleton(new BotSettings());
|
||||
Services.AddSingleton(new BotServices()
|
||||
{
|
||||
|
@ -131,6 +135,14 @@ namespace $safeprojectname$
|
|||
Services.AddSingleton<TestAdapter, DefaultTestAdapter>();
|
||||
Services.AddTransient<IBot, DefaultActivityHandler<MockMainDialog>>();
|
||||
|
||||
// Add MicrosoftAPPId to configuration
|
||||
var configuration = new Mock<IConfiguration>();
|
||||
var configurationSection = new Mock<IConfigurationSection>();
|
||||
configurationSection.Setup(a => a.Value).Returns("testvalue");
|
||||
configuration.Setup(a => a.GetSection("MicrosoftAppId")).Returns(configurationSection.Object);
|
||||
// Register configuration
|
||||
Services.AddSingleton(configuration.Object);
|
||||
|
||||
TestUserProfileState = new UserProfileState();
|
||||
TestUserProfileState.Name = "Bot";
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
|
||||
<PackageReference Include="Moq" Version="4.14.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
|
||||
<PackageReference Include="RichardSzalay.MockHttp" Version="6.0.0" />
|
||||
|
|
|
@ -3,17 +3,26 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Dialogs.Choices;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core.Skills;
|
||||
using Microsoft.Bot.Builder.Teams;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Connector.Authentication;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Bot.Schema.Teams;
|
||||
using Microsoft.Bot.Solutions;
|
||||
using Microsoft.Bot.Solutions.Responses;
|
||||
using Microsoft.Bot.Solutions.Skills;
|
||||
using Microsoft.Bot.Solutions.Skills.Models;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using $safeprojectname$.Extensions;
|
||||
using $safeprojectname$.Models;
|
||||
|
||||
namespace $safeprojectname$.Bots
|
||||
|
@ -27,8 +36,13 @@ namespace $safeprojectname$.Bots
|
|||
private readonly IStatePropertyAccessor<DialogState> _dialogStateAccessor;
|
||||
private readonly IStatePropertyAccessor<UserProfileState> _userProfileState;
|
||||
private readonly LocaleTemplateManager _templateManager;
|
||||
private readonly SkillHttpClient _skillHttpClient;
|
||||
private readonly SkillsConfiguration _skillsConfig;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly string _virtualAssistantBotId;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public DefaultActivityHandler(IServiceProvider serviceProvider, T dialog)
|
||||
public DefaultActivityHandler(IServiceProvider serviceProvider, ILogger<DefaultActivityHandler<T>> logger, T dialog)
|
||||
{
|
||||
_dialog = dialog;
|
||||
_dialog.TelemetryClient = serviceProvider.GetService<IBotTelemetryClient>();
|
||||
|
@ -37,6 +51,11 @@ namespace $safeprojectname$.Bots
|
|||
_dialogStateAccessor = _conversationState.CreateProperty<DialogState>(nameof(DialogState));
|
||||
_userProfileState = _userState.CreateProperty<UserProfileState>(nameof(UserProfileState));
|
||||
_templateManager = serviceProvider.GetService<LocaleTemplateManager>();
|
||||
_skillHttpClient = serviceProvider.GetService<SkillHttpClient>();
|
||||
_skillsConfig = serviceProvider.GetService<SkillsConfiguration>();
|
||||
_configuration = serviceProvider.GetService<IConfiguration>();
|
||||
_virtualAssistantBotId = _configuration.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey)?.Value;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
|
||||
|
@ -104,9 +123,49 @@ namespace $safeprojectname$.Bots
|
|||
}
|
||||
}
|
||||
|
||||
// Invoked when a "task/fetch" event is received to invoke task module.
|
||||
protected override async Task<TaskModuleResponse> OnTeamsTaskModuleFetchAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
|
||||
{
|
||||
return await this.ProcessTaskModuleInvokeAsync(turnContext, cancellationToken);
|
||||
}
|
||||
|
||||
// Invoked when a 'task/submit' invoke activity is received for task module submit actions.
|
||||
protected override async Task<TaskModuleResponse> OnTeamsTaskModuleSubmitAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
|
||||
{
|
||||
return await this.ProcessTaskModuleInvokeAsync(turnContext, cancellationToken);
|
||||
}
|
||||
|
||||
protected override async Task OnEndOfConversationActivityAsync(ITurnContext<IEndOfConversationActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
await _dialog.RunAsync(turnContext, _dialogStateAccessor, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<TaskModuleResponse> ProcessTaskModuleInvokeAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get Skill From TaskInvoke
|
||||
var skillId = (turnContext.Activity as Activity).AsInvokeActivity().GetSkillId(_logger);
|
||||
var skill = _skillsConfig.Skills.Where(s => s.Value.AppId == skillId).FirstOrDefault().Value;
|
||||
|
||||
// Forward request to correct skill
|
||||
var invokeResponse = await _skillHttpClient.PostActivityAsync(_virtualAssistantBotId, skill, _skillsConfig.SkillHostEndpoint, turnContext.Activity as Activity, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Temporary workaround to get correct invokeresponse
|
||||
// issue: https://github.com/microsoft/botframework-sdk/issues/5929
|
||||
var response = new InvokeResponse()
|
||||
{
|
||||
Status = invokeResponse.Status,
|
||||
Body = ((Microsoft.Bot.Builder.InvokeResponse<object>)invokeResponse).Body
|
||||
};
|
||||
|
||||
return response.GetTaskModuleResponse();
|
||||
}
|
||||
catch
|
||||
{
|
||||
await turnContext.SendActivityAsync(_templateManager.GenerateActivityForLocale("ErrorMessage"));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,6 +33,7 @@ namespace $safeprojectname$.Dialogs
|
|||
|
||||
private readonly LocaleTemplateManager _templateManager;
|
||||
private readonly BotServices _services;
|
||||
private readonly BotSettings _settings;
|
||||
private readonly OnboardingDialog _onboardingDialog;
|
||||
private readonly SwitchSkillDialog _switchSkillDialog;
|
||||
private readonly SkillsConfiguration _skillsConfig;
|
||||
|
@ -44,6 +45,7 @@ namespace $safeprojectname$.Dialogs
|
|||
IServiceProvider serviceProvider)
|
||||
: base(nameof(MainDialog))
|
||||
{
|
||||
_settings = serviceProvider.GetService<BotSettings>();
|
||||
_services = serviceProvider.GetService<BotServices>();
|
||||
_templateManager = serviceProvider.GetService<LocaleTemplateManager>();
|
||||
_skillsConfig = serviceProvider.GetService<SkillsConfiguration>();
|
||||
|
@ -189,7 +191,8 @@ namespace $safeprojectname$.Dialogs
|
|||
activeLearningCardTitle: _templateManager.GenerateActivityForLocale("QnaMakerAdaptiveLearningCardTitle").Text,
|
||||
cardNoMatchText: _templateManager.GenerateActivityForLocale("QnaMakerNoMatchText").Text)
|
||||
{
|
||||
Id = knowledgebaseId
|
||||
Id = knowledgebaseId,
|
||||
LogPersonalInformation = _settings.LogPersonalData
|
||||
};
|
||||
}
|
||||
else
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using AdaptiveExpressions;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using $safeprojectname$.Models;
|
||||
|
||||
namespace $safeprojectname$.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension class for getting SkillId from Activity.
|
||||
/// </summary>
|
||||
public static class InvokeActivityExtensions
|
||||
{
|
||||
// Fetches skillId from CardAction data if present
|
||||
public static string GetSkillId(this IInvokeActivity activity, ILogger logger)
|
||||
{
|
||||
if (activity == null)
|
||||
{
|
||||
logger.Log(LogLevel.Error, "activity is null from TaskModule");
|
||||
throw new ArgumentNullException(nameof(activity));
|
||||
}
|
||||
|
||||
if (activity.Value == null)
|
||||
{
|
||||
logger.Log(LogLevel.Error, "activity.Value is null from TaskModule");
|
||||
throw new ArgumentException("activity.Value is null.", nameof(activity));
|
||||
}
|
||||
|
||||
// GetSkillId from Activity Value
|
||||
var data = JObject.Parse(activity.Value.ToString()).SelectToken("data.data")?.ToObject<SkillCardActionData>();
|
||||
return data.SkillId ?? throw new ArgumentException("SkillId in TaskModule is null", nameof(SkillCardActionData));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Schema.Teams;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace $safeprojectname$.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// InvokeResposneHandler class for returning TaskModuleResponse from InvokeResponse
|
||||
/// </summary>
|
||||
public static class InvokeResponseExtensions
|
||||
{
|
||||
// Converts "InvokeResponse" sent by SkillHttpClient to "TaskModuleResponse"
|
||||
public static TaskModuleResponse GetTaskModuleResponse(this InvokeResponse invokeResponse)
|
||||
{
|
||||
if (invokeResponse == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(invokeResponse));
|
||||
}
|
||||
|
||||
if (invokeResponse.Body != null)
|
||||
{
|
||||
return new TaskModuleResponse()
|
||||
{
|
||||
Task = GetTask(invokeResponse.Body),
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static TaskModuleResponseBase GetTask(object invokeResponseBody)
|
||||
{
|
||||
var responseBody = JObject.FromObject(invokeResponseBody);
|
||||
var task = responseBody.GetValue("task");
|
||||
string taskType = task.SelectToken("type")?.Value<string>();
|
||||
|
||||
return taskType switch
|
||||
{
|
||||
"continue" => new TaskModuleContinueResponse()
|
||||
{
|
||||
Type = taskType,
|
||||
Value = task.SelectToken("value").ToObject<TaskModuleTaskInfo>(),
|
||||
},
|
||||
"message" => new TaskModuleMessageResponse()
|
||||
{
|
||||
Type = taskType,
|
||||
Value = task.SelectToken("value").ToString(),
|
||||
},
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace $safeprojectname$.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Skill Card action data should contain skillName parameter
|
||||
/// This class is used to deserialize it and get skillName.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// SkillName.
|
||||
/// </value>
|
||||
public class SkillCardActionData
|
||||
{
|
||||
[JsonProperty("SkillId")]
|
||||
public string SkillId { get; set; }
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ namespace $safeprojectname$.Services
|
|||
luisOptions = new LuisRecognizerOptionsV3(dispatchApp)
|
||||
{
|
||||
TelemetryClient = telemetryClient,
|
||||
LogPersonalInformation = true,
|
||||
LogPersonalInformation = settings.LogPersonalData,
|
||||
};
|
||||
set.DispatchService = new LuisRecognizer(luisOptions);
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ namespace $safeprojectname$.Services
|
|||
luisOptions = new LuisRecognizerOptionsV3(luisApp)
|
||||
{
|
||||
TelemetryClient = telemetryClient,
|
||||
LogPersonalInformation = true,
|
||||
LogPersonalInformation = settings.LogPersonalData,
|
||||
};
|
||||
set.LuisServices.Add(model.Id, new LuisRecognizer(luisOptions));
|
||||
}
|
||||
|
|
|
@ -9,5 +9,6 @@ namespace $safeprojectname$.Services
|
|||
public class BotSettings : BotSettingsBase
|
||||
{
|
||||
public TokenExchangeConfig TokenExchangeConfig { get; set; }
|
||||
public bool LogPersonalData { get; set; }
|
||||
}
|
||||
}
|
|
@ -58,7 +58,10 @@ namespace $safeprojectname$
|
|||
services.AddSingleton(Configuration);
|
||||
|
||||
// Load settings
|
||||
var settings = new BotSettings();
|
||||
var settings = new BotSettings()
|
||||
{
|
||||
LogPersonalData = Configuration.GetSection("logPersonalInfo")?.Value.ToLower() == "true"
|
||||
};
|
||||
Configuration.Bind(settings);
|
||||
services.AddSingleton(settings);
|
||||
|
||||
|
@ -82,7 +85,8 @@ namespace $safeprojectname$
|
|||
services.AddSingleton<ITelemetryInitializer, OperationCorrelationTelemetryInitializer>();
|
||||
services.AddSingleton<ITelemetryInitializer, TelemetryBotIdInitializer>();
|
||||
services.AddSingleton<TelemetryInitializerMiddleware>();
|
||||
services.AddSingleton<TelemetryLoggerMiddleware>();
|
||||
|
||||
services.AddSingleton<TelemetryLoggerMiddleware>(s => new TelemetryLoggerMiddleware(s.GetService<IBotTelemetryClient>(), settings.LogPersonalData));
|
||||
|
||||
// Configure bot services
|
||||
services.AddSingleton<BotServices>();
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<PackageReference Include="Microsoft.Bot.Builder.AI.Luis" Version="4.13.2" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.AI.QnA" Version="4.13.2" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.ApplicationInsights" Version="4.13.2" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Azure" Version="4.13.2" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Azure.Blobs" Version="4.13.2" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Integration.ApplicationInsights.Core" Version="4.13.2" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.13.2" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.LanguageGeneration" Version="4.13.2" />
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
<Folder Name="Adapters" TargetFolderName="Adapters">
|
||||
<ProjectItem ReplaceParameters="true" TargetFileName="DefaultAdapter.cs">DefaultAdapter.cs</ProjectItem>
|
||||
</Folder>
|
||||
<Folder Name="Authentication" TargetFolderName="Authentication">
|
||||
<ProjectItem ReplaceParameters="true" TargetFileName="AllowedCallersClaimsValidator.cs">AllowedCallersClaimsValidator.cs</ProjectItem>
|
||||
</Folder>
|
||||
<Folder Name="Bots" TargetFolderName="Bots">
|
||||
<ProjectItem ReplaceParameters="true" TargetFileName="DefaultActivityHandler.cs">DefaultActivityHandler.cs</ProjectItem>
|
||||
</Folder>
|
||||
|
@ -101,7 +98,12 @@
|
|||
<ProjectItem ReplaceParameters="true" TargetFileName="MainDialog.cs">MainDialog.cs</ProjectItem>
|
||||
<ProjectItem ReplaceParameters="true" TargetFileName="OnboardingDialog.cs">OnboardingDialog.cs</ProjectItem>
|
||||
</Folder>
|
||||
<Folder Name="Extensions" TargetFolderName="Extensions">
|
||||
<ProjectItem ReplaceParameters="true" TargetFileName="InvokeActivityExtensions.cs">InvokeActivityExtensions.cs</ProjectItem>
|
||||
<ProjectItem ReplaceParameters="true" TargetFileName="InvokeResponseExtensions.cs">InvokeResponseExtensions.cs</ProjectItem>
|
||||
</Folder>
|
||||
<Folder Name="Models" TargetFolderName="Models">
|
||||
<ProjectItem ReplaceParameters="true" TargetFileName="SkillCardActionData.cs">SkillCardActionData.cs</ProjectItem>
|
||||
<ProjectItem ReplaceParameters="true" TargetFileName="StateProperties.cs">StateProperties.cs</ProjectItem>
|
||||
<ProjectItem ReplaceParameters="true" TargetFileName="UserProfileState.cs">UserProfileState.cs</ProjectItem>
|
||||
</Folder>
|
||||
|
|
|
@ -21,5 +21,6 @@
|
|||
},
|
||||
"contentModerator": {
|
||||
"key": ""
|
||||
}
|
||||
},
|
||||
"logPersonalInfo": true
|
||||
}
|
Загрузка…
Ссылка в новой задаче