Merge branch 'main' into v-bruhal/functestfixes8-13

This commit is contained in:
LocalizationBuildProcess 2020-09-03 16:16:41 -07:00
Родитель 640594afc7 1a49139d32
Коммит aea05ac535
352 изменённых файлов: 5591 добавлений и 11478 удалений

Просмотреть файл

@ -45,7 +45,7 @@ For more information jump to a section below.
| Microsoft.Bot.Schema | [![BotBuilder Badge](https://buildstats.info/nuget/Microsoft.Bot.Schema?dWidth=70)](https://www.nuget.org/packages/Microsoft.Bot.Schema/) | [![BotBuilder Badge](https://buildstats.info/myget/botbuilder/botbuilder-v4-dotnet-daily/Microsoft.Bot.Schema?includePreReleases=true&dWidth=50)](https://botbuilder.myget.org/feed/botbuilder-v4-dotnet-daily/package/nuget/Microsoft.Bot.Schema) |
| Microsoft.Bot.Streaming | [![BotBuilder Badge](https://buildstats.info/nuget/Microsoft.Bot.Streaming?dWidth=70)](https://www.nuget.org/packages/Microsoft.Bot.Streaming/) | [![BotBuilder Badge](https://buildstats.info/myget/botbuilder/botbuilder-v4-dotnet-daily/Microsoft.Bot.Streaming?includePreReleases=true&dWidth=50)](https://botbuilder.myget.org/feed/botbuilder-v4-dotnet-daily/package/nuget/Microsoft.Bot.Streaming) |
You can refer to the [dependency graph](https://botbuildersdkblobstorage.blob.core.windows.net/sdk-dotnet-dependency-reports/4.9.2/InterdependencyGraph.html) for our libraries.
To view our libraries' interdependencies, see [this dependency graph](https://botbuildersdkblobstorage.blob.core.windows.net/sdk-dotnet-dependency-reports/latest/InterdependencyGraph.html).
To use the daily builds, which are published to MyGet, please follow the instructions [here](UsingMyGet.md).

Просмотреть файл

@ -65,7 +65,7 @@ steps:
inputs:
targetType: filePath
filePath: '$(Build.SourcesDirectory)\build\PublishToCoveralls.ps1'
arguments: '-pathToCoverageFiles "$(Build.SourcesDirectory)\CodeCoverage" -serviceName "master CI-PR"'
arguments: '-pathToCoverageFiles "$(Build.SourcesDirectory)\CodeCoverage" -serviceName "CI-PR build"'
continueOnError: true
condition: and(succeeded(), eq(variables['PublishCoverage'], 'true'))

Просмотреть файл

@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Newtonsoft.Json;
namespace AdaptiveExpressions.BuiltinFunctions
{
/// <summary>
/// Return the json string of a value.
/// String function takes an object as the argument.
/// </summary>
internal class JsonStringify : ExpressionEvaluator
{
/// <summary>
/// Initializes a new instance of the <see cref="JsonStringify"/> class.
/// </summary>
public JsonStringify()
: base(ExpressionType.JsonStringify, Evaluator(), ReturnType.String, FunctionUtils.ValidateUnary)
{
}
private static EvaluateExpressionDelegate Evaluator()
{
return FunctionUtils.Apply(
(args) =>
{
var result = JsonConvert.SerializeObject(args[0]);
return result;
});
}
}
}

Просмотреть файл

@ -24,14 +24,16 @@ namespace AdaptiveExpressions.BuiltinFunctions
{
object result = null;
string error = null;
if (args[0] is JObject && args[1] is JObject)
var arg0 = FunctionUtils.ConvertToJToken(args[0]);
var arg1 = FunctionUtils.ConvertToJToken(args[1]);
if (arg0 is JObject && arg1 is JObject)
{
(args[0] as JObject).Merge(args[1] as JObject, new JsonMergeSettings
(arg0 as JObject).Merge(arg1 as JObject, new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Replace
});
result = args[0];
result = arg0;
}
else
{

Просмотреть файл

@ -114,6 +114,7 @@ namespace AdaptiveExpressions
new BuiltinFunctions.Join(),
new BuiltinFunctions.JPath(),
new BuiltinFunctions.Json(),
new BuiltinFunctions.JsonStringify(),
new BuiltinFunctions.Last(),
new BuiltinFunctions.LastIndexOf(),
new BuiltinFunctions.Length(),
@ -215,4 +216,4 @@ namespace AdaptiveExpressions
return new ReadOnlyDictionary<string, ExpressionEvaluator>(lookup);
}
}
}
}

Просмотреть файл

@ -136,6 +136,7 @@ namespace AdaptiveExpressions
#pragma warning disable CA1720 // Identifier contains type name (by design and can't change this because of backward compat)
public const string String = "string";
#pragma warning restore CA1720 // Identifier contains type name
public const string JsonStringify = "jsonStringify";
public const string Bool = "bool";
public const string Binary = "binary";
public const string Base64 = "base64";
@ -215,4 +216,4 @@ namespace AdaptiveExpressions
public const string Ignore = "ignore";
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
}
}
}

Просмотреть файл

@ -87,6 +87,6 @@ TEMPLATE : '$' '{' (STRING | OBJECT_DEFINITION | ~[\r\n{}'"`])+ '}';
ESCAPE_CHARACTER : '\\' ~[\r\n]?;
TEXT_CONTENT : ~[\r\n];
TEXT_CONTENT : . ;

Просмотреть файл

@ -139,7 +139,8 @@ namespace Microsoft.Bot.Builder.AI.Luis
{
ExternalEntityRecognizer = ExternalEntityRecognizer,
PredictionOptions = options,
TelemetryClient = TelemetryClient
TelemetryClient = TelemetryClient,
IncludeAPIResults = options.IncludeAPIResults,
};
}

Просмотреть файл

@ -1,7 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net.Http;
using System.Runtime.CompilerServices;
using Microsoft.Bot.Builder.Dialogs.Adaptive.Actions;
@ -33,6 +35,22 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Testing.HttpRequestMocks
RegisterSourcePath(path, line);
}
/// <summary>
/// Type for how <see cref="Body"/> matches against request's body.
/// </summary>
public enum BodyMatchType
{
/// <summary>
/// Exact match.
/// </summary>
Exact,
/// <summary>
/// Match as a part.
/// </summary>
Partial
}
/// <summary>
/// Gets or sets the HttpMethod to match. If null, match to any method.
/// </summary>
@ -54,6 +72,26 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Testing.HttpRequestMocks
public string Url { get; set; }
#pragma warning restore CA1056 // Uri properties should not be strings
/// <summary>
/// Gets or sets the match type for body.
/// </summary>
/// <value>
/// One of Exact, Partial.
/// </value>
[DefaultValue(BodyMatchType.Partial)]
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty("matchType")]
public BodyMatchType MatchType { get; set; } = BodyMatchType.Partial;
/// <summary>
/// Gets or sets the body to match against request's body.
/// </summary>
/// <value>
/// Content.
/// </value>
[JsonProperty("body")]
public string Body { get; set; }
/// <summary>
/// Gets the sequence of responses to reply. The last one will be repeated.
/// </summary>
@ -81,6 +119,27 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Testing.HttpRequestMocks
mocked = handler.When(new HttpMethod(Method.Value.ToString()), Url);
}
if (!string.IsNullOrEmpty(Body))
{
if (Method == HttpRequest.HttpMethod.DELETE || Method == HttpRequest.HttpMethod.GET)
{
throw new ArgumentException("GET and DELETE don't support matching body!");
}
if (MatchType == BodyMatchType.Exact)
{
mocked = mocked.WithContent(Body);
}
else if (MatchType == BodyMatchType.Partial)
{
mocked = mocked.WithPartialContent(Body);
}
else
{
throw new InvalidEnumArgumentException($"{nameof(MatchType)} does not support {MatchType} yet!");
}
}
mocked.Respond(re => response.GetMessage());
}
}

Просмотреть файл

@ -1,7 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
@ -19,6 +21,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Testing.Mocks
private readonly HttpClient _httpClient;
private Func<HttpRequestMessage, HttpResponseMessage> _fallback;
/// <summary>
/// Initializes a new instance of the <see cref="MockHttpRequestMiddleware"/> class.
/// </summary>
@ -31,6 +35,26 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Testing.Mocks
mock.Setup(handler);
}
handler.Fallback.Respond((request) =>
{
if (_fallback != null)
{
var result = _fallback(request);
if (result != null)
{
return result;
}
}
// Keep original behaviour
return new HttpResponseMessage(HttpStatusCode.NotFound)
{
ReasonPhrase = $"No matching mock handler for \"{request.Method} {request.RequestUri}\"",
Content = new StringContent(string.Empty),
RequestMessage = request,
};
});
_httpMessageHandler = handler;
var client = handler.ToHttpClient();
_httpClient = client;
@ -41,7 +65,17 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Testing.Mocks
{
turnContext.TurnState.Add(_httpMessageHandler);
turnContext.TurnState.Add(_httpClient);
turnContext.TurnState.Add(this);
await next(cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Set fallback.
/// </summary>
/// <param name="fallback">New fallback or null.</param>
public void SetFallback(Func<HttpRequestMessage, HttpResponseMessage> fallback)
{
_fallback = fallback;
}
}
}

Просмотреть файл

@ -5,12 +5,12 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers;
using Microsoft.Bot.Builder.Dialogs.Adaptive.Testing.Mocks;
using Microsoft.Bot.Schema;
using Newtonsoft.Json;
using RichardSzalay.MockHttp;
namespace Microsoft.Bot.Builder.AI.Luis.Testing
@ -48,21 +48,36 @@ namespace Microsoft.Bot.Builder.AI.Luis.Testing
/// <inheritdoc/>
public override async Task<RecognizerResult> RecognizeAsync(DialogContext dialogContext, Activity activity, CancellationToken cancellationToken = default, Dictionary<string, string> telemetryProperties = null, Dictionary<string, double> telemetryMetrics = null)
{
HttpClientHandler newHandler = null, oldHandler = _recognizer.HttpClient;
// Used for ResponsePath
var recognizer = _recognizer.RecognizerOptions(dialogContext);
recognizer.IncludeAPIResults = true;
using (var client = GetMockedClient(activity.Text, recognizer))
{
var wrapper = new LuisRecognizer(recognizer, client);
var result = await wrapper.RecognizeAsync(dialogContext.Context, cancellationToken).ConfigureAwait(false);
if (client == null)
{
// Save response
var outPath = ResponsePath(activity.Text, recognizer);
File.WriteAllText(outPath, JsonConvert.SerializeObject(result.Properties["luisResult"]));
}
return result;
var middleware = dialogContext.Context.TurnState.Get<MockHttpRequestMiddleware>();
if (middleware == null)
{
#pragma warning disable CA2000 // Dispose objects before losing scope
var mockHandler = new MockHttpMessageHandler();
#pragma warning restore CA2000 // Dispose objects before losing scope
mockHandler.Fallback.Respond((request) => FallbackAsync(request, activity.Text, recognizer, cancellationToken).GetAwaiter().GetResult());
newHandler = new MockedHttpClientHandler(mockHandler);
}
else
{
middleware.SetFallback((request) => FallbackAsync(request, activity.Text, recognizer, cancellationToken).GetAwaiter().GetResult());
newHandler = new MockedHttpClientHandler(dialogContext.Context.TurnState.Get<HttpMessageHandler>());
}
_recognizer.HttpClient = newHandler;
var result = await _recognizer.RecognizeAsync(dialogContext, activity, cancellationToken, telemetryProperties, telemetryMetrics).ConfigureAwait(false);
_recognizer.HttpClient = oldHandler;
if (middleware != null)
{
middleware.SetFallback(null);
}
return result;
}
private string ResponsePath(string utterance, LuisRecognizerOptionsV3 recognizer)
@ -143,28 +158,30 @@ namespace Microsoft.Bot.Builder.AI.Luis.Testing
return Path.Combine(_responseDir, $"{hash}.json");
}
private HttpClientHandler GetMockedClient(string utterance, LuisRecognizerOptionsV3 recognizer)
private async Task<HttpResponseMessage> FallbackAsync(HttpRequestMessage request, string utterance, LuisRecognizerOptionsV3 recognizer, CancellationToken cancellationToken)
{
HttpClientHandler client = null;
if (utterance != null)
var response = ResponsePath(utterance, recognizer);
if (File.Exists(response))
{
var response = ResponsePath(utterance, recognizer);
if (File.Exists(response))
var luisResult = File.ReadAllText(response);
return new HttpResponseMessage
{
#pragma warning disable CA2000 // Dispose objects before losing scope (ownership of handler is passed to MockedHttpClientHandler, that object should dispose it)
var handler = new MockHttpMessageHandler();
#pragma warning restore CA2000 // Dispose objects before losing scope
handler
.When(recognizer.Application.Endpoint + "*")
.WithPartialContent(utterance)
#pragma warning disable CA2000 // Dispose objects before losing scope (ownership of the File.OpenRead() stream is passed to MockedHttpClientHandler, that object should dispose it)
.Respond("application/json", File.OpenRead(response));
#pragma warning restore CA2000 // Dispose objects before losing scope
client = new MockedHttpClientHandler(handler.ToHttpClient());
}
Content = new StringContent(luisResult, Encoding.UTF8, "application/json"),
};
}
else
{
HttpResponseMessage result = null;
using (var client = new HttpClient())
using (var clonedRequest = await MockedHttpClientHandler.CloneHttpRequestMessageAsync(request).ConfigureAwait(false))
{
result = await client.SendAsync(clonedRequest, cancellationToken).ConfigureAwait(false);
}
return client;
var luisResult = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
File.WriteAllText(response, luisResult);
return result;
}
}
}
}

Просмотреть файл

@ -1,7 +1,11 @@
// Copyright(c) Microsoft Corporation.All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
@ -13,6 +17,8 @@ namespace Microsoft.Bot.Builder.AI.Luis.Testing
public class MockedHttpClientHandler : HttpClientHandler
{
private readonly HttpClient client;
private readonly HttpMessageHandler httpMessageHandler;
private readonly MethodInfo httpMessageHandlerMethod;
/// <summary>
/// Initializes a new instance of the <see cref="MockedHttpClientHandler"/> class.
@ -23,9 +29,73 @@ namespace Microsoft.Bot.Builder.AI.Luis.Testing
this.client = client;
}
/// <summary>
/// Initializes a new instance of the <see cref="MockedHttpClientHandler"/> class.
/// </summary>
/// <param name="httpMessageHandler">Handler to use.</param>
public MockedHttpClientHandler(HttpMessageHandler httpMessageHandler)
{
this.httpMessageHandler = httpMessageHandler;
// Call directly to avoid wrapping with HttpClient.
this.httpMessageHandlerMethod = httpMessageHandler.GetType().GetMethod(
nameof(SendAsync),
BindingFlags.Instance | BindingFlags.NonPublic,
Type.DefaultBinder,
new[] { typeof(HttpRequestMessage), typeof(CancellationToken) },
null);
}
/// <summary>
/// Clone everything of a HttpRequestMessage.
/// </summary>
/// <param name="request">The HttpRequestMessage to clone.</param>
/// <returns>The cloned HttpRequestMessage.</returns>
public static async Task<HttpRequestMessage> CloneHttpRequestMessageAsync(HttpRequestMessage request)
{
HttpRequestMessage clone = new HttpRequestMessage(request.Method, request.RequestUri);
#pragma warning disable CA2000 // Dispose objects before losing scope
var memoryStream = new MemoryStream();
#pragma warning restore CA2000 // Dispose objects before losing scope
if (request.Content != null)
{
await request.Content.CopyToAsync(memoryStream).ConfigureAwait(false);
memoryStream.Position = 0;
clone.Content = new StreamContent(memoryStream);
// Copy the content headers
if (request.Content.Headers != null)
{
foreach (var h in request.Content.Headers)
{
clone.Content.Headers.Add(h.Key, h.Value);
}
}
}
clone.Version = request.Version;
foreach (KeyValuePair<string, object> prop in request.Properties)
{
clone.Properties.Add(prop);
}
foreach (KeyValuePair<string, IEnumerable<string>> header in request.Headers)
{
clone.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
return clone;
}
/// <inheritdoc/>
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (httpMessageHandler != null)
{
return (Task<HttpResponseMessage>)httpMessageHandlerMethod.Invoke(httpMessageHandler, new object[] { request, cancellationToken });
}
#pragma warning disable CA2000 // Dispose objects before losing scope
var mockedRequest = new HttpRequestMessage()
{

Просмотреть файл

@ -32,6 +32,28 @@
"https://contoso.com"
]
},
"matchType": {
"type": "string",
"title": "Body Match Type",
"description": "The match type for body.",
"enum": [
"Exact",
"Partial"
],
"examples": [
"Exact",
"Partial"
],
"default": "Partial"
},
"body": {
"type": "string",
"title": "Body",
"description": "The body to match against request's body.",
"examples": [
"content"
]
},
"responses": {
"type": "array",
"title": "Responses",

Просмотреть файл

@ -51,19 +51,21 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Testing.TestActions
// if we have a reply
if (!string.IsNullOrEmpty(this.Text))
{
var description = this.Description != null ? this.Description + "\n" : string.Empty;
var message = $"${description}Text '{activity.Text}' didn't match expected text: {this.Text}'";
if (this.Exact)
{
// Normalize line endings to work on windows and mac
if (activity.AsMessageActivity()?.Text.Replace("\r", string.Empty) != this.Text.Replace("\r", string.Empty))
{
throw new Exception(this.Description ?? $"Text '{activity.Text}' didn't match expected text: {this.Text}'");
throw new Exception(message);
}
}
else
{
if (activity.AsMessageActivity()?.Text.ToLowerInvariant().Trim().Contains(this.Text.ToLowerInvariant().Trim()) == false)
{
throw new Exception(this.Description ?? $"Text '{activity.Text}' didn't match expected text: '{this.Text}'");
throw new Exception(message);
}
}
}

Просмотреть файл

@ -35,11 +35,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
private const string AdaptiveKey = "_adaptive";
private const string DefaultOperationKey = "$defaultOperation";
private const string ExpectedOnlyKey = "$expectedOnly";
private const string EntitiesKey = "$entities";
private const string InstanceKey = "$instance";
private const string NoneIntentKey = "None";
private const string OperationsKey = "$operations";
private const string PropertyNameKey = "PROPERTYName";
private const string UtteranceKey = "utterance";
// unique key for change tracking of the turn state (TURN STATE ONLY)
@ -781,7 +779,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
private async Task<bool> ProcessQueuesAsync(ActionContext actionContext, CancellationToken cancellationToken)
{
DialogEvent evt;
bool handled = false;
bool handled;
var assignments = EntityAssignments.Read(actionContext);
var nextAssignment = assignments.NextAssignment();
if (nextAssignment != null)
@ -908,7 +906,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
var utterance = activity?.AsMessageActivity()?.Text;
// Utterance is a special entity that corresponds to the full utterance
entities[UtteranceKey] = new List<EntityInfo> { new EntityInfo { Priority = int.MaxValue, Coverage = 1.0, Start = 0, End = utterance.Length, Name = UtteranceKey, Score = 0.0, Type = "string", Value = utterance, Text = utterance } };
entities[UtteranceKey] = new List<EntityInfo>
{
new EntityInfo { Priority = int.MaxValue, Coverage = 1.0, Start = 0, End = utterance.Length, Name = UtteranceKey, Score = 0.0, Type = "string", Value = utterance, Text = utterance }
};
var recognized = AssignEntities(actionContext, entities, assignments, lastEvent);
var unrecognized = SplitUtterance(utterance, recognized);
@ -941,7 +942,149 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
return unrecognized;
}
// Combine entity values and $instance meta-data
// Expand object that contains entities which can be op, property or leaf entity
private void ExpandEntityObject(
JObject entities, string op, string property, JObject rootInstance, List<string> operations, List<string> properties, uint turn, string text, Dictionary<string, List<EntityInfo>> entityToInfo)
{
foreach (var token in entities)
{
var entityName = token.Key;
var instances = entities[InstanceKey][entityName] as JArray;
ExpandEntities(entityName, token.Value as JArray, instances, rootInstance, op, property, operations, properties, turn, text, entityToInfo);
}
}
// Expand the array of entities for a particular entity
private void ExpandEntities(
string name, JArray entities, JArray instances, JObject rootInstance, string op, string property, List<string> operations, List<string> properties, uint turn, string text, Dictionary<string, List<EntityInfo>> entityToInfo)
{
if (!name.StartsWith("$", StringComparison.InvariantCulture))
{
string entityName = null;
var isOp = false;
var isProperty = false;
if (operations.Contains(name))
{
op = name;
isOp = true;
}
else if (properties.Contains(name))
{
property = name;
isProperty = true;
}
else
{
entityName = name;
}
for (var entityIndex = 0; entityIndex < entities.Count; ++entityIndex)
{
var entity = entities[entityIndex];
var instance = instances[entityIndex] as JObject;
var root = rootInstance;
if (root == null)
{
// Keep the root entity name and position to help with overlap
root = instance.DeepClone() as JObject;
root["type"] = $"{name}{entityIndex}";
}
if (entityName != null)
{
ExpandEntity(entityName, entity, instance, root, op, property, turn, text, entityToInfo);
}
else if (entity is JObject entityObject)
{
if (entityObject.Count == 0)
{
if (isOp)
{
// Handle operator with no children
ExpandEntity(op, null, instance, root, op, property, turn, text, entityToInfo);
}
else if (isProperty)
{
// Handle property with no children
ExpandEntity(property, null, instance, root, op, property, turn, text, entityToInfo);
}
}
else
{
ExpandEntityObject(entityObject, op, property, root, operations, properties, turn, text, entityToInfo);
}
}
}
}
}
// Expand a leaf entity into EntityInfo.
private void ExpandEntity(string name, object value, dynamic instance, dynamic rootInstance, string op, string property, uint turn, string text, Dictionary<string, List<EntityInfo>> entityToInfo)
{
if (instance != null && rootInstance != null)
{
if (!entityToInfo.TryGetValue(name, out List<EntityInfo> infos))
{
infos = new List<EntityInfo>();
entityToInfo[name] = infos;
}
var info = new EntityInfo
{
WhenRecognized = turn,
Name = name,
Value = value,
Operation = op,
Property = property,
Start = (int)rootInstance.startIndex,
End = (int)rootInstance.endIndex,
RootEntity = rootInstance.type,
Text = (string)(rootInstance.text ?? string.Empty),
Type = (string)(instance.type ?? null),
Score = (double)(instance.score ?? 0.0d),
Priority = 0,
};
info.Coverage = (info.End - info.Start) / (double)text.Length;
infos.Add(info);
}
}
// Combine entity values and $instance meta-data and expand out op/property
// Structure of entities.
//{
// "<op>": [
// // Op property
// {
// "<property>": [
// // Property without entities
// {},
// // Property with entities
// {
// "<entity>": [],
// "$instance": []
// }
// ],
// "$instance": []
// },
// // Op entity
// {
// "<entity> ": [],
// "$instance": []
// }
// ],
// // Direct property
// "<property>": [
// {},
// {
// "<entity>": [],
// "$instance": []
// }
// ],
// // Direct entity
// "<entity>": [],
// "$instance": []
//}
private Dictionary<string, List<EntityInfo>> NormalizeEntities(ActionContext actionContext)
{
var entityToInfo = new Dictionary<string, List<EntityInfo>>();
@ -950,49 +1093,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
{
var turn = actionContext.State.GetValue<uint>(DialogPath.EventCounter);
var operations = dialogSchema.Schema[OperationsKey]?.ToObject<List<string>>() ?? new List<string>();
var metaData = entities[InstanceKey];
foreach (var entry in entities)
{
var name = entry.Name;
if (operations.Contains(name))
{
for (var i = 0; i < entry.Value.Count; ++i)
{
var composite = entry.Value[i];
var childInstance = composite[InstanceKey];
EntityInfo pname = null;
if (composite.Count > 1)
{
// Find PROPERTYName so we can apply it to other entities
foreach (var child in composite)
{
if (child.Name == PropertyNameKey)
{
// Expand PROPERTYName and fold single match into siblings span
// TODO: Would we ever need to handle multiple?
var infos = new Dictionary<string, List<EntityInfo>>();
ExpandEntity(child, childInstance, name, null, turn, text, infos);
pname = infos[PropertyNameKey].First();
break;
}
}
}
foreach (var child in composite)
{
// Drop PROPERTYName if we are applying it to other entities
if (pname == null || child.Name != PropertyNameKey)
{
ExpandEntity(child, childInstance, name, pname, turn, text, entityToInfo);
}
}
}
}
else
{
ExpandEntity(entry, metaData, null, null, turn, text, entityToInfo);
}
}
var properties = dialogSchema.Property.Children.Select((prop) => prop.Name).ToList<string>();
ExpandEntityObject(entities, null, null, null, operations, properties, turn, text, entityToInfo);
}
// When there are multiple possible resolutions for the same entity that overlap, pick the one that covers the
@ -1045,84 +1147,14 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
return entityToInfo;
}
private void ExpandEntity(dynamic entry, dynamic metaData, string op, EntityInfo propertyName, uint turn, string text, Dictionary<string, List<EntityInfo>> entityToInfo)
{
var name = entry.Name;
if (!name.StartsWith("$"))
{
var values = entry.Value;
var instances = metaData?[name];
for (var i = 0; i < values.Count; ++i)
{
var val = values[i];
var instance = instances?[i];
if (!entityToInfo.TryGetValue(name, out List<EntityInfo> infos))
{
infos = new List<EntityInfo>();
entityToInfo[name] = infos;
}
var info = new EntityInfo
{
WhenRecognized = turn,
Name = name,
Value = val,
Operation = op
};
if (instance != null)
{
info.Start = (int)instance.startIndex;
info.End = (int)instance.endIndex;
info.Text = (string)(instance.text ?? string.Empty);
info.Type = (string)(instance.type ?? null);
info.Role = (string)(instance.role ?? null);
info.Score = (double)(instance.score ?? 0.0d);
}
// Eventually this could be passed in
info.Priority = info.Role == null ? 1 : 0;
info.Coverage = (info.End - info.Start) / (double)text.Length;
if (propertyName != null)
{
// Add property information to entities
if (propertyName.Start < info.Start)
{
info.Start = propertyName.Start;
}
if (propertyName.End > info.End)
{
info.End = propertyName.End;
}
// Expand entity to include possible property names
foreach (var property in propertyName.Value as JArray)
{
var newInfo = info.Clone() as EntityInfo;
newInfo.Property = property.Value<string>();
infos.Add(newInfo);
}
}
else
{
if (op != null && name == PropertyNameKey)
{
foreach (var property in val as JArray)
{
var newInfo = info.Clone() as EntityInfo;
newInfo.Property = property.Value<string>();
infos.Add(newInfo);
}
}
else
{
infos.Add(info);
}
}
}
}
}
// TODO: Probably should be assign operation in here as well, in we eventually wanted to expand to possible operations.
// Cases:
// ~op, ~prop, entity -> Assign default op and all possible properties
// ~op, prop, ~entity -> Assign default op?
// ~op, prop, entity -> Assign default op
// op, ~prop, ~entity -> Emit
// op, prop, ~entity -> Emit
// op, prop, entity --> Emit
// Generate possible entity to property mappings
private IEnumerable<EntityAssignment> Candidates(Dictionary<string, List<EntityInfo>> entities, string[] expected)
{
@ -1130,7 +1162,24 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
var usedEntityType = new HashSet<string> { UtteranceKey };
var usedEntity = new HashSet<EntityInfo>();
// Build map from entity to possible expected properties
var entityToExpected = new Dictionary<string, List<string>>();
foreach (var property in expected)
{
foreach (var entity in dialogSchema.PathToSchema(property).Entities)
{
if (!entityToExpected.TryGetValue(entity, out var expectedProperties))
{
expectedProperties = new List<string>();
entityToExpected[entity] = expectedProperties;
}
expectedProperties.Add(property);
}
}
// Emit entities that already have a property
// If property is in entityToExpected, then convert property to entity with expected properties as properties
foreach (var alternatives in entities.Values)
{
foreach (var alternative in alternatives)
@ -1138,13 +1187,33 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
if (alternative.Property != null)
{
usedEntity.Add(alternative);
yield return new EntityAssignment
if (entityToExpected.TryGetValue(alternative.Property, out var properties) && alternative.Operation == null)
{
Entity = alternative,
Property = alternative.Property,
Operation = alternative.Operation,
IsExpected = expected.Contains(alternative.Property)
};
// Property name is expected so rename and emit
foreach (var property in properties)
{
var entity = alternative.Clone() as EntityInfo;
entity.Property = property;
yield return new EntityAssignment
{
Entity = entity,
Property = entity.Property,
Operation = entity.Operation,
IsExpected = true
};
}
}
else
{
// Property corresponds directly to expected
yield return new EntityAssignment
{
Entity = alternative,
Property = alternative.Property,
Operation = alternative.Operation,
IsExpected = expected.Contains(alternative.Property)
};
}
}
}
}
@ -1176,15 +1245,14 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
}
}
// Unassigned entities
var entityPreferences = EntityPreferences(null);
// Entities with an operation, but no property
foreach (var entry in entities)
{
if (!usedEntityType.Contains(entry.Key) && entityPreferences.Contains(entry.Key))
if (!usedEntityType.Contains(entry.Key))
{
foreach (var entity in entry.Value)
{
if (!usedEntity.Contains(entity))
if (!usedEntity.Contains(entity) && entity.Operation != null)
{
yield return new EntityAssignment
{
@ -1228,37 +1296,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
}
}
// Remove any entities that overlap a selected entity
private void RemoveOverlappingEntities(EntityInfo entity, Dictionary<string, List<EntityInfo>> entities)
{
foreach (var infos in entities.Values)
{
infos.RemoveAll(e => e.Overlaps(entity));
}
}
private IReadOnlyList<string> EntityPreferences(string property)
{
IReadOnlyList<string> result;
if (property == null)
{
if (dialogSchema.Schema.ContainsKey(EntitiesKey))
{
result = dialogSchema.Schema[EntitiesKey].ToObject<List<string>>();
}
else
{
result = new List<string> { PropertyNameKey };
}
}
else
{
result = dialogSchema.PathToSchema(property).Entities;
}
return result;
}
// Have each property pick which overlapping entity is the best one
private IEnumerable<EntityAssignment> RemoveOverlappingPerProperty(IEnumerable<EntityAssignment> candidates)
{
@ -1266,7 +1303,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
group candidate by candidate.Property;
foreach (var propChoices in perProperty)
{
var entityPreferences = EntityPreferences(propChoices.Key);
var entityPreferences = dialogSchema.PathToSchema(propChoices.Key).Entities;
var choices = propChoices.ToList();
// Assume preference by order listed in mappings
@ -1288,7 +1325,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
if (candidate != null)
{
// Remove any overlapping entities
// Remove any overlapping entities without a common root
choices.RemoveAll(choice => choice.Entity.Overlaps(candidate.Entity));
yield return candidate;
}
@ -1373,12 +1410,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
existing.Dequeue(actionContext);
lastEvent = null;
}
else if (lastEvent == AdaptiveEvents.ChooseProperty && candidate.Operation == null && candidate.Entity.Name == PropertyNameKey)
else if (lastEvent == AdaptiveEvents.ChooseProperty && candidate.Operation == null && candidate.Property != null)
{
// NOTE: This assumes the existence of an entity named PROPERTYName for resolving this ambiguity
choices = existing.NextAssignment().Alternatives.ToList();
var property = (candidate.Entity.Value as JArray)?[0]?.ToObject<string>();
var choice = choices.Find(p => p.Property == property);
var choice = choices.Find(p => p.Property == candidate.Entity.Name);
if (choice != null)
{
// Resolve choice, pretend it was expected and add to assignments
@ -1430,7 +1465,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
return usedEntities.ToList();
}
// a replaces b when it refers to the same singleton property and is newer or later in same utterance and it is not over PROPERTYName
// a replaces b when it refers to the same singleton property and is newer or later in same utterance and it is not a bare property
// -1 a replaces b
// 0 no replacement
// +1 b replaces a
@ -1441,7 +1476,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
{
foreach (var bAlt in b.Alternatives)
{
if (aAlt.Property == bAlt.Property && aAlt.Entity.Name != PropertyNameKey && bAlt.Entity.Name != PropertyNameKey)
if (aAlt.Property == bAlt.Property && aAlt.Entity.Value != null && bAlt.Entity.Value != null)
{
var prop = dialogSchema.PathToSchema(aAlt.Property);
if (!prop.IsArray)

Просмотреть файл

@ -10,9 +10,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
/// </summary>
/// <remarks>
/// Compare by event: AssignEntity, ChooseProperty, ChooseEntity
/// Then unexpected before expected
/// Then by oldest first
/// Then by order of operations passed in.
/// Then by operations in order from schema (usually within AssignEntity).
/// Then by unexpected before expected.
/// Then by oldest turn first.
/// Then by minimum position in utterance.
/// </remarks>
public class EntityAssignmentComparer : Comparer<EntityAssignment>
{
@ -36,16 +37,21 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
int comparison = Array.IndexOf(eventPreference, x.Event).CompareTo(Array.IndexOf(eventPreference, y.Event));
if (comparison == 0)
{
// Unexpected before expected
comparison = x.IsExpected.CompareTo(y.IsExpected);
// Order by operations
comparison = Array.IndexOf(operationPreference, x.Operation).CompareTo(Array.IndexOf(operationPreference, y.Operation));
if (comparison == 0)
{
// Order by history
comparison = x.Entity.WhenRecognized.CompareTo(y.Entity.WhenRecognized);
// Unexpected before expected
comparison = x.IsExpected.CompareTo(y.IsExpected);
if (comparison == 0)
{
// Order by operations
comparison = Array.IndexOf(operationPreference, x.Operation).CompareTo(Array.IndexOf(operationPreference, y.Operation));
// Order by history
comparison = x.Entity.WhenRecognized.CompareTo(y.Entity.WhenRecognized);
if (comparison == 0)
{
// Order by position in utterance
comparison = x.Entity.Start.CompareTo(y.Entity.Start);
}
}
}
}

Просмотреть файл

@ -12,7 +12,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
/// Tracks entity related events to surface.
/// </summary>
/// <remarks>
/// When processing entities possible ambiguity are identified and when resolved they turn into assign events.
/// When processing entities possible ambiguities are identified and when resolved they turn into assign events.
/// This tracking persists across multiple input utterances.
/// </remarks>
public class EntityAssignments
@ -50,7 +50,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
=> actionContext.State.SetValue(Events, this);
/// <summary>
/// Return the next enetity event to surface.
/// Return the next entity event to surface.
/// </summary>
/// <returns>Next event to surface.</returns>
public EntityAssignment NextAssignment() => Assignments.Any() ? Assignments[0] : null;

Просмотреть файл

@ -67,13 +67,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
[JsonProperty("text")]
public string Text { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the role the entity played in utterance.
/// </summary>
/// <value>Role of entity.</value>
[JsonProperty("role")]
public string Role { get; set; } = string.Empty;
/// <summary>
/// Gets or sets type of entity.
/// </summary>
@ -81,6 +74,13 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
[JsonProperty("type")]
public string Type { get; set; } = string.Empty;
/// <summary>
/// Gets or sets root entity where this entity was found.
/// </summary>
/// <value>Root entity name plus index.</value>
[JsonProperty("rootEntity")]
public string RootEntity { get; set; } = string.Empty;
/// <summary>
/// Gets or sets relative priority of entity compared to other entities with 0 being highest priority.
/// </summary>
@ -108,7 +108,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
/// <param name="entity">Entity to compare.</param>
/// <returns>True if entities overlap.</returns>
public bool Overlaps(EntityInfo entity)
=> Start <= entity.End && End >= entity.Start;
=> (entity == this || entity.RootEntity != RootEntity) && Start <= entity.End && End >= entity.Start;
/// <summary>
/// True if entities come from exactly the same text in the utterance.
@ -124,7 +124,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
/// <param name="entity">Entity to compare.</param>
/// <returns>True if entity text completely covers other entity text.</returns>
public bool Covers(EntityInfo entity)
=> Start <= entity.Start && End >= entity.End && End - Start > entity.End - entity.Start;
=> (entity == this || entity.RootEntity != RootEntity) && Start <= entity.Start && End >= entity.End && End - Start > entity.End - entity.Start;
public override string ToString()
=> $"{Operation}({Name}:{Value}) P{Priority} {Score} {Coverage}";

Просмотреть файл

@ -30,6 +30,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
private readonly ConcurrentDictionary<string, Type> kindToType = new ConcurrentDictionary<string, Type>();
private readonly ConcurrentDictionary<Type, List<string>> typeToKinds = new ConcurrentDictionary<Type, List<string>>();
private List<ResourceProvider> resourceProviders = new List<ResourceProvider>();
private List<IComponentDeclarativeTypes> declarativeTypes;
private CancellationTokenSource cancelReloadToken = new CancellationTokenSource();
private ConcurrentBag<Resource> changedResources = new ConcurrentBag<Resource>();
private bool typesLoaded = false;
@ -49,9 +50,19 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
/// </summary>
/// <param name="providers">The list of resource providers to initialize the current instance.</param>
public ResourceExplorer(IEnumerable<ResourceProvider> providers)
: this()
: this(providers, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ResourceExplorer"/> class.
/// </summary>
/// <param name="providers">The list of resource providers to initialize the current instance.</param>
/// <param name="declarativeTypes">A list of declarative types to use. Falls back to <see cref="ComponentRegistration.Components" /> if set to null.</param>
public ResourceExplorer(IEnumerable<ResourceProvider> providers, IEnumerable<IComponentDeclarativeTypes> declarativeTypes)
{
this.resourceProviders = providers.ToList();
this.declarativeTypes = declarativeTypes?.ToList();
}
/// <summary>
@ -495,6 +506,11 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
Changed?.Invoke(this, resources);
}
private IEnumerable<IComponentDeclarativeTypes> GetComponentRegistrations()
{
return this.declarativeTypes ?? ComponentRegistration.Components.OfType<IComponentDeclarativeTypes>();
}
private void RegisterTypeInternal(string kind, Type type, ICustomDeserializer loader = null)
{
// Default loader if none specified
@ -543,7 +559,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
// this can be reentrant, and we only want to do once.
this.typesLoaded = true;
foreach (var component in ComponentRegistration.Components.OfType<IComponentDeclarativeTypes>())
foreach (var component in GetComponentRegistrations())
{
if (component != null)
{

Просмотреть файл

@ -23,6 +23,7 @@ namespace Microsoft.Bot.Builder.Dialogs
private const string LastAccess = "_lastAccess";
private string _rootDialogId;
private readonly string _dialogStateProperty;
private readonly object _lock = new object();
/// <summary>
/// Initializes a new instance of the <see cref="DialogManager"/> class.
@ -69,33 +70,7 @@ namespace Microsoft.Bot.Builder.Dialogs
/// <value>
/// Root dialog to use to start conversation.
/// </value>
public Dialog RootDialog
{
get
{
if (_rootDialogId != null)
{
return Dialogs.Find(_rootDialogId);
}
return null;
}
set
{
Dialogs = new DialogSet();
if (value != null)
{
_rootDialogId = value.Id;
Dialogs.TelemetryClient = value.TelemetryClient;
Dialogs.Add(value);
}
else
{
_rootDialogId = null;
}
}
}
public Dialog RootDialog { get; set; }
/// <summary>
/// Gets or sets global dialogs that you want to have be callable.
@ -128,6 +103,20 @@ namespace Microsoft.Bot.Builder.Dialogs
/// <returns>result of the running the logic against the activity.</returns>
public async Task<DialogManagerResult> OnTurnAsync(ITurnContext context, CancellationToken cancellationToken = default)
{
// Lazy initialize rootdialog so it can refer to assets like LG function templates
if (_rootDialogId == null)
{
lock (_lock)
{
if (_rootDialogId == null)
{
_rootDialogId = RootDialog.Id;
Dialogs.TelemetryClient = RootDialog.TelemetryClient;
Dialogs.Add(RootDialog);
}
}
}
var botStateSet = new BotStateSet();
// Preload TurnState with DM TurnState.

Просмотреть файл

@ -19,7 +19,9 @@ IMPORT : WHITESPACE* '[' ~[\r\n[\]]*? ']' '(' ~[\r\n()]*? ')' WHITESPACE* { !sta
TEMPLATE_NAME_LINE : WHITESPACE* '#' ~('\r'|'\n')* { _tokenStartCharPositionInLine == 0}? { startTemplate = true; };
MULTILINE_PREFIX: WHITESPACE* '-' WHITESPACE* '```' { startTemplate && _tokenStartCharPositionInLine == 0 }? -> pushMode(MULTILINE_MODE);
INLINE_MULTILINE: WHITESPACE* '-' WHITESPACE* '```' ~('\r'|'\n')* '```' WHITESPACE* { startTemplate && _tokenStartCharPositionInLine == 0 }?;
MULTILINE_PREFIX: WHITESPACE* '-' WHITESPACE* '```' ~('\r'|'\n')* { startTemplate && _tokenStartCharPositionInLine == 0 }? -> pushMode(MULTILINE_MODE);
TEMPLATE_BODY : ~('\r'|'\n')+ { startTemplate }?;

Просмотреть файл

@ -48,5 +48,5 @@ templateBody
;
templateBodyLine
: ((TEMPLATE_BODY | (MULTILINE_PREFIX (MULTILINE_TEXT|ESCAPE_CHARACTER)+ MULTILINE_SUFFIX?)) NEWLINE?) | NEWLINE
: ((TEMPLATE_BODY | INLINE_MULTILINE | (MULTILINE_PREFIX (MULTILINE_TEXT|ESCAPE_CHARACTER)+ MULTILINE_SUFFIX?)) NEWLINE?) | NEWLINE
;

Просмотреть файл

@ -41,7 +41,7 @@ fragment ESCAPE_CHARACTER_FRAGMENT : '\\' ~[\r\n]?;
fragment IDENTIFIER : (LETTER | NUMBER | '_') (LETTER | NUMBER | '_')*;
fragment OBJECT_DEFINITION
: '{' ((WHITESPACE) | ((IDENTIFIER | STRING_LITERAL) ':' ( STRING_LITERAL | ~[{}\r\n'"`] | OBJECT_DEFINITION)+))* '}'
: '{' ((WHITESPACE) | ((IDENTIFIER | STRING_LITERAL) ':' ( STRING_LITERAL | ~[{}'"`] | OBJECT_DEFINITION)+))* '}'
;
fragment EXPRESSION_FRAGMENT

Просмотреть файл

@ -183,7 +183,7 @@ namespace Microsoft.Bot.Connector.Authentication
/// <param name="authConfig">An <see cref="AuthenticationConfiguration"/> instance.</param>
/// <param name="claims">The list of claims to validate.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
/// <exception cref="UnauthorizedAccessException">If the validation returns false.</exception>
/// <exception cref="UnauthorizedAccessException">If the validation returns false, or ClaimsValidator is null and this is a skill claim.</exception>
internal static async Task ValidateClaimsAsync(AuthenticationConfiguration authConfig, IEnumerable<Claim> claims)
{
if (authConfig.ClaimsValidator != null)
@ -192,6 +192,10 @@ namespace Microsoft.Bot.Connector.Authentication
var claimsList = claims as IList<Claim> ?? claims.ToList();
await authConfig.ClaimsValidator.ValidateClaimsAsync(claimsList).ConfigureAwait(false);
}
else if (SkillValidation.IsSkillClaim(claims))
{
throw new UnauthorizedAccessException("ClaimsValidator is required for validation of Skill Host calls.");
}
}
/// <summary>

Просмотреть файл

@ -151,6 +151,7 @@ namespace AdaptiveExpressions.Tests
Test("formatNumber(1,2.0)"), // the second parameter should be an integer
Test("formatNumber(hello,2.0)"), // the first parameter should be a number
Test("formatNumber(hello,2232131231231)"), // the first parameter should be a 32-bit signed integer
Test("jsonStringify(hello,2232131231231)"), // shoule have 1 param
#endregion
#region Math functions test

Просмотреть файл

@ -383,6 +383,12 @@ namespace AdaptiveExpressions.Tests
Test("json(`{\"foo\":${{text:\"hello\"}},\"item\": \"${world}\"}`).foo.text", "hello"),
Test("json(`{\"foo\":${{\"text\":\"hello\"}},\"item\": \"${world}\"}`).foo.text", "hello"),
Test("`{expr: hello all}`", "{expr: hello all}"),
Test("`${hello}\n\n${world}`", "hello\n\nworld"),
Test("`${hello}\r\n${world}`", "hello\r\nworld"),
Test("`\n\n${world}`", "\n\nworld"),
Test("`\r\n${world}`", "\r\nworld"),
Test("`${hello}\n\n`", "hello\n\n"),
Test("`${hello}\r\n`", "hello\r\n"),
#endregion
#region SetPathToProperty test
@ -711,6 +717,10 @@ namespace AdaptiveExpressions.Tests
Test("uriComponentToString('http%3A%2F%2Fcontoso.com')", "http://contoso.com"),
Test("json(jsonContainsDatetime).date", "/Date(634250351766060665)/"),
Test("json(jsonContainsDatetime).invalidDate", "/Date(whatever)/"),
Test("jsonStringify(json('{\"a\":\"b\"}'))", "{\"a\":\"b\"}"),
Test("jsonStringify('a')", "\"a\""),
Test("jsonStringify(null)", "null"),
Test("jsonStringify({a:'b'})", "{\"a\":\"b\"}"),
Test("formatNumber(20.0000, 2, 'en-US')", "20.00"),
Test("formatNumber(12.123, 2, 'en-US')", "12.12"),
Test("formatNumber(1.551, 2, 'en-US')", "1.55"),
@ -1008,6 +1018,7 @@ namespace AdaptiveExpressions.Tests
Test("addProperty({}, 'name', user.name).name", null),
Test("string(merge(json(json1), json(json2)))", "{\"FirstName\":\"John\",\"LastName\":\"Smith\",\"Enabled\":true,\"Roles\":[\"Customer\",\"Admin\"]}"),
Test("string(merge(json(json1), json(json2), json(json3)))", "{\"FirstName\":\"John\",\"LastName\":\"Smith\",\"Enabled\":true,\"Roles\":[\"Customer\",\"Admin\"],\"Age\":36}"),
Test("merge(callstack[1], callstack[2]).z", 1),
#endregion
#region Memory access

Просмотреть файл

@ -32,8 +32,4 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Tests\LuisRecognizerTests\cachedResponses\ExternalEntities_test_en_us_lu\" />
</ItemGroup>
</Project>

Просмотреть файл

@ -6,8 +6,8 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs.Adaptive.Actions;
using Microsoft.Bot.Builder.Dialogs.Adaptive.Testing.Mocks;
using Microsoft.Bot.Builder.AI.Luis;
using Microsoft.Bot.Builder.AI.Luis.Testing;
using Microsoft.Bot.Builder.Dialogs.Declarative.Resources;
using Microsoft.Extensions.Configuration;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@ -17,6 +17,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Tests
[TestClass]
public class TestScriptTests
{
private readonly string luisMockDirectory = PathUtils.NormalizePath(@"..\..\..\..\..\tests\Microsoft.Bot.Builder.Dialogs.Adaptive.Tests\Tests\TestScriptTests\LuisMock\");
public static ResourceExplorer ResourceExplorer { get; set; }
public TestContext TestContext { get; set; }
@ -99,6 +101,20 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Tests
await TestUtils.RunTestScript(ResourceExplorer);
}
[TestMethod]
public async Task TestScriptTests_HttpRequestLuisMock()
{
var config = new ConfigurationBuilder()
.UseMockLuisSettings(luisMockDirectory, "TestBot")
.Build();
var resourceExplorer = new ResourceExplorer()
.AddFolder(Path.Combine(TestUtils.GetProjectPath(), "Tests", nameof(TestScriptTests)), monitorChanges: false)
.RegisterType(LuisAdaptiveRecognizer.Kind, typeof(MockLuisRecognizer), new MockLuisLoader(config));
await TestUtils.RunTestScript(resourceExplorer, configuration: config);
}
[TestMethod]
public async Task TestScriptTests_CustomEvent()
{

Просмотреть файл

@ -1,340 +1,256 @@
{
"$schema": "../../../tests.schema",
"$kind": "Microsoft.Test.Script",
"dialog": "sandwichTest.main",
"script": [
{
"$kind": "Microsoft.Test.UserSays",
"text": "hi!"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Welcome!"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Enter a value for name"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "chris"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Which value do you want for bread?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "rye"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Which value do you want for cheese?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "swiss"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Which value do you want for meat?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "ham"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "What values do you want to add for toppings?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "lettuce and pickles"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "What values do you want to add for sauces?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "yellow mustard"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Enter a value for price"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "$3.25"
},
{
"$kind": "Microsoft.Test.AssertReplyActivity",
"assertions": [
"type == 'message'",
"count(attachments) == 1",
"attachments[0].content.type == 'AdaptiveCard'",
"count(attachments[0].content.body) == 2",
"count(attachments[0].content.body[1].facts) == 9",
"attachments[0].content.body[1].facts[0].value == 'no value'",
"attachments[0].content.body[1].facts[1].value == 'no value'",
"attachments[0].content.body[1].facts[2].value == 'chris'",
"attachments[0].content.body[1].facts[3].value == 'rye'",
"attachments[0].content.body[1].facts[4].value == 'ham'",
"attachments[0].content.body[1].facts[5].value == 'swiss'",
"attachments[0].content.body[1].facts[6].value == 'lettuce, pickles'",
"attachments[0].content.body[1].facts[7].value == 'yellow mustard'",
"attachments[0].content.body[1].facts[8].value == '3.25 Dollar'"
]
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Is there any property you want to change? (no or the property name)"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "remove bread"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "bread has been cleared."
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Which value do you want for bread?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "wheat"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Please choose a value for bread from [multi grain wheat, whole wheat]"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "whole wheat with turkey"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "meat is changed from ham to turkey."
},
{
"$kind": "Microsoft.Test.AssertReplyActivity",
"assertions": [
"type == 'message'",
"count(attachments) == 1",
"attachments[0].content.type == 'AdaptiveCard'",
"count(attachments[0].content.body) == 2",
"count(attachments[0].content.body[1].facts) == 9",
"attachments[0].content.body[1].facts[0].value == 'no value'",
"attachments[0].content.body[1].facts[1].value == 'no value'",
"attachments[0].content.body[1].facts[2].value == 'chris'",
"attachments[0].content.body[1].facts[3].value == 'whole wheat'",
"attachments[0].content.body[1].facts[4].value == 'turkey'",
"attachments[0].content.body[1].facts[5].value == 'swiss'",
"attachments[0].content.body[1].facts[6].value == 'lettuce, pickles'",
"attachments[0].content.body[1].facts[7].value == 'yellow mustard'",
"attachments[0].content.body[1].facts[8].value == '3.25 Dollar'"
]
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Is there any property you want to change? (no or the property name)"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "dlkj"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Sorry, I do not understand 'dlkj'"
},
{
"$kind": "Microsoft.Test.AssertReplyActivity",
"assertions": [
"type == 'message'",
"count(attachments) == 1",
"attachments[0].content.type == 'AdaptiveCard'",
"count(attachments[0].content.body) == 2",
"count(attachments[0].content.body[1].facts) == 9",
"attachments[0].content.body[1].facts[0].value == 'no value'",
"attachments[0].content.body[1].facts[1].value == 'no value'",
"attachments[0].content.body[1].facts[2].value == 'chris'",
"attachments[0].content.body[1].facts[3].value == 'whole wheat'",
"attachments[0].content.body[1].facts[4].value == 'turkey'",
"attachments[0].content.body[1].facts[5].value == 'swiss'",
"attachments[0].content.body[1].facts[6].value == 'lettuce, pickles'",
"attachments[0].content.body[1].facts[7].value == 'yellow mustard'",
"attachments[0].content.body[1].facts[8].value == '3.25 Dollar'"
]
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Is there any property you want to change? (no or the property name)"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "sure"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Which property do you want to change?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "toppings"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "What values do you want to add for toppings?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "none"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Did you mean \"none\" as add to meat or \"none\" as add to cheese?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "cheese and roast beef"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "meat is changed from turkey to roast beef."
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "What values do you want to add for toppings?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "show cheese"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "cheese: none"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "toppings is a list from: [tomato, lettuce, pickles, green peppers, red pepppers, white onions, red onions]\nWhat values do you want to add for toppings?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "tomato"
},
{
"$kind": "Microsoft.Test.AssertReplyActivity",
"assertions": [
"type == 'message'",
"count(attachments) == 1",
"attachments[0].content.type == 'AdaptiveCard'",
"count(attachments[0].content.body) == 2",
"count(attachments[0].content.body[1].facts) == 9",
"attachments[0].content.body[1].facts[0].value == 'no value'",
"attachments[0].content.body[1].facts[1].value == 'no value'",
"attachments[0].content.body[1].facts[2].value == 'chris'",
"attachments[0].content.body[1].facts[3].value == 'whole wheat'",
"attachments[0].content.body[1].facts[4].value == 'roast beef'",
"attachments[0].content.body[1].facts[5].value == 'none'",
"attachments[0].content.body[1].facts[6].value == 'lettuce, pickles, tomato'",
"attachments[0].content.body[1].facts[7].value == 'yellow mustard'",
"attachments[0].content.body[1].facts[8].value == '3.25 Dollar'"
]
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Is there any property you want to change? (no or the property name)"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "remove name"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "name has been cleared."
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Enter a value for name"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "wheat ham and swiss"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Did you mean \"wheat\" as add to bread or \"wheat ham and swiss\" as add to name or \"ham\" as add to meat or \"swiss\" as add to cheese?"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "meat"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "cheese is changed from none to swiss."
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Please choose a value for bread from [multi grain wheat, whole wheat]"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "multi grain"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Enter a value for name"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "bob"
},
{
"$kind": "Microsoft.Test.AssertReplyActivity",
"assertions": [
"type == 'message'",
"count(attachments) == 1",
"attachments[0].content.type == 'AdaptiveCard'",
"count(attachments[0].content.body) == 2",
"count(attachments[0].content.body[1].facts) == 9",
"attachments[0].content.body[1].facts[0].value == 'no value'",
"attachments[0].content.body[1].facts[1].value == 'no value'",
"attachments[0].content.body[1].facts[2].value == 'bob'",
"attachments[0].content.body[1].facts[3].value == 'multi grain wheat'",
"attachments[0].content.body[1].facts[4].value == 'ham'",
"attachments[0].content.body[1].facts[5].value == 'swiss'",
"attachments[0].content.body[1].facts[6].value == 'lettuce, pickles, tomato'",
"attachments[0].content.body[1].facts[7].value == 'yellow mustard'",
"attachments[0].content.body[1].facts[8].value == '3.25 Dollar'"
]
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Is there any property you want to change? (no or the property name)"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "no"
}
]
}
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/main/experimental/generation/TestBot/TestBot/TestBot.schema",
"$kind": "Microsoft.Test.Script",
"dialog": "sandwich",
"script": [
{
"$kind": "Microsoft.Test.UserConversationUpdate",
"membersAdded": [
"Bot",
"User"
],
"membersRemoved": []
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Welcome!"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Enter a value for name"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "wheat"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Did you mean add \"wheat\"\" to bread or add \"wheat\"\" to name?",
"description": "Response to input 1"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "bread"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Please choose a value for bread from [multi grain wheat, whole wheat]",
"description": "Response to input 2"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "whole wheat"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Enter a value for name",
"description": "Response to input 3"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "Chris"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Which value do you want for cheese?",
"description": "Response to input 4"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "ham and swiss with pickles and lettuce"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "meat is set to ham.",
"description": "Response to input 5"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Added pickles to toppings",
"description": "Response to input 5"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Added lettuce to toppings",
"description": "Response to input 5"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "What values do you want to add for sauces?",
"description": "Response to input 5"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "dijon, remove pickles and show toppings"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Removed pickles from toppings",
"description": "Response to input 6"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "toppings: lettuce",
"description": "Response to input 6"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Enter a value for price",
"description": "Response to input 6"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "$3"
},
{
"$kind": "Microsoft.Test.AssertReplyActivity",
"assertions": [
"type == 'message'",
"count(attachments) == 1",
"attachments[0].contentType == 'application/vnd.microsoft.card.adaptive'",
"attachments[0].content.type == 'AdaptiveCard'",
"attachments[0].content.version == '1.0'",
"count(attachments[0].content.body) == 2",
"attachments[0].content.body[0].type == 'TextBlock'",
"attachments[0].content.body[0].text == 'sandwich'",
"attachments[0].content.body[0].size == 'large'",
"attachments[0].content.body[1].type == 'FactSet'",
"count(attachments[0].content.body[1].facts) == 9",
"attachments[0].content.body[1].facts[0].title == 'quantity'",
"attachments[0].content.body[1].facts[0].value == 'no value'",
"attachments[0].content.body[1].facts[1].title == 'length'",
"attachments[0].content.body[1].facts[1].value == 'no value'",
"attachments[0].content.body[1].facts[2].title == 'name'",
"attachments[0].content.body[1].facts[2].value == 'Chris'",
"attachments[0].content.body[1].facts[3].title == 'bread'",
"attachments[0].content.body[1].facts[3].value == 'whole wheat'",
"attachments[0].content.body[1].facts[4].title == 'meat'",
"attachments[0].content.body[1].facts[4].value == 'ham'",
"attachments[0].content.body[1].facts[5].title == 'cheese'",
"attachments[0].content.body[1].facts[5].value == 'swiss'",
"attachments[0].content.body[1].facts[6].title == 'toppings'",
"attachments[0].content.body[1].facts[6].value == 'lettuce'",
"attachments[0].content.body[1].facts[7].title == 'sauces'",
"attachments[0].content.body[1].facts[7].value == 'dijon mustard'",
"attachments[0].content.body[1].facts[8].title == 'price'",
"attachments[0].content.body[1].facts[8].value == '(number: 3, units: Dollar)'",
"attachments[0].content.$schema == 'http://adaptivecards.io/schemas/adaptive-card.json'"
],
"description": "Response to input 7"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Is there any property you want to change? (no or the property name)",
"description": "Response to input 7"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "6 inch"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "length is set as (number: 6, units: Inch).",
"description": "Response to input 8"
},
{
"$kind": "Microsoft.Test.AssertReplyActivity",
"assertions": [
"type == 'message'",
"count(attachments) == 1",
"attachments[0].contentType == 'application/vnd.microsoft.card.adaptive'",
"attachments[0].content.type == 'AdaptiveCard'",
"attachments[0].content.version == '1.0'",
"count(attachments[0].content.body) == 2",
"attachments[0].content.body[0].type == 'TextBlock'",
"attachments[0].content.body[0].text == 'sandwich'",
"attachments[0].content.body[0].size == 'large'",
"attachments[0].content.body[1].type == 'FactSet'",
"count(attachments[0].content.body[1].facts) == 9",
"attachments[0].content.body[1].facts[0].title == 'quantity'",
"attachments[0].content.body[1].facts[0].value == 'no value'",
"attachments[0].content.body[1].facts[1].title == 'length'",
"attachments[0].content.body[1].facts[1].value == '(number: 6, units: Inch)'",
"attachments[0].content.body[1].facts[2].title == 'name'",
"attachments[0].content.body[1].facts[2].value == 'Chris'",
"attachments[0].content.body[1].facts[3].title == 'bread'",
"attachments[0].content.body[1].facts[3].value == 'whole wheat'",
"attachments[0].content.body[1].facts[4].title == 'meat'",
"attachments[0].content.body[1].facts[4].value == 'ham'",
"attachments[0].content.body[1].facts[5].title == 'cheese'",
"attachments[0].content.body[1].facts[5].value == 'swiss'",
"attachments[0].content.body[1].facts[6].title == 'toppings'",
"attachments[0].content.body[1].facts[6].value == 'lettuce'",
"attachments[0].content.body[1].facts[7].title == 'sauces'",
"attachments[0].content.body[1].facts[7].value == 'dijon mustard'",
"attachments[0].content.body[1].facts[8].title == 'price'",
"attachments[0].content.body[1].facts[8].value == '(number: 3, units: Dollar)'",
"attachments[0].content.$schema == 'http://adaptivecards.io/schemas/adaptive-card.json'"
],
"description": "Response to input 8"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Is there any property you want to change? (no or the property name)",
"description": "Response to input 8"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "bread"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Which value do you want for bread?",
"description": "Response to input 9"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "rye"
},
{
"$kind": "Microsoft.Test.AssertReplyActivity",
"assertions": [
"type == 'message'",
"count(attachments) == 1",
"attachments[0].contentType == 'application/vnd.microsoft.card.adaptive'",
"attachments[0].content.type == 'AdaptiveCard'",
"attachments[0].content.version == '1.0'",
"count(attachments[0].content.body) == 2",
"attachments[0].content.body[0].type == 'TextBlock'",
"attachments[0].content.body[0].text == 'sandwich'",
"attachments[0].content.body[0].size == 'large'",
"attachments[0].content.body[1].type == 'FactSet'",
"count(attachments[0].content.body[1].facts) == 9",
"attachments[0].content.body[1].facts[0].title == 'quantity'",
"attachments[0].content.body[1].facts[0].value == 'no value'",
"attachments[0].content.body[1].facts[1].title == 'length'",
"attachments[0].content.body[1].facts[1].value == '(number: 6, units: Inch)'",
"attachments[0].content.body[1].facts[2].title == 'name'",
"attachments[0].content.body[1].facts[2].value == 'Chris'",
"attachments[0].content.body[1].facts[3].title == 'bread'",
"attachments[0].content.body[1].facts[3].value == 'rye'",
"attachments[0].content.body[1].facts[4].title == 'meat'",
"attachments[0].content.body[1].facts[4].value == 'ham'",
"attachments[0].content.body[1].facts[5].title == 'cheese'",
"attachments[0].content.body[1].facts[5].value == 'swiss'",
"attachments[0].content.body[1].facts[6].title == 'toppings'",
"attachments[0].content.body[1].facts[6].value == 'lettuce'",
"attachments[0].content.body[1].facts[7].title == 'sauces'",
"attachments[0].content.body[1].facts[7].value == 'dijon mustard'",
"attachments[0].content.body[1].facts[8].title == 'price'",
"attachments[0].content.body[1].facts[8].value == '(number: 3, units: Dollar)'",
"attachments[0].content.$schema == 'http://adaptivecards.io/schemas/adaptive-card.json'"
],
"description": "Response to input 10"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Is there any property you want to change? (no or the property name)",
"description": "Response to input 10"
},
{
"$kind": "Microsoft.Test.UserSays",
"text": "no"
}
],
"httpRequestMocks": []
}

Просмотреть файл

@ -1,28 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "AddToBread",
"entity": "BreadEntity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${setPropertyMessage('Bread', @BreadEntity)}"
},
{
"$kind": "Microsoft.SetProperty",
"property": "$Bread",
"value": "=@BreadEntity"
},
{
"$kind": "Microsoft.IfCondition",
"condition": "$PropertyToChange == 'Bread'",
"actions": [
{
"$kind": "Microsoft.DeleteProperty",
"property": "$PropertyToChange"
}
]
}
],
"$Generator": "cb2dce5fef44e55fd210a2973ebdd262"
}

Просмотреть файл

@ -1,17 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ClearBread",
"property": "Bread",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${clearPropertyMessage('Bread')}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "$Bread"
}
],
"$Generator": "4097bda89b8d1ec502139965e7447c14"
}

Просмотреть файл

@ -1,16 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnEndOfActions",
"condition": "!$Bread || $PropertyToChange == 'Bread'",
"priority": "=indexOf(dialog.requiredProperties, 'Bread')",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${AskBread()}",
"expectedProperties": [
"Bread"
]
}
],
"$Generator": "d59eee2921f8740e09ead7109fe7d8a7"
}

Просмотреть файл

@ -1,23 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "RemoveFromBread",
"entity": "BreadEntity",
"actions": [
{
"$kind": "Microsoft.IfCondition",
"condition": "$Bread == @BreadEntity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${removePropertyMessage('Bread', @BreadEntity)}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "Bread"
}
]
}
],
"$Generator": "f7f67e73bb79c22886730e3e80ab76d9"
}

Просмотреть файл

@ -1,13 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ShowBread",
"property": "Bread",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${showPropertyMessage(@PROPERTYName)}"
}
],
"$Generator": "1dd42d377dd4c87243b93e03122219a7"
}

Просмотреть файл

@ -1,15 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnChooseEntity",
"entity": "BreadEntity",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${chooseBreadEntity()}",
"expectedProperties": [
"Bread"
]
}
],
"$Generator": "f6e0e6e9eaa46616e6f0527bd42187cc"
}

Просмотреть файл

@ -1,28 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "AddToCheese",
"entity": "CheeseEntity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${setPropertyMessage('Cheese', @CheeseEntity)}"
},
{
"$kind": "Microsoft.SetProperty",
"property": "$Cheese",
"value": "=@CheeseEntity"
},
{
"$kind": "Microsoft.IfCondition",
"condition": "$PropertyToChange == 'Cheese'",
"actions": [
{
"$kind": "Microsoft.DeleteProperty",
"property": "$PropertyToChange"
}
]
}
],
"$Generator": "0d82c5ddb86a9faa794f6c4357829733"
}

Просмотреть файл

@ -1,17 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ClearCheese",
"property": "Cheese",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${clearPropertyMessage('Cheese')}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "$Cheese"
}
],
"$Generator": "99275bde03f2ad1865c6e24b9101e6ec"
}

Просмотреть файл

@ -1,16 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnEndOfActions",
"condition": "!$Cheese || $PropertyToChange == 'Cheese'",
"priority": "=indexOf(dialog.requiredProperties, 'Cheese')",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${AskCheese()}",
"expectedProperties": [
"Cheese"
]
}
],
"$Generator": "5a72cb8db03c87b150b1925ec37ab439"
}

Просмотреть файл

@ -1,23 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "RemoveFromCheese",
"entity": "CheeseEntity",
"actions": [
{
"$kind": "Microsoft.IfCondition",
"condition": "$Cheese == @CheeseEntity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${removePropertyMessage('Cheese', @CheeseEntity)}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "Cheese"
}
]
}
],
"$Generator": "99e1c747b1c2809f9bf3ecbce8e67852"
}

Просмотреть файл

@ -1,13 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ShowCheese",
"property": "Cheese",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${showPropertyMessage(@PROPERTYName)}"
}
],
"$Generator": "cb66b7e2b943c246d63666eaceb7fbf7"
}

Просмотреть файл

@ -1,15 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnChooseEntity",
"entity": "CheeseEntity",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${chooseCheeseEntity()}",
"expectedProperties": [
"Cheese"
]
}
],
"$Generator": "5181ec23c0d2f4c1238b4bf60a7cef25"
}

Просмотреть файл

@ -1,18 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "AddToLength",
"entity": "dimension",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${setObjectPropertyMessage('Length', @dimension)}"
},
{
"$kind": "Microsoft.SetProperty",
"property": "$Length",
"value": "=@dimension"
}
],
"$Generator": "07538ad46e82b25a8a7463bbdaf8ff9d"
}

Просмотреть файл

@ -1,17 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ClearLength",
"property": "Length",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${clearPropertyMessage('Length')}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "$Length"
}
],
"$Generator": "122e205ce20d3bf7528fb619b8bfeb08"
}

Просмотреть файл

@ -1,16 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnEndOfActions",
"condition": "!$Length || $PropertyToChange == 'Length'",
"priority": "=indexOf(dialog.requiredProperties, 'Length')",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${AskLength()}",
"expectedProperties": [
"Length"
]
}
],
"$Generator": "b192167d51eed43fb0123386f7c6dc23"
}

Просмотреть файл

@ -1,23 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "RemoveFromLength",
"entity": "dimension",
"actions": [
{
"$kind": "Microsoft.IfCondition",
"condition": "$Length == @dimension",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${removePropertyMessage('Length', @dimension)}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "Length"
}
]
}
],
"$Generator": "eae7223ba48af33221eee2057d1465ff"
}

Просмотреть файл

@ -1,13 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ShowLength",
"property": "Length",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${showPropertyMessage(@PROPERTYName)}"
}
],
"$Generator": "ff86833af0f00a97e2df71b5e2c9b517"
}

Просмотреть файл

@ -1,28 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "AddToMeat",
"entity": "MeatEntity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${setPropertyMessage('Meat', @MeatEntity)}"
},
{
"$kind": "Microsoft.SetProperty",
"property": "$Meat",
"value": "=@MeatEntity"
},
{
"$kind": "Microsoft.IfCondition",
"condition": "$PropertyToChange == 'Meat'",
"actions": [
{
"$kind": "Microsoft.DeleteProperty",
"property": "$PropertyToChange"
}
]
}
],
"$Generator": "fe27003546fb54ffe8f301fd4b3dc6d1"
}

Просмотреть файл

@ -1,17 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ClearMeat",
"property": "Meat",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${clearPropertyMessage('Meat')}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "$Meat"
}
],
"$Generator": "a5048634148bdb0d9a6d33ec6fcbdc7c"
}

Просмотреть файл

@ -1,16 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnEndOfActions",
"condition": "!$Meat || $PropertyToChange == 'Meat'",
"priority": "=indexOf(dialog.requiredProperties, 'Meat')",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${AskMeat()}",
"expectedProperties": [
"Meat"
]
}
],
"$Generator": "b737ba289bb62e619d2d7907b5ad4173"
}

Просмотреть файл

@ -1,23 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "RemoveFromMeat",
"entity": "MeatEntity",
"actions": [
{
"$kind": "Microsoft.IfCondition",
"condition": "$Meat == @MeatEntity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${removePropertyMessage('Meat', @MeatEntity)}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "Meat"
}
]
}
],
"$Generator": "ab6b6ce4a754bf483d7f7ace7d15a448"
}

Просмотреть файл

@ -1,13 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ShowMeat",
"property": "Meat",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${showPropertyMessage(@PROPERTYName)}"
}
],
"$Generator": "b75c157ab7a3734d4c2d4b663dca5d70"
}

Просмотреть файл

@ -1,15 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnChooseEntity",
"entity": "MeatEntity",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${chooseMeatEntity()}",
"expectedProperties": [
"Meat"
]
}
],
"$Generator": "b4964b3fcc513688ce4e48d8aaf325ff"
}

Просмотреть файл

@ -1,28 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "AddToName",
"entity": "personName",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${setPropertyMessage('Name', @personName)}"
},
{
"$kind": "Microsoft.SetProperty",
"property": "$Name",
"value": "=@personName"
},
{
"$kind": "Microsoft.IfCondition",
"condition": "$PropertyToChange == 'Name'",
"actions": [
{
"$kind": "Microsoft.DeleteProperty",
"property": "$PropertyToChange"
}
]
}
],
"$Generator": "858e82e08a578dd0a532c729136aa2b1"
}

Просмотреть файл

@ -1,28 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "AddToName",
"entity": "utterance",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${setPropertyMessage('Name', @utterance)}"
},
{
"$kind": "Microsoft.SetProperty",
"property": "$Name",
"value": "=@utterance"
},
{
"$kind": "Microsoft.IfCondition",
"condition": "$PropertyToChange == 'Name'",
"actions": [
{
"$kind": "Microsoft.DeleteProperty",
"property": "$PropertyToChange"
}
]
}
],
"$Generator": "8ac78949b9f12bc34f0b66dc61dc28b1"
}

Просмотреть файл

@ -1,17 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ClearName",
"property": "Name",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${clearPropertyMessage('Name')}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "$Name"
}
],
"$Generator": "59849ebb26f8f1e6fae50f34202a1845"
}

Просмотреть файл

@ -1,16 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnEndOfActions",
"condition": "!$Name || $PropertyToChange == 'Name'",
"priority": "=indexOf(dialog.requiredProperties, 'Name')",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${AskName()}",
"expectedProperties": [
"Name"
]
}
],
"$Generator": "5bb345e7a782f6f81da643f0560f6491"
}

Просмотреть файл

@ -1,23 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "RemoveFromName",
"entity": "personName",
"actions": [
{
"$kind": "Microsoft.IfCondition",
"condition": "$Name == @personName",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${removePropertyMessage('Name', @personName)}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "Name"
}
]
}
],
"$Generator": "6f34abf3a44f2d6bedccf0bcb7802d3d"
}

Просмотреть файл

@ -1,13 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ShowName",
"property": "Name",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${showPropertyMessage(@PROPERTYName)}"
}
],
"$Generator": "9bdcb3d25dec8f55bd38964f8f48aabb"
}

Просмотреть файл

@ -1,18 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "AddToPrice",
"entity": "money",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${setObjectPropertyMessage('Price', @money)}"
},
{
"$kind": "Microsoft.SetProperty",
"property": "$Price",
"value": "=@money"
}
],
"$Generator": "18134b3b3a303c362ccddbeef7e67565"
}

Просмотреть файл

@ -1,17 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ClearPrice",
"property": "Price",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${clearPropertyMessage('Price')}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "$Price"
}
],
"$Generator": "8a8ad9ace17d7b1f01315a1974ea85b5"
}

Просмотреть файл

@ -1,16 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnEndOfActions",
"condition": "!$Price || $PropertyToChange == 'Price'",
"priority": "=indexOf(dialog.requiredProperties, 'Price')",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${AskPrice()}",
"expectedProperties": [
"Price"
]
}
],
"$Generator": "d73a6841fb192191c9bf1653a7830be2"
}

Просмотреть файл

@ -1,23 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "RemoveFromPrice",
"entity": "money",
"actions": [
{
"$kind": "Microsoft.IfCondition",
"condition": "$Price == @money",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${removePropertyMessage('Price', @money)}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "Price"
}
]
}
],
"$Generator": "cbc8a9d9e8e38cf0cdceed2ec438d160"
}

Просмотреть файл

@ -1,13 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ShowPrice",
"property": "Price",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${showPropertyMessage(@PROPERTYName)}"
}
],
"$Generator": "ce7c1874d2627e41a43d78e94dab0b4d"
}

Просмотреть файл

@ -1,30 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "AddToQuantity",
"entity": "number",
"actions": [
{
"$kind": "Microsoft.IfCondition",
"condition": "@number < dialogClass.schema.properties['Quantity'].minimum || @number > dialogClass.schema.properties['Quantity'].maximum",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${numberValidation('Quantity', @number)}"
}
],
"elseActions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${setPropertyMessage('Quantity', @number)}"
},
{
"$kind": "Microsoft.SetProperty",
"property": "$Quantity",
"value": "=@number"
}
]
}
],
"$Generator": "5f343f2b1e30e4513c4aeac1ed77adaf"
}

Просмотреть файл

@ -1,17 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ClearQuantity",
"property": "Quantity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${clearPropertyMessage('Quantity')}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "$Quantity"
}
],
"$Generator": "be75fdbc2c8232276bded65ea7eeacea"
}

Просмотреть файл

@ -1,16 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnEndOfActions",
"condition": "!$Quantity || $PropertyToChange == 'Quantity'",
"priority": "=indexOf(dialog.requiredProperties, 'Quantity')",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${AskQuantity()}",
"expectedProperties": [
"Quantity"
]
}
],
"$Generator": "2242219a015d9ee97ad127b427eb4282"
}

Просмотреть файл

@ -1,23 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "RemoveFromQuantity",
"entity": "number",
"actions": [
{
"$kind": "Microsoft.IfCondition",
"condition": "$Quantity == @number",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${removePropertyMessage('Quantity', @number)}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "Quantity"
}
]
}
],
"$Generator": "e565a8300f56eaa149ea37fae2d06220"
}

Просмотреть файл

@ -1,13 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ShowQuantity",
"property": "Quantity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${showPropertyMessage(@PROPERTYName)}"
}
],
"$Generator": "9a5ad48f1e236cfc95d37abcc8ff0410"
}

Просмотреть файл

@ -1,29 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "AddToSauces",
"entity": "SaucesEntity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${setArrayPropertyMessage('Sauces', @SaucesEntity)}"
},
{
"$kind": "Microsoft.EditArray",
"changeType": "push",
"itemsProperty": "$Sauces",
"value": "=@SaucesEntity"
},
{
"$kind": "Microsoft.IfCondition",
"condition": "$PropertyToChange == 'Sauces'",
"actions": [
{
"$kind": "Microsoft.DeleteProperty",
"property": "$PropertyToChange"
}
]
}
],
"$Generator": "eff2796dcbbc7c620dc7fc6e2cc43f60"
}

Просмотреть файл

@ -1,17 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ClearSauces",
"property": "Sauces",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${clearPropertyMessage('Sauces')}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "$Sauces"
}
],
"$Generator": "8a83854a935ab214813c40f019b6367e"
}

Просмотреть файл

@ -1,16 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnEndOfActions",
"condition": "!$Sauces || $PropertyToChange == 'Sauces'",
"priority": "=indexOf(dialog.requiredProperties, 'Sauces')",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${AskSauces()}",
"expectedProperties": [
"Sauces"
]
}
],
"$Generator": "0576f950dfe24fbddb19a4431f9abfef"
}

Просмотреть файл

@ -1,19 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "RemoveFromSauces",
"entity": "SaucesEntity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${removeArrayPropertyMessage('Sauces', @SaucesEntity)}"
},
{
"$kind": "Microsoft.EditArray",
"changeType": "remove",
"itemsProperty": "$Sauces",
"value": "=@SaucesEntity"
}
],
"$Generator": "4d56974ed3e7bc520fdfeb30d5bcacc5"
}

Просмотреть файл

@ -1,13 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ShowSauces",
"property": "Sauces",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${showPropertyMessage(@PROPERTYName)}"
}
],
"$Generator": "2881d6895e98840f6fd56d901b62ecf5"
}

Просмотреть файл

@ -1,15 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnChooseEntity",
"entity": "SaucesEntity",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${chooseSaucesEntity()}",
"expectedProperties": [
"Sauces"
]
}
],
"$Generator": "06b6ef6c2be6def76091b7b8e00114d8"
}

Просмотреть файл

@ -1,29 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "AddToToppings",
"entity": "ToppingsEntity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${setArrayPropertyMessage('Toppings', @ToppingsEntity)}"
},
{
"$kind": "Microsoft.EditArray",
"changeType": "push",
"itemsProperty": "$Toppings",
"value": "=@ToppingsEntity"
},
{
"$kind": "Microsoft.IfCondition",
"condition": "$PropertyToChange == 'Toppings'",
"actions": [
{
"$kind": "Microsoft.DeleteProperty",
"property": "$PropertyToChange"
}
]
}
],
"$Generator": "b34b9ca46a6599bc25a401adba437f77"
}

Просмотреть файл

@ -1,17 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ClearToppings",
"property": "Toppings",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${clearPropertyMessage('Toppings')}"
},
{
"$kind": "Microsoft.DeleteProperty",
"property": "$Toppings"
}
],
"$Generator": "468b63f51802452c7aa36c42d430bb2e"
}

Просмотреть файл

@ -1,16 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnEndOfActions",
"condition": "!$Toppings || $PropertyToChange == 'Toppings'",
"priority": "=indexOf(dialog.requiredProperties, 'Toppings')",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${AskToppings()}",
"expectedProperties": [
"Toppings"
]
}
],
"$Generator": "1602a1058e95f76ec0ff04606f5cc9df"
}

Просмотреть файл

@ -1,19 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "RemoveFromToppings",
"entity": "ToppingsEntity",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${removeArrayPropertyMessage('Toppings', @ToppingsEntity)}"
},
{
"$kind": "Microsoft.EditArray",
"changeType": "remove",
"itemsProperty": "$Toppings",
"value": "=@ToppingsEntity"
}
],
"$Generator": "b43a6132c852cc1ba0f812e998ef491b"
}

Просмотреть файл

@ -1,13 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnAssignEntity",
"operation": "ShowToppings",
"property": "Toppings",
"actions": [
{
"$kind": "Microsoft.SendActivity",
"activity": "${showPropertyMessage(@PROPERTYName)}"
}
],
"$Generator": "e1f828c04792771dd3a2f8fc07c940c1"
}

Просмотреть файл

@ -1,15 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-samples/master/experimental/generation/runbot/runbot.schema",
"$kind": "Microsoft.OnChooseEntity",
"entity": "ToppingsEntity",
"actions": [
{
"$kind": "Microsoft.Ask",
"activity": "${chooseToppingsEntity()}",
"expectedProperties": [
"Toppings"
]
}
],
"$Generator": "dbd03b023817dcec3507e54725e2bd1b"
}

Просмотреть файл

@ -1,5 +1,6 @@
#!/bin/sh
region=$1
thisdir="$(dirname $0)"
if [ -z "$region" ]; then
region="westus"
fi
@ -8,14 +9,13 @@ key=$2
if [ -n "$key" ]; then
key="--authoringKey $key"
fi
bf luis:build --luConfig luconfig.json --region=$region $key
bf luis:build --luConfig $thisdir/luconfig.json --region=$region $key --out $thisdir/generated --log
res=$?
if [ $res != 0 ]; then
echo build [region] [authoringKey]
echo Region defaults to westus.
echo Must have an explicit key or set it using "bf config:set:luis --authoringKey <LUISKEY>"
echo "build [region] [LUISAuthoringKey]"
echo "Region defaults to westus."
echo "Set LUISAuthoringKey default with bf config:set:luis --authoringKey=<yourKey>"
fi
exit $res

Просмотреть файл

@ -7,14 +7,15 @@ if "%region%" EQU "" set region=westus
set key=%2
if "%key%" NEQ "" set key=--authoringKey %key%
echo Building LUIS models
call bf luis:build --luConfig luconfig.json --region=%region% %key%
if %errorlevel% EQU 0 goto done
echo Building Models
call bf luis:build --luConfig luconfig.json --region=%region% %key% --out generated --log
goto done
:help
echo build.cmd [region] [authoringKey]
echo build.cmd [region] [LUISAuthoringKey]
echo Region defaults to westus.
echo Must have an explicit key or set it using "bf config:set:luis --authoringKey <LUISKEY>"
echo Set LUISAuthoringKey default with bf config:set:luis --authoringKey=<yourKey>
:done

Просмотреть файл

@ -1 +0,0 @@
{"query":"$3.25","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9959002}},"entities":{"money":[{"number":3.25,"units":"Dollar"}],"number":[3.25],"$instance":{"money":[{"type":"builtin.currency","text":"$3.25","startIndex":0,"length":5,"modelTypeId":2,"modelType":"Prebuilt Entity Extractor","recognitionSources":["model"]}],"number":[{"type":"builtin.number","text":"3.25","startIndex":1,"length":4,"modelTypeId":2,"modelType":"Prebuilt Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"tomatos","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9770272}},"entities":{"personName":["tomatos"],"$instance":{"personName":[{"type":"builtin.personName","text":"tomatos","startIndex":0,"length":7,"modelTypeId":2,"modelType":"Prebuilt Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"remove name","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9998846}},"entities":{"ClearName":[{"PROPERTYName":[["Name"]],"$instance":{"PROPERTYName":[{"type":"PROPERTYName","text":"name","startIndex":7,"length":4,"score":0.966040254,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}]}}],"$instance":{"ClearName":[{"type":"ClearName","text":"remove name","startIndex":0,"length":11,"score":0.945912838,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"remove bread","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.999815}},"entities":{"ClearBread":[{"PROPERTYName":[["Bread"]],"$instance":{"PROPERTYName":[{"type":"PROPERTYName","text":"bread","startIndex":7,"length":5,"score":0.9622736,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}]}}],"$instance":{"ClearBread":[{"type":"ClearBread","text":"remove bread","startIndex":0,"length":12,"score":0.944366157,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"lettuce and pickles","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.997404635}},"entities":{"ToppingsEntity":[["lettuce"],["pickles"]],"$instance":{"ToppingsEntity":[{"type":"ToppingsEntity","text":"lettuce","startIndex":0,"length":7,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]},{"type":"ToppingsEntity","text":"pickles","startIndex":12,"length":7,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"no whole wheat","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9981792}},"entities":{"RemoveFromBread":[{"BreadEntity":[["wholeWheat"]],"$instance":{"BreadEntity":[{"type":"BreadEntity","text":"whole wheat","startIndex":3,"length":11,"score":0.6396345,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}]}}],"boolean":[["false"]],"BreadEntity":[["multiGrainWheat","wholeWheat"]],"$instance":{"RemoveFromBread":[{"type":"RemoveFromBread","text":"no whole wheat","startIndex":0,"length":14,"score":0.593900561,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}],"boolean":[{"type":"boolean","text":"no","startIndex":0,"length":2,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}],"BreadEntity":[{"type":"BreadEntity","text":"wheat","startIndex":9,"length":5,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"tomato","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.988971}},"entities":{"personName":["tomato"],"ToppingsEntity":[["tomato"]],"$instance":{"personName":[{"type":"builtin.personName","text":"tomato","startIndex":0,"length":6,"modelTypeId":2,"modelType":"Prebuilt Entity Extractor","recognitionSources":["model"]}],"ToppingsEntity":[{"type":"ToppingsEntity","text":"tomato","startIndex":0,"length":6,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"cheese and roast beef","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9996584}},"entities":{"PROPERTYName":[["Cheese"]],"MeatEntity":[["roast beef"],["roast beef"]],"$instance":{"PROPERTYName":[{"type":"PROPERTYName","text":"cheese","startIndex":0,"length":6,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}],"MeatEntity":[{"type":"MeatEntity","text":"roast beef","startIndex":11,"length":10,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]},{"type":"MeatEntity","text":"beef","startIndex":17,"length":4,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"chris","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9770272}},"entities":{"personName":["chris"],"$instance":{"personName":[{"type":"builtin.personName","text":"chris","startIndex":0,"length":5,"modelTypeId":2,"modelType":"Prebuilt Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"ham","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9898129}},"entities":{"personName":["ham"],"MeatEntity":[["ham"]],"$instance":{"personName":[{"type":"builtin.personName","text":"ham","startIndex":0,"length":3,"modelTypeId":2,"modelType":"Prebuilt Entity Extractor","recognitionSources":["model"]}],"MeatEntity":[{"type":"MeatEntity","text":"ham","startIndex":0,"length":3,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"sure","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9770272}},"entities":{"boolean":[["true"]],"$instance":{"boolean":[{"type":"boolean","text":"sure","startIndex":0,"length":4,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"multi grain","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.996665537}},"entities":{"BreadEntity":[["multiGrainWheat"],["multiGrainWheat"]],"$instance":{"BreadEntity":[{"type":"BreadEntity","text":"multi grain","startIndex":0,"length":11,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]},{"type":"BreadEntity","text":"grain","startIndex":6,"length":5,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"bob","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9770272}},"entities":{"personName":["bob"],"$instance":{"personName":[{"type":"builtin.personName","text":"bob","startIndex":0,"length":3,"modelTypeId":2,"modelType":"Prebuilt Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"wheat","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9949749}},"entities":{"BreadEntity":[["multiGrainWheat","wholeWheat"]],"$instance":{"BreadEntity":[{"type":"BreadEntity","text":"wheat","startIndex":0,"length":5,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"yellow mustard","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9968699}},"entities":{"SaucesEntity":[["yellowMustard"],["yellowMustard","dijonMustard"]],"$instance":{"SaucesEntity":[{"type":"SaucesEntity","text":"yellow mustard","startIndex":0,"length":14,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]},{"type":"SaucesEntity","text":"mustard","startIndex":7,"length":7,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"meat","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.9989701}},"entities":{"PROPERTYName":[["Meat"]],"$instance":{"PROPERTYName":[{"type":"PROPERTYName","text":"meat","startIndex":0,"length":4,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"swiss","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.990285456}},"entities":{"personName":["swiss"],"CheeseEntity":[["swiss"]],"$instance":{"personName":[{"type":"builtin.personName","text":"swiss","startIndex":0,"length":5,"modelTypeId":2,"modelType":"Prebuilt Entity Extractor","recognitionSources":["model"]}],"CheeseEntity":[{"type":"CheeseEntity","text":"swiss","startIndex":0,"length":5,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Просмотреть файл

@ -1 +0,0 @@
{"query":"wheat ham and swiss","prediction":{"topIntent":"sandwich","intents":{"sandwich":{"score":0.998998165}},"entities":{"BreadEntity":[["multiGrainWheat","wholeWheat"]],"MeatEntity":[["ham"]],"CheeseEntity":[["swiss"]],"$instance":{"BreadEntity":[{"type":"BreadEntity","text":"wheat","startIndex":0,"length":5,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}],"MeatEntity":[{"type":"MeatEntity","text":"ham","startIndex":6,"length":3,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}],"CheeseEntity":[{"type":"CheeseEntity","text":"swiss","startIndex":14,"length":5,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше