forked from microsoft/BotBuilder-Samples
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Skill Samples (dotnet) (microsoft#2032)
* First pass at DialogToDialog sample * Updated nuget packages to latest nightly. * Updated to 4.7 RC0. Updated readmes Reorganized MainDialog, SkillDialog and SkillDialogArgs. * Updated readmes * Adds SimpleBotToBot sample. Updated readmes for DialotToDialog. * Added a readme for the root folder. * Addressed some of Jonathan's comments. Addressed LUIS warning. * Changed the conversation ID to avoid using hashcodes (the unique value will be given by the parent conversation ID). * Changed how the skill conversation ID key gets generated. * Fixed stylecop issues. * Updated nuget references to RC1 * Updated code for partiy with JS * Moved SimpleBotToBot in main samples solution. Updated SimpleBotToBot to send an eoc on error with a status and text message. * Rename skill adapter. Updated OnError Upated nuget packages to released versions. * Readded skill sample that was lost in mege from master * Updated readmes Added sample claim validators for skill and parent. Added status checks for skill call invocations. * Updated links. * Fixed some strings and comments. * Update samples/csharp_dotnetcore/70.skills-simple-bot-to-bot/README.md Co-Authored-By: Jonathan Fingold <[email protected]> * Updated readme
- Loading branch information
1 parent
6ca6255
commit f1d9e1d
Showing
74 changed files
with
5,313 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
experimental/skills/DialogToDialog/DialogRootBot/AdapterWithErrorHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using Microsoft.Bot.Builder; | ||
using Microsoft.Bot.Builder.Integration.AspNet.Core; | ||
using Microsoft.Bot.Builder.TraceExtensions; | ||
using Microsoft.Bot.Connector.Authentication; | ||
using Microsoft.Bot.Schema; | ||
using Microsoft.BotBuilderSamples.DialogRootBot.Middleware; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Logging.Console; | ||
|
||
namespace Microsoft.BotBuilderSamples.DialogRootBot | ||
{ | ||
public class AdapterWithErrorHandler : BotFrameworkHttpAdapter | ||
{ | ||
public AdapterWithErrorHandler(IConfiguration configuration, ICredentialProvider credentialProvider, AuthenticationConfiguration authConfig, ILogger<AdapterWithErrorHandler> logger, ConversationState conversationState = null) | ||
: base(configuration, credentialProvider, authConfig, logger: 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 | ||
var errorMessageText = "The bot encountered an error or bug."; | ||
var errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.IgnoringInput); | ||
await turnContext.SendActivityAsync(errorMessage); | ||
|
||
errorMessageText = "To continue to run this bot, please fix the bot source code."; | ||
errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput); | ||
await turnContext.SendActivityAsync(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); | ||
} | ||
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.ToString(), "https://www.botframework.com/schemas/error", "TurnError"); | ||
}; | ||
|
||
Use(new LoggerMiddleware(logger)); | ||
} | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
...ental/skills/DialogToDialog/DialogRootBot/Authentication/AllowedCallersClaimsValidator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Security.Claims; | ||
using System.Threading.Tasks; | ||
using Microsoft.Bot.Connector.Authentication; | ||
|
||
namespace Microsoft.BotBuilderSamples.DialogRootBot.Authentication | ||
{ | ||
/// <summary> | ||
/// Sample claims validator that loads an allowed list from configuration if present | ||
/// and checks that responses are coming from configured skills. | ||
/// </summary> | ||
public class AllowedCallersClaimsValidator : ClaimsValidator | ||
{ | ||
private readonly List<string> _allowedSkills; | ||
|
||
public AllowedCallersClaimsValidator(SkillsConfiguration skillsConfig) | ||
{ | ||
if (skillsConfig == null) | ||
{ | ||
throw new ArgumentNullException(nameof(skillsConfig)); | ||
} | ||
|
||
// Load the appIds for the configured skills (we will only allow responses from skills we have configured). | ||
_allowedSkills = (from skill in skillsConfig.Skills.Values select skill.AppId).ToList(); | ||
} | ||
|
||
public override Task ValidateClaimsAsync(IList<Claim> claims) | ||
{ | ||
if (SkillValidation.IsSkillClaim(claims)) | ||
{ | ||
// Check that the appId claim in the skill request is in the list of skills configured for this bot. | ||
var appId = JwtTokenValidation.GetAppIdFromClaims(claims); | ||
if (!_allowedSkills.Contains(appId)) | ||
{ | ||
throw new UnauthorizedAccessException($"Received a request from an application with an appID of \"{appId}\". To enable requests from this skill, add the skill to your configuration file."); | ||
} | ||
} | ||
|
||
return Task.CompletedTask; | ||
} | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
experimental/skills/DialogToDialog/DialogRootBot/Bots/RootBot.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Bot.Builder; | ||
using Microsoft.Bot.Builder.Dialogs; | ||
using Microsoft.Bot.Schema; | ||
using Newtonsoft.Json; | ||
|
||
namespace Microsoft.BotBuilderSamples.DialogRootBot.Bots | ||
{ | ||
public class RootBot<T> : ActivityHandler | ||
where T : Dialog | ||
{ | ||
private readonly ConversationState _conversationState; | ||
private readonly Dialog _mainDialog; | ||
|
||
public RootBot(ConversationState conversationState, T mainDialog) | ||
{ | ||
_conversationState = conversationState; | ||
_mainDialog = mainDialog; | ||
} | ||
|
||
public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default) | ||
{ | ||
if (turnContext.Activity.Type != ActivityTypes.ConversationUpdate) | ||
{ | ||
// Run the Dialog with the Activity. | ||
await _mainDialog.RunAsync(turnContext, _conversationState.CreateProperty<DialogState>("DialogState"), cancellationToken); | ||
} | ||
else | ||
{ | ||
await base.OnTurnAsync(turnContext, cancellationToken); | ||
} | ||
|
||
// Save any state changes that might have occurred during the turn. | ||
await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken); | ||
} | ||
|
||
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken) | ||
{ | ||
foreach (var member in membersAdded) | ||
{ | ||
// Greet anyone that was not the target (recipient) of this message. | ||
// To learn more about Adaptive Cards, see https://aka.ms/msbot-adaptivecards for more details. | ||
if (member.Id != turnContext.Activity.Recipient.Id) | ||
{ | ||
var welcomeCard = CreateAdaptiveCardAttachment(); | ||
var activity = MessageFactory.Attachment(welcomeCard); | ||
await turnContext.SendActivityAsync(activity, cancellationToken); | ||
await _mainDialog.RunAsync(turnContext, _conversationState.CreateProperty<DialogState>("DialogState"), cancellationToken); | ||
} | ||
} | ||
} | ||
|
||
// Load attachment from embedded resource. | ||
private Attachment CreateAdaptiveCardAttachment() | ||
{ | ||
var cardResourcePath = "Microsoft.BotBuilderSamples.DialogRootBot.Cards.welcomeCard.json"; | ||
|
||
using (var stream = GetType().Assembly.GetManifestResourceStream(cardResourcePath)) | ||
{ | ||
using (var reader = new StreamReader(stream)) | ||
{ | ||
var adaptiveCard = reader.ReadToEnd(); | ||
return new Attachment | ||
{ | ||
ContentType = "application/vnd.microsoft.card.adaptive", | ||
Content = JsonConvert.DeserializeObject(adaptiveCard) | ||
}; | ||
} | ||
} | ||
} | ||
} | ||
} |
128 changes: 128 additions & 0 deletions
128
experimental/skills/DialogToDialog/DialogRootBot/Cards/welcomeCard.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
{ | ||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json", | ||
"type": "AdaptiveCard", | ||
"version": "1.0", | ||
"body": [ | ||
{ | ||
"type": "TextBlock", | ||
"spacing": "Medium", | ||
"size": "Medium", | ||
"weight": "Bolder", | ||
"text": "Welcome to the Dialog Skill Prototype!", | ||
"wrap": true, | ||
"maxLines": 0, | ||
"color": "Accent" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "Here are some things you can do:", | ||
"wrap": true, | ||
"maxLines": 0 | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "Send a text message to the bot (message, single-turn)", | ||
"wrap": true, | ||
"weight": "Bolder", | ||
"color": "Accent" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "**m:some message** sends the text after **m:** directly to the skill and the skill does intent and entity recognition against LUIS.", | ||
"wrap": true, | ||
"spacing": "None" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "Send a BookFlight event (event, multi-turn)", | ||
"wrap": true, | ||
"weight": "Bolder", | ||
"color": "Accent" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "**bookflight** sends an event to the skill with the name = 'BookFlight' to start a flight booking dialog.", | ||
"wrap": true, | ||
"spacing": "None" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "Send a GetWeather invoke activity (invoke, single-turn)", | ||
"wrap": true, | ||
"weight": "Bolder", | ||
"color": "Accent" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "**getweather** sends an invoke activity to the skill with the name = 'GetWeather'. The skill replies right away (Invoke activities are Request/Response).", | ||
"wrap": true, | ||
"spacing": "None" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "OAuthTest (event, multi-turn)", | ||
"wrap": true, | ||
"weight": "Bolder", | ||
"color": "Accent" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "**oauthtest** sends an event to the skill to start an OAuthCard dialog.", | ||
"wrap": true, | ||
"spacing": "None" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "Send a message to the bot with values (message, single-turn)", | ||
"wrap": true, | ||
"weight": "Bolder", | ||
"color": "Accent" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "**mv:some message** sends some complex object in the Value property of the activity in addition to the message after **mv:**.", | ||
"wrap": true, | ||
"spacing": "None" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "Canceling multi-turn conversations", | ||
"wrap": true, | ||
"weight": "Bolder", | ||
"color": "Accent" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "**abort** during a multi-turn dialog (i.e. BookFlight) sends an EndOfConversation activity to the skill to cancel the conversation.", | ||
"wrap": true, | ||
"spacing": "None" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "**cancel** during a multi-turn dialog (i.e. OAuthTest) is recognized by the skill, it cancels its current dialog and sends an EndOfConversation activity to the parent.", | ||
"wrap": true, | ||
"spacing": "None" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"size": "default", | ||
"text": "Use the suggested actions bellow to test different parent to skill interactions.", | ||
"wrap": true, | ||
"maxLines": 0 | ||
} | ||
] | ||
} |
35 changes: 35 additions & 0 deletions
35
experimental/skills/DialogToDialog/DialogRootBot/Controllers/BotController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.Bot.Builder; | ||
using Microsoft.Bot.Builder.Integration.AspNet.Core; | ||
|
||
namespace Microsoft.BotBuilderSamples.DialogRootBot.Controllers | ||
{ | ||
// This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot | ||
// implementation at runtime. Multiple different IBot implementations running at different endpoints can be | ||
// achieved by specifying a more specific type for the bot constructor argument. | ||
[Route("api/messages")] | ||
[ApiController] | ||
public class BotController : ControllerBase | ||
{ | ||
private readonly IBotFrameworkHttpAdapter _adapter; | ||
private readonly IBot _bot; | ||
|
||
public BotController(BotFrameworkHttpAdapter adapter, IBot bot) | ||
{ | ||
_adapter = adapter; | ||
_bot = bot; | ||
} | ||
|
||
[HttpPost] | ||
public async Task PostAsync() | ||
{ | ||
// Delegate the processing of the HTTP POST to the adapter. | ||
// The adapter will invoke the bot. | ||
await _adapter.ProcessAsync(Request, Response, _bot); | ||
} | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
experimental/skills/DialogToDialog/DialogRootBot/Controllers/SkillController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.Bot.Builder; | ||
using Microsoft.Bot.Builder.Integration.AspNet.Core; | ||
using Microsoft.Bot.Builder.Skills; | ||
|
||
namespace Microsoft.BotBuilderSamples.DialogRootBot.Controllers | ||
{ | ||
/// <summary> | ||
/// A controller that handles skill replies to the bot. | ||
/// This example uses the <see cref="SkillHandler"/> that is registered as a <see cref="ChannelServiceHandler"/> in startup.cs. | ||
/// </summary> | ||
[ApiController] | ||
[Route("api/skills")] | ||
public class SkillController : ChannelServiceController | ||
{ | ||
public SkillController(ChannelServiceHandler handler) | ||
: base(handler) | ||
{ | ||
} | ||
} | ||
} |
Oops, something went wrong.