Warnings fix group 16.
This commit is contained in:
Коммит
72eb746bb6
|
@ -55,12 +55,12 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
{
|
||||
get
|
||||
{
|
||||
return InputBindings.TryGetValue(DialogContextState.DialogNames, out string value) ? value : null;
|
||||
return InputBindings.TryGetValue(DialogContextState.DIALOG_VALUE, out string value) ? value : null;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
InputBindings[DialogContextState.DialogNames] = value;
|
||||
InputBindings[DialogContextState.DIALOG_VALUE] = value;
|
||||
OutputBinding = value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
|
||||
// In-memory property that will contain the current items value. Defaults to `dialog.value`.
|
||||
[JsonProperty("valueProperty")]
|
||||
public string ValueProperty { get; set; } = DialogContextState.DialogNames;
|
||||
public string ValueProperty { get; set; } = DialogContextState.DIALOG_VALUE;
|
||||
|
||||
// Actions to be run for each of items.
|
||||
[JsonProperty("actions")]
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
|
||||
// In-memory property that will contain the current items value. Defaults to `dialog.value`.
|
||||
[JsonProperty("valueProperty")]
|
||||
public string ValueProperty { get; set; } = DialogContextState.DialogNames;
|
||||
public string ValueProperty { get; set; } = DialogContextState.DIALOG_VALUE;
|
||||
|
||||
// Actions to be run for each of items.
|
||||
[JsonProperty("actions")]
|
||||
|
|
|
@ -2,12 +2,17 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Cache;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.TraceExtensions;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
@ -16,18 +21,17 @@ using Newtonsoft.Json.Linq;
|
|||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Action for HttpRequests.
|
||||
/// Action for performing an HttpRequest.
|
||||
/// </summary>
|
||||
public class HttpRequest : DialogAction
|
||||
{
|
||||
private static readonly HttpClient Client = new HttpClient();
|
||||
|
||||
public HttpRequest(HttpMethod method, string url, string property, Dictionary<string, string> headers = null, JObject body = null, [CallerFilePath] string callerPath = "", [CallerLineNumber] int callerLine = 0)
|
||||
public HttpRequest(HttpMethod method, string url, string inputProperty, Dictionary<string, string> headers = null, JObject body = null, [CallerFilePath] string callerPath = "", [CallerLineNumber] int callerLine = 0)
|
||||
{
|
||||
this.RegisterSourceLocation(callerPath, callerLine);
|
||||
this.Method = method;
|
||||
this.Url = url ?? throw new ArgumentNullException(nameof(url));
|
||||
this.Property = property;
|
||||
this.Headers = headers;
|
||||
this.Body = body;
|
||||
}
|
||||
|
@ -111,10 +115,15 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
public ResponseTypes ResponseType { get; set; } = ResponseTypes.Json;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets bidirectional property for input and output. Example: user.age will be passed in, and user.age will be set when the dialog completes.
|
||||
/// Gets or sets the property to store the HTTP response in.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The result will have 4 properties from the http response:
|
||||
/// [statusCode|reasonPhrase|content|headers]
|
||||
/// If the content is json it will be an deserialized object, otherwise it will be a string.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// Property for input and output.
|
||||
/// Property from the HTTP response.
|
||||
/// </value>
|
||||
public string Property
|
||||
{
|
||||
|
@ -125,7 +134,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
|
||||
set
|
||||
{
|
||||
InputBindings[DialogContextState.DialogNames] = value;
|
||||
OutputBinding = value;
|
||||
}
|
||||
}
|
||||
|
@ -173,6 +181,12 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
}
|
||||
}
|
||||
|
||||
dynamic traceInfo = new JObject();
|
||||
|
||||
traceInfo.request = new JObject();
|
||||
traceInfo.request.method = this.Method.ToString();
|
||||
traceInfo.request.url = instanceUrl;
|
||||
|
||||
HttpResponseMessage response = null;
|
||||
|
||||
switch (this.Method)
|
||||
|
@ -184,7 +198,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
}
|
||||
else
|
||||
{
|
||||
response = await Client.PostAsync(instanceUrl, new StringContent(instanceBody.ToString(), Encoding.UTF8, "application/json"));
|
||||
var postContent = new StringContent(instanceBody.ToString(), Encoding.UTF8, "application/json");
|
||||
traceInfo.request.content = instanceBody.ToString();
|
||||
traceInfo.request.headers = JObject.FromObject(postContent?.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
|
||||
response = await Client.PostAsync(instanceUrl, postContent);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -199,6 +216,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
{
|
||||
var request = new HttpRequestMessage(new System.Net.Http.HttpMethod("PATCH"), instanceUrl);
|
||||
request.Content = new StringContent(instanceBody.ToString(), Encoding.UTF8, "application/json");
|
||||
traceInfo.request.content = instanceBody.ToString();
|
||||
traceInfo.request.headers = JObject.FromObject(request.Content.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
|
||||
response = await Client.SendAsync(request);
|
||||
}
|
||||
|
||||
|
@ -211,7 +230,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
}
|
||||
else
|
||||
{
|
||||
response = await Client.PutAsync(instanceUrl, new StringContent(instanceBody.ToString(), Encoding.UTF8, "application/json"));
|
||||
var putContent = new StringContent(instanceBody.ToString(), Encoding.UTF8, "application/json");
|
||||
traceInfo.request.content = instanceBody.ToString();
|
||||
traceInfo.request.headers = JObject.FromObject(putContent.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
|
||||
response = await Client.PutAsync(instanceUrl, putContent);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -225,37 +247,54 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
break;
|
||||
}
|
||||
|
||||
object result = (object)await response.Content.ReadAsStringAsync();
|
||||
Result requestResult = new Result(response.Headers)
|
||||
{
|
||||
StatusCode = (int)response.StatusCode,
|
||||
ReasonPhrase = response.ReasonPhrase,
|
||||
};
|
||||
|
||||
object content = (object)await response.Content.ReadAsStringAsync();
|
||||
|
||||
switch (this.ResponseType)
|
||||
{
|
||||
case ResponseTypes.Activity:
|
||||
var activity = JsonConvert.DeserializeObject<Activity>((string)result);
|
||||
var activity = JsonConvert.DeserializeObject<Activity>((string)content);
|
||||
requestResult.Content = JObject.FromObject(activity);
|
||||
await dc.Context.SendActivityAsync(activity, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
return await dc.EndDialogAsync(cancellationToken: cancellationToken);
|
||||
break;
|
||||
|
||||
case ResponseTypes.Activities:
|
||||
var activities = JsonConvert.DeserializeObject<Activity[]>((string)result);
|
||||
var activities = JsonConvert.DeserializeObject<Activity[]>((string)content);
|
||||
requestResult.Content = JObject.FromObject(activities);
|
||||
await dc.Context.SendActivitiesAsync(activities, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
return await dc.EndDialogAsync(cancellationToken: cancellationToken);
|
||||
break;
|
||||
|
||||
case ResponseTypes.Json:
|
||||
// Try set with JOjbect for further retreiving
|
||||
try
|
||||
{
|
||||
result = JToken.Parse((string)result);
|
||||
content = JToken.Parse((string)content);
|
||||
}
|
||||
catch
|
||||
{
|
||||
result = result.ToString();
|
||||
content = content.ToString();
|
||||
}
|
||||
|
||||
return await dc.EndDialogAsync(result, cancellationToken: cancellationToken);
|
||||
requestResult.Content = content;
|
||||
break;
|
||||
|
||||
case ResponseTypes.None:
|
||||
default:
|
||||
return await dc.EndDialogAsync(cancellationToken: cancellationToken);
|
||||
break;
|
||||
}
|
||||
|
||||
traceInfo.response = JObject.FromObject(requestResult);
|
||||
|
||||
// Write Trace Activity for the http request and response values
|
||||
await dc.Context.TraceActivityAsync("HttpRequest", (object)traceInfo, valueType: "Microsoft.HttpRequest", label: this.Id).ConfigureAwait(false);
|
||||
|
||||
// return the actionResult as the result of this operation
|
||||
return await dc.EndDialogAsync(result: requestResult, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
private async Task ReplaceJTokenRecursively(DialogContext dc, JToken token)
|
||||
|
@ -301,5 +340,48 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Result data of the the http operation.
|
||||
/// </summary>
|
||||
public class Result
|
||||
{
|
||||
public Result()
|
||||
{
|
||||
}
|
||||
|
||||
public Result(HttpHeaders headers)
|
||||
{
|
||||
this.Headers = headers.ToDictionary(t => t.Key, t => t.Value.First());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status code from the response to the http operation.
|
||||
/// </summary>
|
||||
/// <value>Response status code.</value>
|
||||
[JsonProperty("statusCode")]
|
||||
public int StatusCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the reason phrase from the response to the http operation.
|
||||
/// </summary>
|
||||
/// <value>Response reason phrase.</value>
|
||||
[JsonProperty("reasonPhrase")]
|
||||
public string ReasonPhrase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the headers from the response to the http operation.
|
||||
/// </summary>
|
||||
/// <value>Response headers.</value>
|
||||
[JsonProperty("headers")]
|
||||
public Dictionary<string, string> Headers { get; } = new Dictionary<string, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content body from the response to the http operation.
|
||||
/// </summary>
|
||||
/// <value>Response content body.</value>
|
||||
[JsonProperty("content")]
|
||||
public object Content { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
|||
|
||||
set
|
||||
{
|
||||
InputBindings[DialogContextState.DialogNames] = value;
|
||||
InputBindings[DialogContextState.DIALOG_VALUE] = value;
|
||||
OutputBinding = value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ using System.Threading.Tasks;
|
|||
using Microsoft.Bot.Builder.Dialogs.Adaptive.Events;
|
||||
using Microsoft.Bot.Builder.Dialogs.Adaptive.Selectors;
|
||||
using Microsoft.Bot.Builder.Dialogs.Debugging;
|
||||
using Microsoft.Bot.Builder.Expressions;
|
||||
using Microsoft.Bot.Builder.Expressions.Parser;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using static Microsoft.Bot.Builder.Dialogs.Debugging.DebugSupport;
|
||||
|
@ -22,7 +24,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
|||
/// </summary>
|
||||
public class AdaptiveDialog : DialogContainer
|
||||
{
|
||||
private const string AdaptiveKey = "adaptiveDialogState";
|
||||
#pragma warning disable SA1310 // Field should not contain underscore.
|
||||
private const string ADAPTIVE_KEY = "adaptiveDialogState";
|
||||
#pragma warning restore SA1310 // Field should not contain underscore.
|
||||
|
||||
private readonly string changeKey = Guid.NewGuid().ToString();
|
||||
|
||||
|
@ -63,14 +67,14 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
|||
public virtual List<IOnEvent> Events { get; set; } = new List<IOnEvent>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether gets or sets the policty to Automatically end the dialog when there are no actions to execute.
|
||||
/// Gets or sets a value indicating whether to end the dialog when there are no actions to execute.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If true, when there are no actions to execute the current dialog will end
|
||||
/// If false, when there are no actions to execute the current dialog will simply end the turn and still be active.
|
||||
/// If true, when there are no actions to execute, the current dialog will end
|
||||
/// If false, when there are no actions to execute, the current dialog will simply end the turn and still be active.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// The policty to Automatically end the dialog when there are no actions to execute.
|
||||
/// Whether to end the dialog when there are no actions to execute.
|
||||
/// </value>
|
||||
public bool AutoEndDialog { get; set; } = true;
|
||||
|
||||
|
@ -115,8 +119,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
|||
EnsureDependenciesInstalled();
|
||||
|
||||
var activeDialogState = dc.ActiveDialog.State as Dictionary<string, object>;
|
||||
activeDialogState[AdaptiveKey] = new AdaptiveDialogState();
|
||||
var state = activeDialogState[AdaptiveKey] as AdaptiveDialogState;
|
||||
activeDialogState[ADAPTIVE_KEY] = new AdaptiveDialogState();
|
||||
var state = activeDialogState[ADAPTIVE_KEY] as AdaptiveDialogState;
|
||||
|
||||
// Persist options to dialog state
|
||||
state.Options = options ?? new Dictionary<string, object>();
|
||||
|
@ -169,7 +173,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
|||
public override async Task RepromptDialogAsync(ITurnContext turnContext, DialogInstance instance, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
// Forward to current sequence step
|
||||
var state = (instance.State as Dictionary<string, object>)[AdaptiveKey] as AdaptiveDialogState;
|
||||
var state = (instance.State as Dictionary<string, object>)[ADAPTIVE_KEY] as AdaptiveDialogState;
|
||||
|
||||
if (state.Actions.Any())
|
||||
{
|
||||
|
@ -205,12 +209,12 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
|||
public override DialogContext CreateChildContext(DialogContext dc)
|
||||
{
|
||||
var activeDialogState = dc.ActiveDialog.State as Dictionary<string, object>;
|
||||
var state = activeDialogState[AdaptiveKey] as AdaptiveDialogState;
|
||||
var state = activeDialogState[ADAPTIVE_KEY] as AdaptiveDialogState;
|
||||
|
||||
if (state == null)
|
||||
{
|
||||
state = new AdaptiveDialogState();
|
||||
activeDialogState[AdaptiveKey] = state;
|
||||
activeDialogState[ADAPTIVE_KEY] = state;
|
||||
}
|
||||
|
||||
if (state.Actions != null && state.Actions.Any())
|
||||
|
@ -242,7 +246,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
|||
protected async Task<bool> ProcessEventAsync(SequenceContext sequenceContext, DialogEvent dialogEvent, bool preBubble, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
// Save into turn
|
||||
sequenceContext.State.SetValue(DialogContextState.TurnDialogEvent, dialogEvent);
|
||||
sequenceContext.State.SetValue(DialogContextState.TURN_DIALOGEVENT, dialogEvent);
|
||||
|
||||
// Look for triggered evt
|
||||
var handled = await this.QueueFirstMatchAsync(sequenceContext, dialogEvent, preBubble, cancellationToken).ConfigureAwait(false);
|
||||
|
@ -272,11 +276,11 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
|||
// Recognize utterance
|
||||
var recognized = await this.OnRecognize(sequenceContext, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
sequenceContext.State.SetValue(DialogContextState.TurnRecognized, recognized);
|
||||
sequenceContext.State.SetValue(DialogContextState.TURN_RECOGNIZED, recognized);
|
||||
|
||||
var (name, score) = recognized.GetTopScoringIntent();
|
||||
sequenceContext.State.SetValue(DialogContextState.TurnTopIntent, name);
|
||||
sequenceContext.State.SetValue(DialogContextState.TurnTopScore, score);
|
||||
sequenceContext.State.SetValue(DialogContextState.TURN_TOPINTENT, name);
|
||||
sequenceContext.State.SetValue(DialogContextState.TURN_TOPSCORE, score);
|
||||
|
||||
if (this.Recognizer != null)
|
||||
{
|
||||
|
@ -380,8 +384,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
|||
// Increment turns step count
|
||||
// This helps dialogs being resumed from an interruption to determine if they
|
||||
// should re-prompt or not.
|
||||
var stepCount = sequenceContext.State.GetValue<int>(DialogContextState.TurnStepCount, 0);
|
||||
sequenceContext.State.SetValue(DialogContextState.TurnStepCount, stepCount + 1);
|
||||
var stepCount = sequenceContext.State.GetValue<int>(DialogContextState.TURN_STEPCOUNT, 0);
|
||||
sequenceContext.State.SetValue(DialogContextState.TURN_STEPCOUNT, stepCount + 1);
|
||||
|
||||
// Is the step waiting for input or were we cancelled?
|
||||
if (result.Status == DialogTurnStatus.Waiting || this.GetUniqueInstanceId(sequenceContext) != instanceId)
|
||||
|
@ -448,10 +452,53 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
|||
protected async Task<RecognizerResult> OnRecognize(SequenceContext sequenceContext, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var context = sequenceContext.Context;
|
||||
var noneIntent = new RecognizerResult()
|
||||
{
|
||||
Text = context.Activity.Text ?? string.Empty,
|
||||
Intents = new Dictionary<string, IntentScore>()
|
||||
{
|
||||
{ "None", new IntentScore() { Score = 0.0 } }
|
||||
},
|
||||
Entities = JObject.Parse("{}")
|
||||
};
|
||||
var text = context.Activity.Text;
|
||||
if (context.Activity.Value != null)
|
||||
{
|
||||
var value = JObject.FromObject(context.Activity.Value);
|
||||
|
||||
// Check for submission of an adaptive card
|
||||
if (string.IsNullOrEmpty(text) && value.Property("intent") != null)
|
||||
{
|
||||
// Map submitted values to a recognizer result
|
||||
var recognized = new RecognizerResult() { Text = string.Empty };
|
||||
|
||||
foreach (var property in value.Properties())
|
||||
{
|
||||
if (property.Name.ToLower() == "intent")
|
||||
{
|
||||
recognized.Intents[property.Value.ToString()] = new IntentScore() { Score = 1.0 };
|
||||
}
|
||||
else
|
||||
{
|
||||
if (recognized.Entities.Property(property.Name) == null)
|
||||
{
|
||||
recognized.Entities[property.Name] = new JArray(property.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
((JArray)recognized.Entities[property.Name]).Add(property.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return recognized;
|
||||
}
|
||||
}
|
||||
|
||||
if (Recognizer != null)
|
||||
{
|
||||
var result = await Recognizer.RecognizeAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
||||
// only allow one intent
|
||||
var topIntent = result.GetTopScoringIntent();
|
||||
result.Intents.Clear();
|
||||
|
@ -460,15 +507,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
|||
}
|
||||
else
|
||||
{
|
||||
return new RecognizerResult()
|
||||
{
|
||||
Text = context.Activity.Text ?? string.Empty,
|
||||
Intents = new Dictionary<string, IntentScore>()
|
||||
{
|
||||
{ "None", new IntentScore() { Score = 0.0 } }
|
||||
},
|
||||
Entities = JObject.Parse("{}")
|
||||
};
|
||||
return noneIntent;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -552,12 +591,12 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
|||
private SequenceContext ToSequenceContext(DialogContext dc)
|
||||
{
|
||||
var activeDialogState = dc.ActiveDialog.State as Dictionary<string, object>;
|
||||
var state = activeDialogState[AdaptiveKey] as AdaptiveDialogState;
|
||||
var state = activeDialogState[ADAPTIVE_KEY] as AdaptiveDialogState;
|
||||
|
||||
if (state == null)
|
||||
{
|
||||
state = new AdaptiveDialogState();
|
||||
activeDialogState[AdaptiveKey] = state;
|
||||
activeDialogState[ADAPTIVE_KEY] = state;
|
||||
}
|
||||
|
||||
if (state.Actions == null)
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
|
||||
protected override Task<InputState> OnRecognizeInput(DialogContext dc)
|
||||
{
|
||||
var input = dc.State.GetValue<List<Attachment>>(InputProperty);
|
||||
var input = dc.State.GetValue<List<Attachment>>(INPUT_PROPERTY);
|
||||
var first = input.Count > 0 ? input[0] : null;
|
||||
|
||||
if (first == null || (string.IsNullOrEmpty(first.ContentUrl) && first.Content == null))
|
||||
|
@ -51,10 +51,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
switch (this.OutputFormat)
|
||||
{
|
||||
case AttachmentOutputFormat.All:
|
||||
dc.State.SetValue(InputProperty, input);
|
||||
dc.State.SetValue(INPUT_PROPERTY, input);
|
||||
break;
|
||||
case AttachmentOutputFormat.First:
|
||||
dc.State.SetValue(InputProperty, first);
|
||||
dc.State.SetValue(INPUT_PROPERTY, first);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -141,8 +141,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
|
||||
protected override Task<InputState> OnRecognizeInput(DialogContext dc)
|
||||
{
|
||||
var input = dc.State.GetValue<object>(InputProperty);
|
||||
var options = dc.State.GetValue<ChoiceInputOptions>(DialogContextState.DialogOptions);
|
||||
var input = dc.State.GetValue<object>(INPUT_PROPERTY);
|
||||
var options = dc.State.GetValue<ChoiceInputOptions>(DialogContextState.DIALOG_OPTIONS);
|
||||
|
||||
var choices = options.Choices;
|
||||
|
||||
|
@ -162,10 +162,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
{
|
||||
case ChoiceOutputFormat.Value:
|
||||
default:
|
||||
dc.State.SetValue(InputProperty, foundChoice.Value);
|
||||
dc.State.SetValue(INPUT_PROPERTY, foundChoice.Value);
|
||||
break;
|
||||
case ChoiceOutputFormat.Index:
|
||||
dc.State.SetValue(InputProperty, foundChoice.Index);
|
||||
dc.State.SetValue(INPUT_PROPERTY, foundChoice.Index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
|
||||
protected override Task<InputState> OnRecognizeInput(DialogContext dc)
|
||||
{
|
||||
var input = dc.State.GetValue<object>(InputProperty);
|
||||
var input = dc.State.GetValue<object>(INPUT_PROPERTY);
|
||||
if (dc.Context.Activity.Type == ActivityTypes.Message)
|
||||
{
|
||||
// Recognize utterance
|
||||
|
@ -60,7 +60,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
var first = results[0];
|
||||
if (bool.TryParse(first.Resolution["value"].ToString(), out var value))
|
||||
{
|
||||
dc.State.SetValue(InputProperty, value);
|
||||
dc.State.SetValue(INPUT_PROPERTY, value);
|
||||
return Task.FromResult(InputState.Valid);
|
||||
}
|
||||
else
|
||||
|
@ -83,7 +83,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
if (secondAttemptResults.Count > 0)
|
||||
{
|
||||
input = secondAttemptResults[0].Resolution.Index == 0;
|
||||
dc.State.SetValue(InputProperty, input);
|
||||
dc.State.SetValue(INPUT_PROPERTY, input);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
|
||||
protected override Task<InputState> OnRecognizeInput(DialogContext dc)
|
||||
{
|
||||
var input = dc.State.GetValue<object>(InputProperty);
|
||||
var input = dc.State.GetValue<object>(INPUT_PROPERTY);
|
||||
|
||||
var culture = GetCulture(dc);
|
||||
var results = DateTimeRecognizer.RecognizeDateTime(input.ToString(), culture);
|
||||
|
@ -36,7 +36,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
result.Add(ReadResolution(value));
|
||||
}
|
||||
|
||||
dc.State.SetValue(InputProperty, result);
|
||||
dc.State.SetValue(INPUT_PROPERTY, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -43,30 +43,32 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
|
||||
public enum AllowInterruptions
|
||||
{
|
||||
/**
|
||||
* always consult parent dialogs before taking the input
|
||||
*/
|
||||
/// <summary>
|
||||
/// Always consult parent dialogs before taking the input.
|
||||
/// </summary>
|
||||
Always,
|
||||
|
||||
/**
|
||||
* never consult parent dialogs
|
||||
*/
|
||||
/// <summary>
|
||||
/// Never consult parent dialogs.
|
||||
/// </summary>
|
||||
Never,
|
||||
|
||||
/**
|
||||
* recognize the input first, only consult parent dilaogs when notRecognized
|
||||
*/
|
||||
/// <summary>
|
||||
/// Recognize the input first, only consult parent dilaogs when notRecognized.
|
||||
/// </summary>
|
||||
NotRecognized
|
||||
}
|
||||
|
||||
public abstract class InputDialog : Dialog
|
||||
{
|
||||
#pragma warning disable SA1310 // Field should not contain underscore.
|
||||
public const string TURN_COUNT_PROPERTY = "dialog.turnCount";
|
||||
public const string INPUT_PROPERTY = "turn.value";
|
||||
|
||||
// This property can be set by user's code to indicate that the input should re-process incoming user utterance.
|
||||
// Designed to be a bool property. So user's code can set this to 'true' to signal the input to re-process incoming user utterance.
|
||||
public const string ProcessInputProperty = "turn.processInput";
|
||||
public const string TurnCountProperty = "dialog.turnCount";
|
||||
public const string InputProperty = "turn.value";
|
||||
|
||||
public const string PROCESS_INPUT_PROPERTY = "turn.processInput";
|
||||
#pragma warning restore SA1310 // Field should not contain underscore.
|
||||
private const string PersistedOptions = "options";
|
||||
private const string PersistedState = "state";
|
||||
|
||||
|
@ -78,7 +80,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
public AllowInterruptions AllowInterruptions { get; set; } = AllowInterruptions.NotRecognized;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets initial value for the prompt.
|
||||
/// Gets or sets the initial value for the prompt.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Initial value for the prompt.
|
||||
|
@ -91,7 +93,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets activity to send to the user.
|
||||
/// Gets or sets the activity to send to the user.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Activity to send to the user.
|
||||
|
@ -99,7 +101,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
public ITemplate<Activity> Prompt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets activity template for retrying prompt.
|
||||
/// Gets or sets the activity template for retrying prompt.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Activity template for retrying prompt.
|
||||
|
@ -107,13 +109,19 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
public ITemplate<Activity> UnrecognizedPrompt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets activity template to send to the user whenever the value provided is invalid.
|
||||
/// Gets or sets the activity template to send to the user whenever the value provided is invalid.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Activity template to send to the user whenever the value provided is invalid.
|
||||
/// </value>
|
||||
public ITemplate<Activity> InvalidPrompt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the activity template to send when MaxTurnCount has been reached and the default value is used.
|
||||
/// </summary>
|
||||
/// <value>The activity template.</value>
|
||||
public ITemplate<Activity> DefaultValueResponse { get; set; }
|
||||
|
||||
public List<string> Validations { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
|
@ -125,7 +133,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
public int? MaxTurnCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets default value for the input dialog.
|
||||
/// Gets or sets the default value for the input dialog when MaxTurnCount is exceeded.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Default value for the input dialog.
|
||||
|
@ -161,7 +169,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
|
||||
set
|
||||
{
|
||||
InputBindings[DialogContextState.DialogNames] = value;
|
||||
InputBindings[DialogContextState.DIALOG_VALUE] = value;
|
||||
OutputBinding = value;
|
||||
}
|
||||
}
|
||||
|
@ -174,14 +182,14 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
}
|
||||
|
||||
var op = OnInitializeOptions(dc, options);
|
||||
dc.State.SetValue(DialogContextState.DialogOptions, op);
|
||||
dc.State.SetValue(TurnCountProperty, 0);
|
||||
dc.State.SetValue(InputProperty, null);
|
||||
dc.State.SetValue(DialogContextState.DIALOG_OPTIONS, op);
|
||||
dc.State.SetValue(TURN_COUNT_PROPERTY, 0);
|
||||
dc.State.SetValue(INPUT_PROPERTY, null);
|
||||
|
||||
var state = this.AlwaysPrompt ? InputState.Missing : await this.RecognizeInput(dc);
|
||||
if (state == InputState.Valid)
|
||||
{
|
||||
var input = dc.State.GetValue<object>(InputProperty);
|
||||
var input = dc.State.GetValue<object>(INPUT_PROPERTY);
|
||||
return await dc.EndDialogAsync(input);
|
||||
}
|
||||
else
|
||||
|
@ -189,7 +197,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
// turnCount should increase here, because you want when nextTurn comes in
|
||||
// We will set the turn count to 1 so the input will not pick from "dialog.value"
|
||||
// and instead go with "turn.activity.text"
|
||||
dc.State.SetValue(TurnCountProperty, 1);
|
||||
dc.State.SetValue(TURN_COUNT_PROPERTY, 1);
|
||||
return await this.PromptUser(dc, state);
|
||||
}
|
||||
}
|
||||
|
@ -202,44 +210,50 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
return Dialog.EndOfTurn;
|
||||
}
|
||||
|
||||
var stepCount = dc.State.GetValue<int>(DialogContextState.TurnStepCount, 0);
|
||||
var stepCount = dc.State.GetValue<int>(DialogContextState.TURN_STEPCOUNT, 0);
|
||||
|
||||
if (stepCount > 0)
|
||||
{
|
||||
return await this.PromptUser(dc, InputState.Missing);
|
||||
return await this.PromptUser(dc, InputState.Missing).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var turnCount = dc.State.GetValue<int>(TurnCountProperty, 0);
|
||||
var turnCount = dc.State.GetValue<int>(TURN_COUNT_PROPERTY, 0);
|
||||
|
||||
// Perform base recognition
|
||||
var state = await this.RecognizeInput(dc);
|
||||
|
||||
if (state == InputState.Valid)
|
||||
{
|
||||
var input = dc.State.GetValue<object>(InputProperty);
|
||||
return await dc.EndDialogAsync(input);
|
||||
var input = dc.State.GetValue<object>(INPUT_PROPERTY);
|
||||
return await dc.EndDialogAsync(input).ConfigureAwait(false);
|
||||
}
|
||||
else if (this.MaxTurnCount == null || turnCount < this.MaxTurnCount)
|
||||
{
|
||||
// increase the turnCount as last step
|
||||
dc.State.SetValue(TurnCountProperty, turnCount + 1);
|
||||
return await this.PromptUser(dc, state);
|
||||
dc.State.SetValue(TURN_COUNT_PROPERTY, turnCount + 1);
|
||||
return await this.PromptUser(dc, state).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.defaultValue != null)
|
||||
{
|
||||
var (value, error) = this.defaultValue.TryEvaluate(dc.State);
|
||||
return await dc.EndDialogAsync(value);
|
||||
if (this.DefaultValueResponse != null)
|
||||
{
|
||||
var response = await this.DefaultValueResponse.BindToData(dc.Context, dc.State).ConfigureAwait(false);
|
||||
await dc.Context.SendActivityAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return await dc.EndDialogAsync(value).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
return await dc.EndDialogAsync();
|
||||
return await dc.EndDialogAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public override async Task<DialogTurnResult> ResumeDialogAsync(DialogContext dc, DialogReason reason, object result = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return await this.PromptUser(dc, InputState.Missing);
|
||||
return await this.PromptUser(dc, InputState.Missing).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected abstract Task<InputState> OnRecognizeInput(DialogContext dc);
|
||||
|
@ -372,7 +386,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
break;
|
||||
}
|
||||
|
||||
return await this.Prompt.BindToData(dc.Context, dc.State);
|
||||
return await this.Prompt.BindToData(dc.Context, dc.State).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<InputState> RecognizeInput(DialogContext dc)
|
||||
|
@ -398,13 +412,13 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
|
||||
if (input == null)
|
||||
{
|
||||
var turnCount = dc.State.GetValue<int>(TurnCountProperty);
|
||||
var processInput = dc.State.GetValue<bool>(ProcessInputProperty, false);
|
||||
var turnCount = dc.State.GetValue<int>(TURN_COUNT_PROPERTY);
|
||||
var processInput = dc.State.GetValue<bool>(PROCESS_INPUT_PROPERTY, false);
|
||||
|
||||
// Go down this path only if the user has not requested to re-process user input via turn.processInput = true.
|
||||
if (turnCount == 0 && !processInput)
|
||||
{
|
||||
input = dc.State.GetValue<object>(DialogContextState.DialogNames, null);
|
||||
input = dc.State.GetValue<object>(DialogContextState.DIALOG_VALUE, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -419,10 +433,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
}
|
||||
|
||||
// reset turn.processInput so subsequent actions are not impacted.
|
||||
dc.State.SetValue(ProcessInputProperty, false);
|
||||
dc.State.SetValue(PROCESS_INPUT_PROPERTY, false);
|
||||
}
|
||||
|
||||
dc.State.SetValue(InputProperty, input);
|
||||
dc.State.SetValue(INPUT_PROPERTY, input);
|
||||
if (input != null)
|
||||
{
|
||||
var state = await this.OnRecognizeInput(dc).ConfigureAwait(false);
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
|
||||
protected override Task<InputState> OnRecognizeInput(DialogContext dc)
|
||||
{
|
||||
var input = dc.State.GetValue<object>(InputProperty);
|
||||
var input = dc.State.GetValue<object>(INPUT_PROPERTY);
|
||||
|
||||
var culture = GetCulture(dc);
|
||||
var results = NumberRecognizer.RecognizeNumber(input.ToString(), culture);
|
||||
|
@ -70,10 +70,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
{
|
||||
case NumberOutputFormat.Float:
|
||||
default:
|
||||
dc.State.SetValue(InputProperty, input);
|
||||
dc.State.SetValue(INPUT_PROPERTY, input);
|
||||
break;
|
||||
case NumberOutputFormat.Integer:
|
||||
dc.State.SetValue(InputProperty, Math.Floor((float)input));
|
||||
dc.State.SetValue(INPUT_PROPERTY, Math.Floor((float)input));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
|
||||
set
|
||||
{
|
||||
InputBindings[DialogContextState.DialogNames] = value;
|
||||
InputBindings[DialogContextState.DIALOG_VALUE] = value;
|
||||
OutputBinding = value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
|
||||
protected override Task<InputState> OnRecognizeInput(DialogContext dc)
|
||||
{
|
||||
var input = dc.State.GetValue<string>(InputProperty);
|
||||
var input = dc.State.GetValue<string>(INPUT_PROPERTY);
|
||||
|
||||
switch (this.OutputFormat)
|
||||
{
|
||||
|
@ -67,7 +67,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
|
|||
break;
|
||||
}
|
||||
|
||||
dc.State.SetValue(InputProperty, input);
|
||||
dc.State.SetValue(INPUT_PROPERTY, input);
|
||||
return input.Length > 0 ? Task.FromResult(InputState.Valid) : Task.FromResult(InputState.Unrecognized);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
"property": {
|
||||
"$role": "expression",
|
||||
"title": "Property",
|
||||
"description": "The property to store the result of the HTTP call in (as object or string)",
|
||||
"description": "The property to store the result of the HTTP call in. The result will have 4 properties from the http response: statusCode|reasonPhrase|content|headers. If the content is json it will be an deserialized object, otherwise it will be a string",
|
||||
"examples": [
|
||||
"dialog.contosodata"
|
||||
]
|
||||
|
|
|
@ -31,6 +31,14 @@
|
|||
"No date was recognized"
|
||||
]
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
]
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
|
|
@ -85,38 +85,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
Exited
|
||||
}
|
||||
|
||||
private ulong EncodeValue(ThreadModel thread, object value)
|
||||
{
|
||||
if (dataModel.IsScalar(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var threadCode = threads[thread];
|
||||
var valueCode = thread.ValueCodes.Add(value);
|
||||
return Identifier.Encode(threadCode, valueCode);
|
||||
}
|
||||
|
||||
private void DecodeValue(ulong variablesReference, out ThreadModel thread, out object value)
|
||||
{
|
||||
Identifier.Decode(variablesReference, out var threadCode, out var valueCode);
|
||||
thread = this.threads[threadCode];
|
||||
value = thread.ValueCodes[valueCode];
|
||||
}
|
||||
|
||||
private ulong EncodeFrame(ThreadModel thread, ICodePoint frame)
|
||||
{
|
||||
var threadCode = threads[thread];
|
||||
var valueCode = thread.FrameCodes.Add(frame);
|
||||
return Identifier.Encode(threadCode, valueCode);
|
||||
}
|
||||
|
||||
private void DecodeFrame(ulong frameCode, out ThreadModel thread, out ICodePoint frame)
|
||||
{
|
||||
Identifier.Decode(frameCode, out var threadCode, out var valueCode);
|
||||
thread = this.threads[threadCode];
|
||||
frame = thread.FrameCodes[valueCode];
|
||||
}
|
||||
private int NextSeq => Interlocked.Increment(ref sequence);
|
||||
|
||||
public static string Ellipsis(string text, int length)
|
||||
{
|
||||
|
@ -277,6 +246,39 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
return $"{turnContext.Activity.ChannelId}-{turnContext.Activity.Id}";
|
||||
}
|
||||
|
||||
private ulong EncodeValue(ThreadModel thread, object value)
|
||||
{
|
||||
if (dataModel.IsScalar(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var threadCode = threads[thread];
|
||||
var valueCode = thread.ValueCodes.Add(value);
|
||||
return Identifier.Encode(threadCode, valueCode);
|
||||
}
|
||||
|
||||
private void DecodeValue(ulong variablesReference, out ThreadModel thread, out object value)
|
||||
{
|
||||
Identifier.Decode(variablesReference, out var threadCode, out var valueCode);
|
||||
thread = this.threads[threadCode];
|
||||
value = thread.ValueCodes[valueCode];
|
||||
}
|
||||
|
||||
private ulong EncodeFrame(ThreadModel thread, ICodePoint frame)
|
||||
{
|
||||
var threadCode = threads[thread];
|
||||
var valueCode = thread.FrameCodes.Add(frame);
|
||||
return Identifier.Encode(threadCode, valueCode);
|
||||
}
|
||||
|
||||
private void DecodeFrame(ulong frameCode, out ThreadModel thread, out ICodePoint frame)
|
||||
{
|
||||
Identifier.Decode(frameCode, out var threadCode, out var valueCode);
|
||||
thread = this.threads[threadCode];
|
||||
frame = thread.FrameCodes[valueCode];
|
||||
}
|
||||
|
||||
private async Task UpdateBreakpointsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var breakpoints = this.breakpoints.ApplyUpdates();
|
||||
|
@ -368,8 +370,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
await SendAsync(Protocol.Event.From(NextSeq, "output", body), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private int NextSeq => Interlocked.Increment(ref sequence);
|
||||
|
||||
private Protocol.Capabilities MakeCapabilities()
|
||||
{
|
||||
// TODO: there is a "capabilities" event for dynamic updates, but exceptionBreakpointFilters does not seem to be dynamically updateable
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
||||
{
|
||||
public interface IBreakpoints
|
||||
{
|
||||
bool IsBreakPoint(object item);
|
||||
|
||||
object ItemFor(Protocol.Breakpoint breakpoint);
|
||||
|
||||
IReadOnlyList<Protocol.Breakpoint> SetBreakpoints(Protocol.Source source, IReadOnlyList<Protocol.SourceBreakpoint> sourceBreakpoints);
|
||||
|
||||
IReadOnlyList<Protocol.Breakpoint> SetBreakpoints(IReadOnlyList<Protocol.FunctionBreakpoint> functionBreakpoints);
|
||||
|
||||
IReadOnlyList<Protocol.Breakpoint> ApplyUpdates();
|
||||
}
|
||||
}
|
|
@ -95,9 +95,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
|
||||
string IDataModel.ToString(object context) => ToString((TContext)context);
|
||||
|
||||
protected T Coerce<T>(object item) => (T)this.coercion.Coerce(item, typeof(T));
|
||||
|
||||
IEnumerable<object> IDataModel.Names(object context) => Names((TContext)context).Cast<object>();
|
||||
|
||||
protected T Coerce<T>(object item) => (T)this.coercion.Coerce(item, typeof(T));
|
||||
}
|
||||
|
||||
public sealed class DictionaryDataModel<TKey, TValue> : DataModelBase<IDictionary<TKey, TValue>, TKey, TValue>
|
||||
|
|
|
@ -212,6 +212,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
|
||||
public class Event : Message
|
||||
{
|
||||
#pragma warning disable SA1300 // Should begin with an uppercase letter.
|
||||
public Event(int seq, string @event)
|
||||
{
|
||||
this.Seq = seq;
|
||||
|
@ -220,6 +221,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
}
|
||||
|
||||
public string @event { get; set; }
|
||||
#pragma warning restore SA1300 // Should begin with an uppercase letter.
|
||||
|
||||
public static Event<TBody> From<TBody>(int seq, string @event, TBody body) => new Event<TBody>(seq, @event) { Body = body };
|
||||
}
|
||||
|
|
|
@ -284,17 +284,4 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
public object Item { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
public interface IBreakpoints
|
||||
{
|
||||
bool IsBreakPoint(object item);
|
||||
|
||||
object ItemFor(Protocol.Breakpoint breakpoint);
|
||||
|
||||
IReadOnlyList<Protocol.Breakpoint> SetBreakpoints(Protocol.Source source, IReadOnlyList<Protocol.SourceBreakpoint> sourceBreakpoints);
|
||||
|
||||
IReadOnlyList<Protocol.Breakpoint> SetBreakpoints(IReadOnlyList<Protocol.FunctionBreakpoint> functionBreakpoints);
|
||||
|
||||
IReadOnlyList<Protocol.Breakpoint> ApplyUpdates();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Dialogs.Adaptive;
|
||||
using Microsoft.Bot.Builder.Dialogs.Debugging;
|
||||
|
@ -21,27 +23,37 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative
|
|||
{
|
||||
IRefResolver refResolver = new IdRefResolver(resourceExplorer, registry);
|
||||
|
||||
string id = resource.Id;
|
||||
var paths = new Stack<string>();
|
||||
paths.Push(resource.Id);
|
||||
if (resource is FileResource fileResource)
|
||||
{
|
||||
id = fileResource.FullName;
|
||||
paths.Push(fileResource.FullName);
|
||||
}
|
||||
|
||||
var json = await resource.ReadTextAsync();
|
||||
try
|
||||
{
|
||||
var json = await resource.ReadTextAsync();
|
||||
|
||||
return Load<T>(registry, refResolver, paths, json);
|
||||
return Load<T>(registry, refResolver, paths, json);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
if (err.InnerException is SyntaxErrorException)
|
||||
{
|
||||
throw new SyntaxErrorException(err.InnerException.Message)
|
||||
{
|
||||
Source = $"{id}{err.InnerException.Source}"
|
||||
};
|
||||
}
|
||||
|
||||
throw new Exception($"{id} error: {err.Message}\n{err.InnerException?.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public static T Load<T>(IResource resource, ResourceExplorer resourceExplorer, Source.IRegistry registry)
|
||||
{
|
||||
IRefResolver refResolver = new IdRefResolver(resourceExplorer, registry);
|
||||
|
||||
var paths = new Stack<string>();
|
||||
if (resource is FileResource fileResource)
|
||||
{
|
||||
paths.Push(fileResource.FullName);
|
||||
}
|
||||
|
||||
var json = resource.ReadTextAsync().GetAwaiter().GetResult();
|
||||
|
||||
return Load<T>(registry, refResolver, paths, json);
|
||||
return LoadAsync<T>(resource, resourceExplorer, registry).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace Microsoft.Bot.Builder.Dialogs
|
|||
}
|
||||
|
||||
State = new DialogContextState(this, settings: settings, userState: userState, conversationState: conversationState, turnState: turnState as Dictionary<string, object>);
|
||||
State.SetValue(DialogContextState.TurnActivity, Context.Activity);
|
||||
State.SetValue(DialogContextState.TURN_ACTIVITY, Context.Activity);
|
||||
}
|
||||
|
||||
public DialogContext(DialogSet dialogs, ITurnContext turnContext, DialogState state, IDictionary<string, object> conversationState = null, IDictionary<string, object> userState = null, IDictionary<string, object> settings = null)
|
||||
|
@ -67,7 +67,7 @@ namespace Microsoft.Bot.Builder.Dialogs
|
|||
}
|
||||
|
||||
State = new DialogContextState(this, settings: settings, userState: userState, conversationState: conversationState, turnState: turnState as Dictionary<string, object>);
|
||||
State.SetValue(DialogContextState.TurnActivity, Context.Activity);
|
||||
State.SetValue(DialogContextState.TURN_ACTIVITY, Context.Activity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -330,11 +330,11 @@ namespace Microsoft.Bot.Builder.Dialogs
|
|||
// set dialog result
|
||||
if (ShouldInheritState(dialog))
|
||||
{
|
||||
State.SetValue(DialogContextState.StepOptionsProperty, options);
|
||||
State.SetValue(DialogContextState.STEP_OPTIONS_PROPERTY, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
State.SetValue(DialogContextState.DialogOptions, options);
|
||||
State.SetValue(DialogContextState.DIALOG_OPTIONS, options);
|
||||
}
|
||||
|
||||
// Call dialogs BeginAsync() method.
|
||||
|
|
|
@ -1,31 +1,51 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Expressions;
|
||||
using Microsoft.Bot.Builder.Expressions.Parser;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the shape of the state object returned by calling DialogContext.State.ToJson().
|
||||
/// </summary>
|
||||
public class DialogContextVisibleState
|
||||
{
|
||||
[JsonProperty(PropertyName = "user")]
|
||||
public IDictionary<string, object> User { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "conversation")]
|
||||
public IDictionary<string, object> Conversation { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "dialog")]
|
||||
public IDictionary<string, object> Dialog { get; set; }
|
||||
}
|
||||
|
||||
public class DialogContextState : IDictionary<string, object>
|
||||
{
|
||||
/// <summary>
|
||||
/// Common state properties paths.
|
||||
/// </summary>
|
||||
public const string DialogOptions = "dialog.options";
|
||||
public const string DialogNames = "dialog.value";
|
||||
#pragma warning disable SA1310 // Field should not contain underscore.
|
||||
public const string DIALOG_OPTIONS = "dialog.options";
|
||||
public const string DIALOG_VALUE = "dialog.value";
|
||||
|
||||
public const string TurnActivity = "turn.activity";
|
||||
public const string TurnRecognized = "turn.recognized";
|
||||
public const string TurnTopIntent = "turn.recognized.intent";
|
||||
public const string TurnTopScore = "turn.recognized.score";
|
||||
public const string TurnStepCount = "turn.stepCount";
|
||||
public const string TurnDialogEvent = "turn.dialogEvent";
|
||||
public const string TURN_ACTIVITY = "turn.activity";
|
||||
public const string TURN_RECOGNIZED = "turn.recognized";
|
||||
public const string TURN_TOPINTENT = "turn.recognized.intent";
|
||||
public const string TURN_TOPSCORE = "turn.recognized.score";
|
||||
public const string TURN_STEPCOUNT = "turn.stepCount";
|
||||
public const string TURN_DIALOGEVENT = "turn.dialogEvent";
|
||||
|
||||
public const string StepOptionsProperty = "dialog.step.options";
|
||||
public const string STEP_OPTIONS_PROPERTY = "dialog.step.options";
|
||||
#pragma warning restore SA1310 // Field should not contain underscore.
|
||||
|
||||
private const string PrefixCallBack = "callstackScope('";
|
||||
|
||||
|
@ -424,19 +444,4 @@ namespace Microsoft.Bot.Builder.Dialogs
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the shape of the state object returned by calling DialogContext.State.ToJson().
|
||||
/// </summary>
|
||||
public class DialogContextVisibleState
|
||||
{
|
||||
[JsonProperty(PropertyName = "user")]
|
||||
public IDictionary<string, object> User { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "conversation")]
|
||||
public IDictionary<string, object> Conversation { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "dialog")]
|
||||
public IDictionary<string, object> Dialog { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using Antlr4.Runtime;
|
||||
using Antlr4.Runtime.Misc;
|
||||
|
||||
|
@ -11,6 +13,9 @@ namespace Microsoft.Bot.Builder.Expressions
|
|||
{
|
||||
public static readonly ErrorListener Instance = new ErrorListener();
|
||||
|
||||
public override void SyntaxError([NotNull] IRecognizer recognizer, [Nullable] IToken offendingSymbol, int line, int charPositionInLine, [NotNull] string msg, [Nullable] RecognitionException e) => throw new Exception($"syntax error at line {line}:{charPositionInLine} {msg}");
|
||||
public override void SyntaxError([NotNull] IRecognizer recognizer, [Nullable] IToken offendingSymbol, int line, int charPositionInLine, [NotNull] string msg, [Nullable] RecognitionException e)
|
||||
{
|
||||
throw new SyntaxErrorException(msg) { Source = $"({line}:{charPositionInLine})", };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,6 @@ namespace Microsoft.Bot.Builder.Expressions.Parser
|
|||
{ "~", $"dialog.instance" },
|
||||
};
|
||||
|
||||
private readonly EvaluatorLookup _lookup;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExpressionEngine"/> class.
|
||||
/// Constructor.
|
||||
|
@ -39,15 +37,17 @@ namespace Microsoft.Bot.Builder.Expressions.Parser
|
|||
/// <param name="lookup">If present delegate to lookup evaluation information from type string.</param>
|
||||
public ExpressionEngine(EvaluatorLookup lookup = null)
|
||||
{
|
||||
_lookup = lookup ?? BuiltInFunctions.Lookup;
|
||||
EvaluatorLookup = lookup ?? BuiltInFunctions.Lookup;
|
||||
}
|
||||
|
||||
public EvaluatorLookup EvaluatorLookup { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Parse the input into an expression.
|
||||
/// </summary>
|
||||
/// <param name="expression">Expression to parse.</param>
|
||||
/// <returns>Expresion tree.</returns>
|
||||
public Expression Parse(string expression) => new ExpressionTransformer(_lookup).Transform(AntlrParse(expression));
|
||||
public Expression Parse(string expression) => new ExpressionTransformer(EvaluatorLookup).Transform(AntlrParse(expression));
|
||||
|
||||
protected static IParseTree AntlrParse(string expression)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
@ -666,7 +667,7 @@ namespace Microsoft.Bot.Builder.Expressions
|
|||
{
|
||||
if (!_functions.TryGetValue(type, out var eval))
|
||||
{
|
||||
throw new Exception($"{type} does not have an evaluator, it's not a built-in function or a customized function");
|
||||
throw new SyntaxErrorException($"{type} does not have an evaluator, it's not a built-in function or a customized function");
|
||||
}
|
||||
return eval;
|
||||
}
|
||||
|
|
|
@ -17,11 +17,14 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
|
||||
private Stack<EvaluationTarget> evaluationTargetStack = new Stack<EvaluationTarget>();
|
||||
|
||||
public Analyzer(List<LGTemplate> templates)
|
||||
public Analyzer(List<LGTemplate> templates, ExpressionEngine expressionEngine)
|
||||
{
|
||||
Templates = templates;
|
||||
templateMap = templates.ToDictionary(t => t.Name);
|
||||
_expressionParser = new ExpressionEngine(new GetMethodExtensions(new Evaluator(this.Templates, null)).GetMethodX);
|
||||
|
||||
// create an evaluator to leverage it's customized function look up for checking
|
||||
var evaluator = new Evaluator(Templates, expressionEngine);
|
||||
this._expressionParser = evaluator.ExpressionEngine;
|
||||
}
|
||||
|
||||
public List<LGTemplate> Templates { get; }
|
||||
|
|
|
@ -6,24 +6,28 @@ using System.Text;
|
|||
using System.Text.RegularExpressions;
|
||||
using Antlr4.Runtime.Misc;
|
||||
using Antlr4.Runtime.Tree;
|
||||
using Microsoft.Bot.Builder.Expressions;
|
||||
using Microsoft.Bot.Builder.Expressions.Parser;
|
||||
|
||||
namespace Microsoft.Bot.Builder.LanguageGeneration
|
||||
{
|
||||
public class Evaluator : LGFileParserBaseVisitor<string>
|
||||
{
|
||||
private readonly IGetMethod getMethodX;
|
||||
private readonly Stack<EvaluationTarget> evaluationTargetStack = new Stack<EvaluationTarget>();
|
||||
|
||||
public Evaluator(List<LGTemplate> templates, IGetMethod getMethod)
|
||||
public Evaluator(List<LGTemplate> templates, ExpressionEngine expressionEngine)
|
||||
{
|
||||
Templates = templates;
|
||||
TemplateMap = templates.ToDictionary(x => x.Name);
|
||||
getMethodX = getMethod ?? new GetMethodExtensions(this);
|
||||
|
||||
// generate a new customzied expression engine by injecting the template as functions
|
||||
ExpressionEngine = new ExpressionEngine(CustomizedEvaluatorLookup(expressionEngine.EvaluatorLookup));
|
||||
}
|
||||
|
||||
public List<LGTemplate> Templates { get; }
|
||||
|
||||
public ExpressionEngine ExpressionEngine { get; }
|
||||
|
||||
public Dictionary<string, LGTemplate> TemplateMap { get; }
|
||||
|
||||
public string EvaluateTemplate(string templateName, object scope)
|
||||
|
@ -255,9 +259,53 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
|
||||
private (object value, string error) EvalByExpressionEngine(string exp, object scope)
|
||||
{
|
||||
var parse = new ExpressionEngine(getMethodX.GetMethodX).Parse(exp);
|
||||
var parse = this.ExpressionEngine.Parse(exp);
|
||||
return parse.TryEvaluate(scope);
|
||||
}
|
||||
|
||||
// Genearte a new lookup function based on one lookup function
|
||||
private EvaluatorLookup CustomizedEvaluatorLookup(EvaluatorLookup baseLookup)
|
||||
=> (string name) =>
|
||||
{
|
||||
var builtInPrefix = "builtin.";
|
||||
|
||||
if (name.StartsWith(builtInPrefix))
|
||||
{
|
||||
return baseLookup(name.Substring(builtInPrefix.Length));
|
||||
}
|
||||
|
||||
if (this.TemplateMap.ContainsKey(name))
|
||||
{
|
||||
return new ExpressionEvaluator(name, BuiltInFunctions.Apply(this.TemplateEvaluator(name)), ReturnType.String, this.ValidTemplateReference);
|
||||
}
|
||||
|
||||
return baseLookup(name);
|
||||
};
|
||||
|
||||
private Func<IReadOnlyList<object>, object> TemplateEvaluator(string templateName)
|
||||
=> (IReadOnlyList<object> args) =>
|
||||
{
|
||||
var newScope = this.ConstructScope(templateName, args.ToList());
|
||||
return this.EvaluateTemplate(templateName, newScope);
|
||||
};
|
||||
|
||||
private void ValidTemplateReference(Expression expression)
|
||||
{
|
||||
var templateName = expression.Type;
|
||||
|
||||
if (!this.TemplateMap.ContainsKey(templateName))
|
||||
{
|
||||
throw new Exception($"no such template '{templateName}' to call in {expression}");
|
||||
}
|
||||
|
||||
var expectedArgsCount = this.TemplateMap[templateName].Parameters.Count();
|
||||
var actualArgsCount = expression.Children.Length;
|
||||
|
||||
if (expectedArgsCount != actualArgsCount)
|
||||
{
|
||||
throw new Exception($"arguments mismatch for template {templateName}, expect {expectedArgsCount} actual {actualArgsCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class EvaluationTarget
|
||||
|
|
|
@ -13,14 +13,16 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
{
|
||||
public class Expander : LGFileParserBaseVisitor<List<string>>
|
||||
{
|
||||
private readonly IGetMethod getMethodX;
|
||||
private readonly ExpressionEngine expressionEngine;
|
||||
private readonly Stack<EvaluationTarget> evaluationTargetStack = new Stack<EvaluationTarget>();
|
||||
|
||||
public Expander(List<LGTemplate> templates, IGetMethod getMethod)
|
||||
public Expander(List<LGTemplate> templates, ExpressionEngine expressionEngine)
|
||||
{
|
||||
Templates = templates;
|
||||
TemplateMap = templates.ToDictionary(x => x.Name);
|
||||
getMethodX = getMethod ?? new GetExpanderMethod(this);
|
||||
|
||||
// generate a new customzied expression engine by injecting the template as functions
|
||||
this.expressionEngine = new ExpressionEngine(CustomizedEvaluatorLookup(expressionEngine.EvaluatorLookup));
|
||||
}
|
||||
|
||||
public List<LGTemplate> Templates { get; }
|
||||
|
@ -252,10 +254,8 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
return EvalExpression(exp);
|
||||
}
|
||||
|
||||
private EvaluationTarget CurrentTarget() =>
|
||||
|
||||
// just don't want to write evaluationTargetStack.Peek() everywhere
|
||||
evaluationTargetStack.Peek();
|
||||
// just don't want to write evaluationTargetStack.Peek() everywhere
|
||||
private EvaluationTarget CurrentTarget() => evaluationTargetStack.Peek();
|
||||
|
||||
private List<string> EvalMultiLineText(string exp)
|
||||
{
|
||||
|
@ -292,7 +292,7 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
|
||||
private (object value, string error) EvalByExpressionEngine(string exp, object scope)
|
||||
{
|
||||
var parse = new ExpressionEngine(getMethodX.GetMethodX).Parse(exp);
|
||||
var parse = this.expressionEngine.Parse(exp);
|
||||
return parse.TryEvaluate(scope);
|
||||
}
|
||||
|
||||
|
@ -309,63 +309,43 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
internal class GetExpanderMethod : IGetMethod
|
||||
{
|
||||
// Hold an evaluator instance to make sure all functions have access
|
||||
// This ensentially make all functions as closure
|
||||
// This is perticularly used for using templateName as lambda
|
||||
// Such as {foreach(alarms, ShowAlarm)}
|
||||
private readonly Expander _expander;
|
||||
|
||||
public GetExpanderMethod(Expander expander)
|
||||
// Genearte a new lookup function based on one lookup function
|
||||
private EvaluatorLookup CustomizedEvaluatorLookup(EvaluatorLookup baseLookup)
|
||||
=> (string name) =>
|
||||
{
|
||||
_expander = expander;
|
||||
}
|
||||
|
||||
public ExpressionEvaluator GetMethodX(string name)
|
||||
{
|
||||
// user can always choose to use builtin.xxx to disambiguate with template xxx
|
||||
var builtInPrefix = "builtin.";
|
||||
|
||||
if (name.StartsWith(builtInPrefix))
|
||||
{
|
||||
return BuiltInFunctions.Lookup(name.Substring(builtInPrefix.Length));
|
||||
return baseLookup(name.Substring(builtInPrefix.Length));
|
||||
}
|
||||
|
||||
// TODO: Should add verifiers and validators
|
||||
switch (name)
|
||||
if (this.TemplateMap.ContainsKey(name))
|
||||
{
|
||||
case "join":
|
||||
return new ExpressionEvaluator("join", BuiltInFunctions.Apply(this.Join));
|
||||
return new ExpressionEvaluator(name, BuiltInFunctions.Apply(this.TemplateEvaluator(name)), ReturnType.String, this.ValidTemplateReference);
|
||||
}
|
||||
|
||||
if (_expander.TemplateMap.ContainsKey(name))
|
||||
{
|
||||
return new ExpressionEvaluator($"{name}", BuiltInFunctions.Apply(this.TemplateEvaluator(name)), ReturnType.String, this.ValidTemplateReference);
|
||||
}
|
||||
return baseLookup(name);
|
||||
};
|
||||
|
||||
return BuiltInFunctions.Lookup(name);
|
||||
}
|
||||
|
||||
public Func<IReadOnlyList<object>, object> TemplateEvaluator(string templateName) =>
|
||||
private Func<IReadOnlyList<object>, object> TemplateEvaluator(string templateName) =>
|
||||
(IReadOnlyList<object> args) =>
|
||||
{
|
||||
var newScope = _expander.ConstructScope(templateName, args.ToList());
|
||||
return _expander.EvaluateTemplate(templateName, newScope);
|
||||
var newScope = this.ConstructScope(templateName, args.ToList());
|
||||
return this.EvaluateTemplate(templateName, newScope);
|
||||
};
|
||||
|
||||
public void ValidTemplateReference(Expression expression)
|
||||
private void ValidTemplateReference(Expression expression)
|
||||
{
|
||||
var templateName = expression.Type;
|
||||
|
||||
if (!_expander.TemplateMap.ContainsKey(templateName))
|
||||
if (!this.TemplateMap.ContainsKey(templateName))
|
||||
{
|
||||
throw new Exception($"no such template '{templateName}' to call in {expression}");
|
||||
}
|
||||
|
||||
var expectedArgsCount = _expander.TemplateMap[templateName].Parameters.Count();
|
||||
var expectedArgsCount = this.TemplateMap[templateName].Parameters.Count();
|
||||
var actualArgsCount = expression.Children.Length;
|
||||
|
||||
if (expectedArgsCount != actualArgsCount)
|
||||
|
@ -373,36 +353,5 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
throw new Exception($"arguments mismatch for template {templateName}, expect {expectedArgsCount} actual {actualArgsCount}");
|
||||
}
|
||||
}
|
||||
|
||||
public object Join(IReadOnlyList<object> parameters)
|
||||
{
|
||||
object result = null;
|
||||
if (parameters.Count == 2 &&
|
||||
BuiltInFunctions.TryParseList(parameters[0], out var p0) &&
|
||||
parameters[1] is string sep)
|
||||
{
|
||||
var p = p0.OfType<object>().Select(x => BuiltInFunctions.TryParseList(x, out var p1) ? p1[0].ToString() : x.ToString());
|
||||
result = string.Join(sep, p);
|
||||
}
|
||||
else if (parameters.Count == 3 &&
|
||||
BuiltInFunctions.TryParseList(parameters[0], out var li) &&
|
||||
parameters[1] is string sep1 &&
|
||||
parameters[2] is string sep2)
|
||||
{
|
||||
var p = li.OfType<object>().Select(x => BuiltInFunctions.TryParseList(x, out var p1) ? p1[0].ToString() : x.ToString());
|
||||
|
||||
if (li.Count < 3)
|
||||
{
|
||||
result = string.Join(sep2, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
var firstPart = string.Join(sep1, p.TakeWhile(o => o != null && o != p.LastOrDefault()));
|
||||
result = firstPart + sep2 + p.Last().ToString();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,21 @@ using System.Text.RegularExpressions;
|
|||
using Antlr4.Runtime;
|
||||
using Antlr4.Runtime.Misc;
|
||||
using Antlr4.Runtime.Tree;
|
||||
using Microsoft.Bot.Builder.Expressions;
|
||||
using Microsoft.Bot.Builder.Expressions.Parser;
|
||||
|
||||
namespace Microsoft.Bot.Builder.LanguageGeneration
|
||||
{
|
||||
public class StaticChecker
|
||||
{
|
||||
public static List<Diagnostic> CheckFiles(IEnumerable<string> filePaths, ImportResolverDelegate importResolver = null)
|
||||
private readonly ExpressionEngine expressionEngine;
|
||||
|
||||
public StaticChecker(ExpressionEngine expressionEngine = null)
|
||||
{
|
||||
this.expressionEngine = expressionEngine ?? new ExpressionEngine();
|
||||
}
|
||||
|
||||
public List<Diagnostic> CheckFiles(IEnumerable<string> filePaths, ImportResolverDelegate importResolver = null)
|
||||
{
|
||||
var result = new List<Diagnostic>();
|
||||
var templates = new List<LGTemplate>();
|
||||
|
@ -51,9 +59,9 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
return result;
|
||||
}
|
||||
|
||||
public static List<Diagnostic> CheckFile(string filePath, ImportResolverDelegate importResolver = null) => CheckFiles(new List<string>() { filePath }, importResolver);
|
||||
public List<Diagnostic> CheckFile(string filePath, ImportResolverDelegate importResolver = null) => CheckFiles(new List<string>() { filePath }, importResolver);
|
||||
|
||||
public static List<Diagnostic> CheckText(string content, string id = "", ImportResolverDelegate importResolver = null)
|
||||
public List<Diagnostic> CheckText(string content, string id = "", ImportResolverDelegate importResolver = null)
|
||||
{
|
||||
if (importResolver == null)
|
||||
{
|
||||
|
@ -92,21 +100,40 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
return result;
|
||||
}
|
||||
|
||||
public static List<Diagnostic> CheckTemplates(List<LGTemplate> templates) => new StaticCheckerInner(templates).Check();
|
||||
public List<Diagnostic> CheckTemplates(List<LGTemplate> templates) => new StaticCheckerInner(templates, expressionEngine).Check();
|
||||
|
||||
private class StaticCheckerInner : LGFileParserBaseVisitor<List<Diagnostic>>
|
||||
{
|
||||
private Dictionary<string, LGTemplate> templateMap = new Dictionary<string, LGTemplate>();
|
||||
|
||||
private string currentSource = string.Empty;
|
||||
private ExpressionEngine baseExpressionEngine;
|
||||
|
||||
public StaticCheckerInner(List<LGTemplate> templates)
|
||||
private IExpressionParser _expressionParser;
|
||||
|
||||
public StaticCheckerInner(List<LGTemplate> templates, ExpressionEngine expressionEngine)
|
||||
{
|
||||
Templates = templates;
|
||||
baseExpressionEngine = expressionEngine;
|
||||
}
|
||||
|
||||
public List<LGTemplate> Templates { get; }
|
||||
|
||||
// Create a property because we want this to be lazy loaded
|
||||
private IExpressionParser ExpressionParser
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_expressionParser == null)
|
||||
{
|
||||
// create an evaluator to leverage it's customized function look up for checking
|
||||
var evaluator = new Evaluator(Templates, baseExpressionEngine);
|
||||
_expressionParser = evaluator.ExpressionEngine;
|
||||
}
|
||||
return _expressionParser;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return error messaages list.
|
||||
/// </summary>
|
||||
|
@ -408,7 +435,7 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
|
||||
try
|
||||
{
|
||||
new ExpressionEngine(new GetMethodExtensions(new Evaluator(this.Templates, null)).GetMethodX).Parse(expression);
|
||||
ExpressionParser.Parse(expression);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -454,7 +481,7 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
|
||||
try
|
||||
{
|
||||
new ExpressionEngine(new GetMethodExtensions(new Evaluator(this.Templates, null)).GetMethodX).Parse(exp);
|
||||
ExpressionParser.Parse(exp);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Bot.Builder.Expressions.Parser;
|
||||
|
||||
namespace Microsoft.Bot.Builder.LanguageGeneration
|
||||
{
|
||||
|
@ -10,13 +11,17 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
/// </summary>
|
||||
public class TemplateEngine
|
||||
{
|
||||
private readonly ExpressionEngine expressionEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TemplateEngine"/> class.
|
||||
/// Return an empty engine, you can then use AddFile\AddFiles to add files to it,
|
||||
/// or you can just use this empty engine to evaluate inline template.
|
||||
/// </summary>
|
||||
public TemplateEngine()
|
||||
/// <param name="expressionEngine">The expression engine this template engine based on.</param>
|
||||
public TemplateEngine(ExpressionEngine expressionEngine = null)
|
||||
{
|
||||
this.expressionEngine = expressionEngine ?? new ExpressionEngine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -88,11 +93,10 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
/// </summary>
|
||||
/// <param name="templateName">Template name to be evaluated.</param>
|
||||
/// <param name="scope">The state visible in the evaluation.</param>
|
||||
/// <param name="methodBinder">Optional methodBinder to extend or override functions.</param>
|
||||
/// <returns>Evaluate result.</returns>
|
||||
public string EvaluateTemplate(string templateName, object scope = null, IGetMethod methodBinder = null)
|
||||
public string EvaluateTemplate(string templateName, object scope = null)
|
||||
{
|
||||
var evaluator = new Evaluator(Templates, methodBinder);
|
||||
var evaluator = new Evaluator(Templates, this.expressionEngine);
|
||||
return evaluator.EvaluateTemplate(templateName, scope);
|
||||
}
|
||||
|
||||
|
@ -102,17 +106,16 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
/// </summary>
|
||||
/// <param name="templateName">Template name to be evaluated.</param>
|
||||
/// <param name="scope">The state visible in the evaluation.</param>
|
||||
/// <param name="methodBinder">Optional methodBinder to extend or override functions.</param>
|
||||
/// <returns>Expand result.</returns>
|
||||
public List<string> ExpandTemplate(string templateName, object scope = null, IGetMethod methodBinder = null)
|
||||
public List<string> ExpandTemplate(string templateName, object scope = null)
|
||||
{
|
||||
var expander = new Expander(Templates, methodBinder);
|
||||
var expander = new Expander(Templates, this.expressionEngine);
|
||||
return expander.EvaluateTemplate(templateName, scope);
|
||||
}
|
||||
|
||||
public AnalyzerResult AnalyzeTemplate(string templateName)
|
||||
{
|
||||
var analyzer = new Analyzer(Templates);
|
||||
var analyzer = new Analyzer(Templates, this.expressionEngine);
|
||||
return analyzer.AnalyzeTemplate(templateName);
|
||||
}
|
||||
|
||||
|
@ -121,9 +124,8 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
/// </summary>
|
||||
/// <param name="inlineStr">inline string which will be evaluated.</param>
|
||||
/// <param name="scope">scope object or JToken.</param>
|
||||
/// <param name="methodBinder">input method.</param>
|
||||
/// <returns>Evaluate result.</returns>
|
||||
public string Evaluate(string inlineStr, object scope = null, IGetMethod methodBinder = null)
|
||||
public string Evaluate(string inlineStr, object scope = null)
|
||||
{
|
||||
// wrap inline string with "# name and -" to align the evaluation process
|
||||
var fakeTemplateId = "__temp__";
|
||||
|
@ -135,7 +137,7 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
var templates = Templates.Concat(lgsource.Templates).ToList();
|
||||
RunStaticCheck(templates);
|
||||
|
||||
var evaluator = new Evaluator(templates, methodBinder);
|
||||
var evaluator = new Evaluator(templates, this.expressionEngine);
|
||||
return evaluator.EvaluateTemplate(fakeTemplateId, scope);
|
||||
}
|
||||
|
||||
|
@ -146,7 +148,7 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
private void RunStaticCheck(List<LGTemplate> templates = null)
|
||||
{
|
||||
var teamplatesToCheck = templates ?? this.Templates;
|
||||
var diagnostics = StaticChecker.CheckTemplates(teamplatesToCheck);
|
||||
var diagnostics = new StaticChecker(this.expressionEngine).CheckTemplates(teamplatesToCheck);
|
||||
|
||||
var errors = diagnostics.Where(u => u.Severity == DiagnosticSeverity.Error).ToList();
|
||||
if (errors.Count != 0)
|
||||
|
|
|
@ -490,6 +490,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -869,6 +878,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -1237,6 +1255,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -1476,6 +1503,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -2524,7 +2560,7 @@
|
|||
"property": {
|
||||
"$role": "expression",
|
||||
"title": "Property",
|
||||
"description": "The property to store the result of the HTTP call in (as object or string)",
|
||||
"description": "The property to store the result of the HTTP call in. The result will have 4 properties from the http response: statusCode|reasonPhrase|content|headers. If the content is json it will be an deserialized object, otherwise it will be a string",
|
||||
"examples": [
|
||||
"dialog.contosodata"
|
||||
],
|
||||
|
@ -3524,6 +3560,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -3702,6 +3747,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -5713,6 +5767,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
|
|
@ -17,7 +17,7 @@ set branch=4.Future
|
|||
rem Update .schema
|
||||
:update
|
||||
echo Updating .schema files and building sdk.schema for branch %branch%
|
||||
call dialogSchema ../libraries/**/*.schema -u -b %branch% -o sdk.schema
|
||||
bf dialog:merge ../libraries/**/*.schema -u -b %branch% -o sdk.schema
|
||||
echo *** Schema files will not be available until branch %current% is merged into %branch% ***
|
||||
|
||||
:done
|
||||
|
|
|
@ -541,6 +541,7 @@ namespace Microsoft.Bot.Builder.AI.TriggerTrees.Tests
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
public class WeightedChoice<T>
|
||||
{
|
||||
public double Weight = 0.0;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
|
@ -10,11 +11,13 @@ using Microsoft.Bot.Builder.Dialogs.Adaptive.Input;
|
|||
using Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers;
|
||||
using Microsoft.Bot.Builder.Dialogs.Declarative.Resources;
|
||||
using Microsoft.Bot.Builder.Dialogs.Declarative.Types;
|
||||
using Microsoft.Bot.Builder.Expressions;
|
||||
using Microsoft.Bot.Builder.Expressions.Parser;
|
||||
using Microsoft.Bot.Builder.LanguageGeneration;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Schema.NET;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Tests
|
||||
{
|
||||
|
@ -291,6 +294,84 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Tests
|
|||
.StartTestAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task AdaptiveDialog_TextInputDefaultValueResponse()
|
||||
{
|
||||
var ruleDialog = new AdaptiveDialog("planningTest")
|
||||
{
|
||||
Events = new List<IOnEvent>()
|
||||
{
|
||||
new OnBeginDialog()
|
||||
{
|
||||
Actions = new List<IDialog>()
|
||||
{
|
||||
new NumberInput()
|
||||
{
|
||||
Prompt = new ActivityTemplate("Hello, what is your age?"),
|
||||
Property = "user.age",
|
||||
DefaultValue = "10",
|
||||
MaxTurnCount = 2,
|
||||
DefaultValueResponse = new ActivityTemplate("I am going to say you are 10.")
|
||||
},
|
||||
new SendActivity()
|
||||
{
|
||||
Activity = new ActivityTemplate("Your age is {user.age}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
await CreateFlow(ruleDialog)
|
||||
.SendConversationUpdate()
|
||||
.AssertReply("Hello, what is your age?")
|
||||
.Send("Why do you want to know")
|
||||
.AssertReply("Hello, what is your age?")
|
||||
.Send("Why do you want to know")
|
||||
.AssertReply("I am going to say you are 10.")
|
||||
.AssertReply("Your age is 10.")
|
||||
.StartTestAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task AdaptiveDialog_TextInputNoMaxTurnCount()
|
||||
{
|
||||
var ruleDialog = new AdaptiveDialog("planningTest")
|
||||
{
|
||||
Events = new List<IOnEvent>()
|
||||
{
|
||||
new OnBeginDialog()
|
||||
{
|
||||
Actions = new List<IDialog>()
|
||||
{
|
||||
new NumberInput()
|
||||
{
|
||||
Prompt = new ActivityTemplate("Hello, what is your age?"),
|
||||
Property = "user.age",
|
||||
DefaultValue = "10",
|
||||
DefaultValueResponse = new ActivityTemplate("I am going to say you are 10.")
|
||||
},
|
||||
new SendActivity()
|
||||
{
|
||||
Activity = new ActivityTemplate("Your age is {user.age}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
await CreateFlow(ruleDialog)
|
||||
.SendConversationUpdate()
|
||||
.AssertReply("Hello, what is your age?")
|
||||
.Send("Why do you want to know")
|
||||
.AssertReply("Hello, what is your age?")
|
||||
.Send("Why do you want to know")
|
||||
.AssertReply("Hello, what is your age?")
|
||||
.Send("Why do you want to know")
|
||||
.AssertReply("Hello, what is your age?")
|
||||
.StartTestAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task AdaptiveDialog_DoActions()
|
||||
{
|
||||
|
@ -965,7 +1046,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Tests
|
|||
},
|
||||
new BeginDialog("ageDialog")
|
||||
{
|
||||
Options = new
|
||||
Options = new
|
||||
{
|
||||
userAge = "$age"
|
||||
}
|
||||
|
@ -1896,6 +1977,44 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Tests
|
|||
.StartTestAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task AdaptiveDialog_AdaptiveCardSubmit()
|
||||
{
|
||||
var ruleDialog = new AdaptiveDialog("planningTest")
|
||||
{
|
||||
AutoEndDialog = false,
|
||||
Recognizer = new RegexRecognizer()
|
||||
{
|
||||
Intents = new Dictionary<string, string>()
|
||||
{
|
||||
{ "SubmitIntent", "123123123" }
|
||||
}
|
||||
},
|
||||
Events = new List<IOnEvent>()
|
||||
{
|
||||
new OnIntent(intent: "SubmitIntent")
|
||||
{
|
||||
Actions = new List<IDialog>()
|
||||
{
|
||||
new SendActivity("The city is {@city}!")
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
var submitActivity = Activity.CreateMessageActivity();
|
||||
submitActivity.Value = new
|
||||
{
|
||||
intent = "SubmitIntent",
|
||||
city = "Seattle"
|
||||
};
|
||||
|
||||
await CreateFlow(ruleDialog)
|
||||
.Send(submitActivity)
|
||||
.AssertReply("The city is Seattle!")
|
||||
.StartTestAsync();
|
||||
}
|
||||
|
||||
private TestFlow CreateFlow(AdaptiveDialog ruleDialog)
|
||||
{
|
||||
TypeFactory.Configuration = new ConfigurationBuilder().Build();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Bot.Builder.Expressions.Parser;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
|
@ -10,7 +12,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
{
|
||||
private TestContext testContextInstance;
|
||||
|
||||
public static IEnumerable<object[]> InvalidExpressions => new[]
|
||||
public static IEnumerable<object[]> SyntaxErrorExpressions => new[]
|
||||
{
|
||||
Test("a+"),
|
||||
Test("a+b*"),
|
||||
|
@ -22,7 +24,16 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("user.lists.{dialog.listName}")
|
||||
};
|
||||
|
||||
public static object[] Test(string input) => new object[] { input };
|
||||
/// <summary>
|
||||
/// Gets or sets the test context which provides
|
||||
/// information about and functionality for the current test run.
|
||||
/// </summary>
|
||||
/// <value>The TestContext.</value>
|
||||
public TestContext TestContext
|
||||
{
|
||||
get { return testContextInstance; }
|
||||
set { testContextInstance = value; }
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> BadExpressions => new[]
|
||||
{
|
||||
|
@ -106,8 +117,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("lessOrEquals(one)"), // function need two parameters
|
||||
Test("equals(one)"), // equals must accept two parameters
|
||||
Test("exists(1, 2)"), // function need one parameter
|
||||
|
||||
// Test("if(!exists(one), one, hello)"), // the second and third parameters of if must the same type
|
||||
//Test("if(!exists(one), one, hello)"), // the second and third parameters of if must the same type
|
||||
Test("not(false, one)"), // function need one parameter
|
||||
#endregion
|
||||
|
||||
|
@ -121,23 +131,23 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("array(hello,world)"), // shold have 1 param
|
||||
Test("array(one)"), // shold have 1 param
|
||||
Test("DataUri(hello, world)"), // shoule have 1 param
|
||||
Test("DataUri(false)"), // should have string param
|
||||
Test("DataUri(false)"), //should have string param
|
||||
Test("uriComponent(hello, world)"), // shoule have 1 param
|
||||
Test("uriComponent(false)"), // should have string param
|
||||
Test("uriComponent(false)"), //should have string param
|
||||
Test("uriComponentToString(hello, world)"), // shoule have 1 param
|
||||
Test("uriComponentToString(false)"), // should have string param
|
||||
Test("uriComponentToString(false)"), //should have string param
|
||||
Test("dataUriToBinary(hello, world)"), // shoule have 1 param
|
||||
Test("dataUriToBinary(false)"), // should have string param
|
||||
Test("dataUriToBinary(false)"), //should have string param
|
||||
Test("dataUriToString(hello, world)"), // shoule have 1 param
|
||||
Test("dataUriToString(false)"), // should have string param
|
||||
Test("dataUriToString(false)"), //should have string param
|
||||
Test("binary(hello, world)"), // shoule have 1 param
|
||||
Test("binary(one)"), // should have string param
|
||||
Test("binary(one)"), //should have string param
|
||||
Test("base64(hello, world)"), // shoule have 1 param
|
||||
Test("base64(one)"), // should have string param
|
||||
Test("base64(one)"), //should have string param
|
||||
Test("base64ToBinary(hello, world)"), // shoule have 1 param
|
||||
Test("base64ToBinary(one)"), // should have string param
|
||||
Test("base64ToBinary(one)"), //should have string param
|
||||
Test("base64ToString(hello, world)"), // shoule have 1 param
|
||||
Test("base64ToString(false)"), // should have string param
|
||||
Test("base64ToString(false)"), //should have string param
|
||||
#endregion
|
||||
|
||||
#region Math functions test
|
||||
|
@ -168,7 +178,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("rand(7, 6)"), // minvalue cannot be greater than maxValue
|
||||
Test("sum(items)"), // should have number parameters
|
||||
Test("range(hello,one)"), // params should be integer
|
||||
Test("range(one,0)"), // the second param should be more than 0
|
||||
Test("range(one,0)"), //the second param should be more than 0
|
||||
#endregion
|
||||
|
||||
#region Date and time function test
|
||||
|
@ -193,19 +203,19 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("addSeconds(timestamp, 1,'yyyy', 2)"), // should have 2 or 3 params
|
||||
Test("addSeconds(notISOTimestamp, 1)"), // not ISO datetime format
|
||||
Test("dayOfMonth('errortime')"), // error datetime format
|
||||
Test("dayOfMonth(timestamp, 1)"), // should have 1 param
|
||||
Test("dayOfMonth(timestamp, 1)"), //should have 1 param
|
||||
Test("dayOfMonth(notISOTimestamp)"), // not ISO datetime format
|
||||
Test("dayOfWeek('errortime')"), // error datetime format
|
||||
Test("dayOfWeek(timestamp, 1)"), // should have 1 param
|
||||
Test("dayOfWeek(timestamp, 1)"), //should have 1 param
|
||||
Test("dayOfWeek(notISOTimestamp)"), // not ISO datetime format
|
||||
Test("dayOfYear('errortime')"), // error datetime format
|
||||
Test("dayOfYear(timestamp, 1)"), // should have 1 param
|
||||
Test("dayOfYear(timestamp, 1)"), //should have 1 param
|
||||
Test("dayOfYear(notISOTimestamp)"), // not ISO datetime format
|
||||
Test("month('errortime')"), // error datetime format
|
||||
Test("month(timestamp, 1)"), // should have 1 param
|
||||
Test("month(timestamp, 1)"), //should have 1 param
|
||||
Test("month(notISOTimestamp)"), // not ISO datetime format
|
||||
Test("date('errortime')"), // error datetime format
|
||||
Test("date(timestamp, 1)"), // should have 1 param
|
||||
Test("date(timestamp, 1)"), //should have 1 param
|
||||
Test("date(notISOTimestamp)"), // not ISO datetime format
|
||||
Test("year('errortime')"), // error datetime format
|
||||
Test("year(timestamp, 1)"), // should have 1 param
|
||||
|
@ -245,9 +255,9 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("convertToUTC(timestamp, timezone, 'D', hello)"), // should have 2 or 3 params
|
||||
Test("addToTime(notValidTimeStamp, one, 'day')"), // not valid timestamp
|
||||
Test("addToTime(timeStamp, hello, 'day')"), // interval should be integer
|
||||
Test("addToTime(timeStamp, one, 'decade', 'D')"), // not valid time unit
|
||||
Test("addToTime(timeStamp, one, 'week', 'A')"), // not valid format
|
||||
Test("addToTime(timeStamp, one, 'week', 'A', one)"), // should have 3 or 4 params
|
||||
Test("addToTime(timeStamp, one, 'decade', 'D')"), //not valid time unit
|
||||
Test("addToTime(timeStamp, one, 'week', 'A')"), //not valid format
|
||||
Test("addToTime(timeStamp, one, 'week', 'A', one)"), //should have 3 or 4 params
|
||||
Test("convertTimeZone(notValidTimeStamp, 'UTC', timezone)"), // not valid timestamp
|
||||
Test("convertTimeZone(timestamp2, invalidTimezone, timezone, 'D')"), // not valid source timezone
|
||||
Test("convertTimeZone(timestamp2, timezone, invalidTimezone, 'D')"), // not valid destination timezone
|
||||
|
@ -262,72 +272,72 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
#endregion
|
||||
|
||||
#region uri parsing function test
|
||||
Test("uriHost(relativeUri)"),
|
||||
Test("uriPath(relativeUri)"),
|
||||
Test("uriPathAndQuery(relativeUri)"),
|
||||
Test("uriPort(relativeUri)"),
|
||||
Test("uriQuery(relativeUri)"),
|
||||
Test("uriScheme(relativeUri)"),
|
||||
Test("uriHost(relatibeUri)"),
|
||||
Test("uriPath(relatibeUri)"),
|
||||
Test("uriPathAndQuery(relatibeUri)"),
|
||||
Test("uriPort(relatibeUri)"),
|
||||
Test("uriQuery(relatibeUri)"),
|
||||
Test("uriScheme(relatibeUri)"),
|
||||
#endregion
|
||||
|
||||
#region collection functions test
|
||||
Test("sum(items, 'hello')"), // should have 1 parameter
|
||||
Test("sum('hello')"), // first param should be list
|
||||
Test("average(items, 'hello')"), // should have 1 parameter
|
||||
Test("average('hello')"), // first param should be list
|
||||
Test("average(hello)"), // first param should be list
|
||||
Test("contains('hello world', 'hello', 'new')"), // should have 2 parameter
|
||||
Test("count(items, 1)"), // should have 1 parameter
|
||||
Test("count(1)"), // first param should be list or string
|
||||
Test("empty(1,2)"), // should have two params
|
||||
Test("first(items,2)"), // should have 1 param
|
||||
Test("last(items,2)"), // should have 1 param
|
||||
Test("join(items, 'p1', 'p2','p3')"), // builtin function should have 2-3 params,
|
||||
Test("sum(items, 'hello')"), //should have 1 parameter
|
||||
Test("sum('hello')"), //first param should be list
|
||||
Test("average(items, 'hello')"), //should have 1 parameter
|
||||
Test("average('hello')"), //first param should be list
|
||||
Test("average(hello)"), //first param should be list
|
||||
Test("contains('hello world', 'hello', 'new')"), //should have 2 parameter
|
||||
Test("count(items, 1)"), //should have 1 parameter
|
||||
Test("count(1)"), //first param should be list or string
|
||||
Test("empty(1,2)"), //should have two params
|
||||
Test("first(items,2)"), //should have 1 param
|
||||
Test("last(items,2)"), //should have 1 param
|
||||
Test("join(items, 'p1', 'p2','p3')"), //builtin function should have 2-3 params,
|
||||
Test("join(hello, 'hi')"), // first param must list
|
||||
Test("join(items, 1)"), // second param must string
|
||||
Test("join(items, '1', 2)"), // third param must string
|
||||
Test("foreach(hello, item, item)"), // first arg is not list
|
||||
Test("foreach(items, item)"), // should have three parameters
|
||||
Test("foreach(items, item, item2, item3)"), // should have three parameters
|
||||
Test("foreach(items, item)"), //should have three parameters
|
||||
Test("foreach(items, item, item2, item3)"), //should have three parameters
|
||||
Test("foreach(items, add(1), item)"), // Second paramter of foreach is not an identifier
|
||||
Test("foreach(items, 1, item)"), // Second paramter error
|
||||
Test("foreach(items, x, sum(x))"), // third paramter error
|
||||
Test("select(hello, item, item)"), // first arg is not list
|
||||
Test("select(items, item)"), // should have three parameters
|
||||
Test("select(items, item, item2, item3)"), // should have three parameters
|
||||
Test("select(items, item)"), //should have three parameters
|
||||
Test("select(items, item, item2, item3)"), //should have three parameters
|
||||
Test("select(items, add(1), item)"), // Second paramter of foreach is not an identifier
|
||||
Test("select(items, 1, item)"), // Second paramter error
|
||||
Test("select(items, x, sum(x))"), // third paramter error
|
||||
Test("where(hello, item, item)"), // first arg is not list
|
||||
Test("where(items, item)"), // should have three parameters
|
||||
Test("where(items, item, item2, item3)"), // should have three parameters
|
||||
Test("where(items, item)"), //should have three parameters
|
||||
Test("where(items, item, item2, item3)"), //should have three parameters
|
||||
Test("where(items, add(1), item)"), // Second paramter of where is not an identifier
|
||||
Test("where(items, 1, item)"), // Second paramter error
|
||||
Test("where(items, x, sum(x))"), // third paramter error
|
||||
Test("union(one, two)"), // should have collection param
|
||||
Test("intersection(one, two)"), // should have collection param
|
||||
Test("skip(one, two)"), // should have collection param
|
||||
Test("skip(items,-1)"), // the second parameter shoule not less than zero
|
||||
Test("skip(items,3)"), // the second parameter shoule less than the length of the collection
|
||||
Test("take(one, two)"), // should have collection param
|
||||
Test("skip(one, two)"), //should have collection param
|
||||
Test("skip(items,-1)"), //the second parameter shoule not less than zero
|
||||
Test("skip(items,3)"), //the second parameter shoule less than the length of the collection
|
||||
Test("take(one, two)"), //should have collection param
|
||||
Test("take(createArray('H','e','l','l','0'),items[5])"), // the second param expr is wrong
|
||||
Test("take(items,-1)"), // the second parameter shoule not less than zero
|
||||
Test("take(items,4)"), // the second parameter shoule less than the length of the collection
|
||||
Test("subArray(one,1,4)"), // should have collection param
|
||||
Test("subArray(items,-1,4)"), // the second parameter shoule not less than zero
|
||||
Test("subArray(items,1,4)"), // the second parameter shoule less than the length of the collection
|
||||
Test("subArray(createArray('H','e','l','l','o'),items[5],5)"), // the second parameter expression is invalid
|
||||
Test("subArray(createArray('H','e','l','l','o'),2,items[5])"), // the second parameter expression is invalid
|
||||
Test("take(items,-1)"), //the second parameter shoule not less than zero
|
||||
Test("take(items,4)"), //the second parameter shoule less than the length of the collection
|
||||
Test("subArray(one,1,4)"), //should have collection param
|
||||
Test("subArray(items,-1,4)"), //the second parameter shoule not less than zero
|
||||
Test("subArray(items,1,4)"), //the second parameter shoule less than the length of the collection
|
||||
Test("subArray(createArray('H','e','l','l','o'),items[5],5)"), //the second parameter expression is invalid
|
||||
Test("subArray(createArray('H','e','l','l','o'),2,items[5])"), //the second parameter expression is invalid
|
||||
#endregion
|
||||
|
||||
#region Object manipulation and construction functions test
|
||||
Test("json(1,2)"), // should have 1 parameter
|
||||
Test("json(1)"), // should be string parameter
|
||||
Test("json(1,2)"), //should have 1 parameter
|
||||
Test("json(1)"), //should be string parameter
|
||||
Test("json('{\"key1\":value1\"}')"), // invalid json format string
|
||||
Test("addProperty(json('{\"key1\":\"value1\"}'), 'key2','value2','key3')"), // should have 3 parameter
|
||||
Test("addProperty(json('{\"key1\":\"value1\"}'), 'key2','value2','key3')"), //should have 3 parameter
|
||||
Test("addProperty(json('{\"key1\":\"value1\"}'), 1,'value2')"), // second param should be string
|
||||
Test("addProperty(json('{\"key1\":\"value1\"}'), 'key1', 3)"), // cannot add existing property
|
||||
Test("setProperty(json('{\"key1\":\"value1\"}'), 'key2','value2','key3')"), // should have 3 parameter
|
||||
Test("setProperty(json('{\"key1\":\"value1\"}'), 'key2','value2','key3')"), //should have 3 parameter
|
||||
Test("setProperty(json('{\"key1\":\"value1\"}'), 1,'value2')"), // second param should be string
|
||||
Test("removeProperty(json('{\"key1\":\"value1\",\"key2\":\"value2\"}'), 1))"), // second param should be string
|
||||
Test("removeProperty(json('{\"key1\":\"value1\",\"key2\":\"value2\"}'), '1', '2'))"), // should have 2 parameters
|
||||
|
@ -369,24 +379,12 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
#endregion
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the test context which provides
|
||||
/// information about and functionality for the current test run.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The test context which provides
|
||||
/// information about and functionality for the current test run.
|
||||
/// </value>
|
||||
public TestContext TestContext
|
||||
{
|
||||
get { return testContextInstance; }
|
||||
set { testContextInstance = value; }
|
||||
}
|
||||
public static object[] Test(string input) => new object[] { input };
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(InvalidExpressions))]
|
||||
[ExpectedException(typeof(Exception))]
|
||||
public void Parse(string exp)
|
||||
[DynamicData(nameof(SyntaxErrorExpressions))]
|
||||
[ExpectedException(typeof(SyntaxErrorException))]
|
||||
public void ParseSyntaxErrors(string exp)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -395,7 +393,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
catch (Exception e)
|
||||
{
|
||||
TestContext.WriteLine(e.Message);
|
||||
throw e;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.Bot.Builder.Expressions.Parser;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Expressions.Tests
|
||||
|
@ -308,6 +309,12 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("count(concat(hello,world))", 10),
|
||||
Test("replace('hello', 'l', 'k')", "hekko"),
|
||||
Test("replace('hello', 'L', 'k')", "hello"),
|
||||
Test("replace(\"hello'\", \"'\", '\"')", "hello\""),
|
||||
Test("replace('hello\"', '\"', \"'\")", "hello'"),
|
||||
Test("replace('hello\"', '\"', '\n')", "hello\n"),
|
||||
Test("replace('hello\n', '\n', '\\\\')", "hello\\"),
|
||||
Test(@"replace('hello\\', '\\', '\\\\')", @"hello\\"),
|
||||
Test(@"replace('hello\n', '\n', '\\\\')", @"hello\\"),
|
||||
Test("replaceIgnoreCase('hello', 'L', 'k')", "hekko"),
|
||||
Test("split('hello','e')", new string[] { "h", "llo" }),
|
||||
Test("substring('hello', 0, 5)", "hello"),
|
||||
|
@ -335,21 +342,21 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("addOrdinal(11 + 11)", "22nd"),
|
||||
Test("addOrdinal(11 + 12)", "23rd"),
|
||||
Test("addOrdinal(11 + 13)", "24th"),
|
||||
Test("addOrdinal(-1)", "-1"), // original string value
|
||||
Test("addOrdinal(-1)", "-1"), //original string value
|
||||
|
||||
#endregion
|
||||
|
||||
#region Logical comparison functions test
|
||||
Test("and(1 == 1, 1 < 2, 1 > 2)", false),
|
||||
Test("and(!true, !!true)", false), // false && true
|
||||
Test("and(!!true, !!true)", true), // true && true
|
||||
Test("and(hello != 'world', bool('true'))", true), // true && true
|
||||
Test("and(hello == 'world', bool('true'))", false), // false && true
|
||||
Test("or(!exists(one), !!exists(one))", true), // false && true
|
||||
Test("or(!exists(one), !exists(one))", false), // false && false
|
||||
Test("and(!true, !!true)", false), //false && true
|
||||
Test("and(!!true, !!true)", true), //true && true
|
||||
Test("and(hello != 'world', bool('true'))", true), //true && true
|
||||
Test("and(hello == 'world', bool('true'))", false), //false && true
|
||||
Test("or(!exists(one), !!exists(one))", true), //false && true
|
||||
Test("or(!exists(one), !exists(one))", false), //false && false
|
||||
Test("greater(one, two)", false, OneTwo),
|
||||
Test("greater(one , 0.5) && less(two , 2.5)", true), // true && true
|
||||
Test("greater(one , 0.5) || less(two , 1.5)", true), // true || false
|
||||
Test("greater(one , 0.5) || less(two , 1.5)", true), //true || false
|
||||
Test("greater(5, 2)", true),
|
||||
Test("greater(2, 2)", false),
|
||||
Test("greater(one, two)", false),
|
||||
|
@ -376,13 +383,18 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("equals(hello, 'hello')", true),
|
||||
Test("equals(bag.index, 3)", true),
|
||||
Test("equals(bag.index, 2)", false),
|
||||
Test("equals(hello == 'world', bool('true'))", false), // false, true
|
||||
Test("equals(hello == 'world', bool(0))", false), // false, true
|
||||
Test("if(!exists(one), 'r1', 'r2')", "r2"), // false
|
||||
Test("if(!!exists(one), 'r1', 'r2')", "r1"), // true
|
||||
Test("if(0, 'r1', 'r2')", "r1"), // true
|
||||
Test("if(bool('true'), 'r1', 'r2')", "r1"), // true
|
||||
Test("if(istrue, 'r1', 'r2')", "r1"), // true
|
||||
Test("equals(hello == 'world', bool('true'))", false), //false, true
|
||||
Test("equals(hello == 'world', bool(0))", false), //false, true
|
||||
Test("if(!exists(one), 'r1', 'r2')", "r2"), //false
|
||||
Test("if(!!exists(one), 'r1', 'r2')", "r1"), //true
|
||||
Test("if(0, 'r1', 'r2')", "r1"), //true
|
||||
Test("if(bool('true'), 'r1', 'r2')", "r1"), //true
|
||||
Test("if(istrue, 'r1', 'r2')", "r1"), //true
|
||||
Test("if(bag.name == null, \"hello\", bag.name)", "mybag"),
|
||||
Test("if(user.name == null, \"hello\", user.name)", "hello"), // user.name don't exist
|
||||
Test("if(user.name == null, '', user.name)", string.Empty), // user.name don't exist
|
||||
Test("if(one > 0, one, two)", 1),
|
||||
Test("if(one < 0, one, two)", 2),
|
||||
Test("exists(one)", true),
|
||||
Test("exists(xxx)", false),
|
||||
Test("exists(one.xxx)", false),
|
||||
|
@ -465,8 +477,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
#endregion
|
||||
|
||||
#region Date and time function test
|
||||
|
||||
// init dateTime: 2018-03-15T13:00:00Z
|
||||
//init dateTime: 2018-03-15T13:00:00Z
|
||||
Test("addDays(timestamp, 1)", "2018-03-16T13:00:00.000Z"),
|
||||
Test("addDays(timestamp, 1,'MM-dd-yy')", "03-16-18"),
|
||||
Test("addHours(timestamp, 1)", "2018-03-15T14:00:00.000Z"),
|
||||
|
@ -476,10 +487,10 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("addSeconds(timestamp, 1)", "2018-03-15T13:00:01.000Z"),
|
||||
Test("addSeconds(timestamp, 1, 'MM-dd-yy hh-mm-ss')", "03-15-18 01-00-01"),
|
||||
Test("dayOfMonth(timestamp)", 15),
|
||||
Test("dayOfWeek(timestamp)", 4), // Thursday
|
||||
Test("dayOfWeek(timestamp)", 4), //Thursday
|
||||
Test("dayOfYear(timestamp)", 74),
|
||||
Test("month(timestamp)", 3),
|
||||
Test("date(timestamp)", "3/15/2018"), // Default. TODO
|
||||
Test("date(timestamp)", "3/15/2018"), //Default. TODO
|
||||
Test("year(timestamp)", 2018),
|
||||
Test("length(utcNow())", 24),
|
||||
Test("utcNow('MM-DD-YY')", DateTime.UtcNow.ToString("MM-DD-YY")),
|
||||
|
@ -624,7 +635,6 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("$x", 3),
|
||||
Test("$y", 2),
|
||||
Test("$z", 1),
|
||||
|
||||
// Test("^x", 3),
|
||||
// Test("^y", 2),
|
||||
// Test("^z", 1),
|
||||
|
@ -683,17 +693,17 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
public static object[] Test(string input, object value, HashSet<string> paths = null) => new object[] { input, value, paths };
|
||||
|
||||
public static bool IsNumber(object value) =>
|
||||
value is sbyte
|
||||
|| value is byte
|
||||
|| value is short
|
||||
|| value is ushort
|
||||
|| value is int
|
||||
|| value is uint
|
||||
|| value is long
|
||||
|| value is ulong
|
||||
|| value is float
|
||||
|| value is double
|
||||
|| value is decimal;
|
||||
value is sbyte
|
||||
|| value is byte
|
||||
|| value is short
|
||||
|| value is ushort
|
||||
|| value is int
|
||||
|| value is uint
|
||||
|| value is long
|
||||
|| value is ulong
|
||||
|| value is float
|
||||
|| value is double
|
||||
|| value is decimal;
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(Data))]
|
||||
|
|
|
@ -5,3 +5,35 @@
|
|||
|
||||
# otherEscape
|
||||
- Hi \y \
|
||||
|
||||
# escapeInExpression
|
||||
- Hi {replace('hello\\', '\\', '\\\\')}
|
||||
|
||||
# escapeInExpression2
|
||||
- Hi {replace('hello\"', '\"', "'")}
|
||||
|
||||
# escapeInExpression3
|
||||
- Hi {replace("hello'", "'", '\"')}
|
||||
|
||||
# escapeInExpression4
|
||||
- Hi {replace("hello\n", "\n", '\"')}
|
||||
|
||||
# escapeInExpression5
|
||||
- Hi {replace('hello\"', '\"', '\n')}
|
||||
|
||||
# escapeInExpression6
|
||||
- Hi {replace("hello'", "'", '\n')}
|
||||
|
||||
# showTodo(todos)
|
||||
- IF: {count(todos) > 0}
|
||||
- ```
|
||||
Your most recent @{count(todos)} tasks are
|
||||
@{join(foreach(todos, x, showSingleTodo(x)), '\n')}
|
||||
```
|
||||
- ELSE:
|
||||
- ```
|
||||
You don't have any "@{replace(replace('t\\odo\"', '\"', "'"), '\\', '\\\\')}".
|
||||
```
|
||||
|
||||
# showSingleTodo(x)
|
||||
- * {x}
|
||||
|
|
|
@ -275,6 +275,31 @@ namespace Microsoft.Bot.Builder.AI.LanguageGeneration.Tests
|
|||
|
||||
evaled = engine.EvaluateTemplate("otherEscape", null);
|
||||
Assert.AreEqual(evaled, @"Hi \y \");
|
||||
|
||||
evaled = engine.EvaluateTemplate("escapeInExpression", null);
|
||||
Assert.AreEqual(evaled, "Hi hello\\\\");
|
||||
|
||||
evaled = engine.EvaluateTemplate("escapeInExpression2", null);
|
||||
Assert.AreEqual(evaled, "Hi hello'");
|
||||
|
||||
evaled = engine.EvaluateTemplate("escapeInExpression3", null);
|
||||
Assert.AreEqual(evaled, "Hi hello\"");
|
||||
|
||||
evaled = engine.EvaluateTemplate("escapeInExpression4", null);
|
||||
Assert.AreEqual(evaled, "Hi hello\"");
|
||||
|
||||
evaled = engine.EvaluateTemplate("escapeInExpression5", null);
|
||||
Assert.AreEqual(evaled, "Hi hello\n");
|
||||
|
||||
evaled = engine.EvaluateTemplate("escapeInExpression6", null);
|
||||
Assert.AreEqual(evaled, "Hi hello\n");
|
||||
|
||||
var todos = new[] { "A", "B", "C" };
|
||||
evaled = engine.EvaluateTemplate("showTodo", new { todos });
|
||||
Assert.AreEqual(evaled, Environment.NewLine + " Your most recent 3 tasks are" + Environment.NewLine + " * A\n* B\n* C" + Environment.NewLine + " ");
|
||||
|
||||
evaled = engine.EvaluateTemplate("showTodo", null);
|
||||
Assert.AreEqual(evaled, Environment.NewLine + " You don't have any \"t\\\\odo'\"." + Environment.NewLine + " ");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -564,30 +589,6 @@ namespace Microsoft.Bot.Builder.AI.LanguageGeneration.Tests
|
|||
Assert.AreEqual("You have 2 alarms, they are 8 pm of tomorrow", evaled[1]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestExpandTemplateWithRefInForeach()
|
||||
{
|
||||
var engine = new TemplateEngine().AddFile(GetExampleFilePath("Expand.lg"));
|
||||
|
||||
var alarms = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
time = "7 am",
|
||||
date = "tomorrow"
|
||||
},
|
||||
new
|
||||
{
|
||||
time = "8 pm",
|
||||
date = "tomorrow"
|
||||
}
|
||||
};
|
||||
|
||||
var evaled = engine.ExpandTemplate("ShowAlarmsWithForeach", new { alarms = alarms });
|
||||
Assert.AreEqual(1, evaled.Count);
|
||||
Assert.AreEqual("You have 2 alarms, 7 am at tomorrow and 8 pm at tomorrow", evaled[0]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestExpandTemplateWithRefInMultiLine()
|
||||
{
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace Microsoft.Bot.Builder.AI.LanguageGeneration.Tests
|
|||
{
|
||||
var engine = new TemplateEngine().AddFile(GetExampleFilePath(input));
|
||||
|
||||
var report = StaticChecker.CheckTemplates(engine.Templates);
|
||||
var report = new StaticChecker().CheckTemplates(engine.Templates);
|
||||
|
||||
TestContext.WriteLine(string.Join("\n", report));
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
},
|
||||
{
|
||||
"$type": "Microsoft.SendActivity",
|
||||
"activity": "Done! You have added a pet named \"{dialog.postResponse.name}\" with id \"{dialog.postResponse.id}\""
|
||||
"activity": "Done! You have added a pet named \"{dialog.postResponse.content.name}\" with id \"{dialog.postResponse.content.id}\""
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.TextInput",
|
||||
|
@ -65,7 +65,7 @@
|
|||
},
|
||||
{
|
||||
"$type": "Microsoft.SendActivity",
|
||||
"activity": "Great! I found your pet named \"{dialog.getResponse.name}\""
|
||||
"activity": "Great! I found your pet named \"{dialog.getResponse.content.name}\""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Show
|
||||
- You have following issues : \n {join(foreach(dialog.getResponse, x, showSingleUrl(x)), '\n')}
|
||||
- You have following issues : \n {join(foreach(dialog.getResponse.content, x, showSingleUrl(x)), '\n')}
|
||||
|
||||
# showSingleUrl(x)
|
||||
- ```
|
||||
|
@ -14,7 +14,7 @@
|
|||
"type": "TextBlock",
|
||||
"size": "Medium",
|
||||
"weight": "Bolder",
|
||||
"text": "@{x.title}"
|
||||
"text": "@{replace(replace(x.title, '\"', "'"), '\\', '\\\\')}"
|
||||
},
|
||||
{
|
||||
"type": "ColumnSet",
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"activity": "Your age is: {user.age}"
|
||||
},
|
||||
{
|
||||
"$type": "Testbot.JavascriptStep",
|
||||
"$type": "Testbot.JavascriptAction",
|
||||
"script": "Samples/13 - CustomStep/dogyears.js",
|
||||
"inputBindings": {
|
||||
"age": "user.age"
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
{
|
||||
"$type": "Microsoft.IfCondition",
|
||||
"condition": "!contains({user.email}, '@')",
|
||||
"condition": "!contains(user.email, '@')",
|
||||
"actions": [
|
||||
"CalendarFindSingleContact"
|
||||
]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"$type": "Microsoft.OnBeginDialog",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your calendar account",
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your calendar account",
|
||||
|
@ -30,7 +30,7 @@
|
|||
}
|
||||
//{
|
||||
// "$type": "Microsoft.SendActivity",
|
||||
// "activity": "response: {user.acceptResponse}"
|
||||
// "activity": "response: {user.acceptResponse.content}"
|
||||
//}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your calendar account",
|
||||
|
@ -58,7 +58,7 @@
|
|||
}
|
||||
//{
|
||||
// "$type": "Microsoft.SendActivity",
|
||||
// "activity": "response: {user.createResponse}"
|
||||
// "activity": "response: {user.createResponse.content}"
|
||||
//}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your calendar account",
|
||||
|
@ -30,7 +30,7 @@
|
|||
},
|
||||
{
|
||||
"$type": "Microsoft.SendActivity",
|
||||
"activity": "response: {user.declineResponse}"
|
||||
"activity": "response: {user.declineResponse.content}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
{
|
||||
"$schema": "../../../../app.schema",
|
||||
"$type": "Microsoft.AdaptiveDialog",
|
||||
"events": [
|
||||
{
|
||||
"$type": "Microsoft.OnBeginDialog",
|
||||
"actions": [
|
||||
"$schema": "../../../../app.schema",
|
||||
"$type": "Microsoft.AdaptiveDialog",
|
||||
"events": [
|
||||
{
|
||||
"$type": "Microsoft.IfCondition",
|
||||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"connectionName": "msgraph",
|
||||
"title": "Log in",
|
||||
"text": "Please log in to your Microsoft account",
|
||||
"property": "dialog.token"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.HttpRequest",
|
||||
"url": "https://graph.microsoft.com/v1.0/me/contacts?$filter=startswith(displayName,'{user.email}')",
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {dialog.token.Token}"
|
||||
},
|
||||
"property": "dialog.getResponse"
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.SendActivity",
|
||||
"activity": "The contact you find is {dialog.getResponse.value[0].displayName}, email address is {dialog.getResponse.value[0].emailAddresses[0].address}."
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.SetProperty",
|
||||
"value": "dialog.getResponse.value[0].emailAddresses[0].address",
|
||||
"property": "user.email"
|
||||
"$type": "Microsoft.OnBeginDialog",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.IfCondition",
|
||||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"connectionName": "msgraph",
|
||||
"title": "Log in",
|
||||
"text": "Please log in to your Microsoft account",
|
||||
"property": "dialog.token"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.HttpRequest",
|
||||
"url": "https://graph.microsoft.com/v1.0/me/contacts?$filter=startswith(displayName,'{user.email}')",
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {dialog.token.Token}"
|
||||
},
|
||||
"property": "dialog.getResponse"
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.SendActivity",
|
||||
"activity": "The contact you find is {dialog.getResponse.content.value[0].displayName}, email address is {dialog.getResponse.content.value[0].emailAddresses[0].address}."
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.SetProperty",
|
||||
"value": "dialog.getResponse.content.value[0].emailAddresses[0].address",
|
||||
"property": "user.email"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,32 +1,32 @@
|
|||
{
|
||||
"$schema": "../../app.schema",
|
||||
"$type": "Microsoft.AdaptiveDialog",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.IfCondition",
|
||||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
"$schema": "../../app.schema",
|
||||
"$type": "Microsoft.AdaptiveDialog",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your calendar account",
|
||||
"Property": "dialog.token"
|
||||
"$type": "Microsoft.IfCondition",
|
||||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your calendar account",
|
||||
"Property": "dialog.token"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.HttpRequest",
|
||||
"url": "https://graph.microsoft.com/v1.0/me/calendarview?startdatetime={utcNow()}&enddatetime={addDays(utcNow(), 1)}",
|
||||
"method": "GET",
|
||||
"header": {
|
||||
"Authorization": "Bearer {dialog.token.Token}"
|
||||
},
|
||||
"Property": "user.getGraphMeetings"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.HttpRequest",
|
||||
"url": "https://graph.microsoft.com/v1.0/me/calendarview?startdatetime={utcNow()}&enddatetime={addDays(utcNow(), 1)}",
|
||||
"method": "GET",
|
||||
"header": {
|
||||
"Authorization": "Bearer {dialog.token.Token}"
|
||||
},
|
||||
"Property": "user.getGraphMeetings"
|
||||
}
|
||||
//,{
|
||||
// "$type": "Microsoft.SendActivity",
|
||||
// "activity": "{user.getGraphMeetings}"
|
||||
//}
|
||||
]
|
||||
//,{
|
||||
// "$type": "Microsoft.SendActivity",
|
||||
// "activity": "{user.getGraphMeetings.content}"
|
||||
//}
|
||||
]
|
||||
}
|
|
@ -1,44 +1,44 @@
|
|||
{
|
||||
"$schema": "../../app.schema",
|
||||
"$type": "Microsoft.AdaptiveDialog",
|
||||
"actions": [
|
||||
"actions": [
|
||||
|
||||
{
|
||||
"$type": "Microsoft.IfCondition",
|
||||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your calendar account",
|
||||
"Property": "dialog.token"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"$type": "Microsoft.HttpRequest",
|
||||
"url": "https://graph.microsoft.com/v1.0/me/events/{user.focusedMeeting.id}",
|
||||
"method": "PATCH",
|
||||
"header": {
|
||||
"Authorization": "Bearer {dialog.token.Token}"
|
||||
},
|
||||
"body": {
|
||||
"start": {
|
||||
"dateTime": "{user.startDateTime}",
|
||||
"timeZone": "UTC"
|
||||
"$type": "Microsoft.IfCondition",
|
||||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your calendar account",
|
||||
"Property": "dialog.token"
|
||||
}
|
||||
]
|
||||
},
|
||||
"end": {
|
||||
"dateTime": "{user.endDateTime}",
|
||||
"timeZone": "UTC"
|
||||
|
||||
{
|
||||
"$type": "Microsoft.HttpRequest",
|
||||
"url": "https://graph.microsoft.com/v1.0/me/events/{user.focusedMeeting.id}",
|
||||
"method": "PATCH",
|
||||
"header": {
|
||||
"Authorization": "Bearer {dialog.token.Token}"
|
||||
},
|
||||
"body": {
|
||||
"start": {
|
||||
"dateTime": "{user.startDateTime}",
|
||||
"timeZone": "UTC"
|
||||
},
|
||||
"end": {
|
||||
"dateTime": "{user.endDateTime}",
|
||||
"timeZone": "UTC"
|
||||
}
|
||||
},
|
||||
"Property": "user.updateResponse"
|
||||
}
|
||||
},
|
||||
"Property": "user.updateResponse"
|
||||
}
|
||||
//{
|
||||
// "$type": "Microsoft.SendActivity",
|
||||
// "activity": "response: {user.updateResponse}"
|
||||
//}
|
||||
]
|
||||
//{
|
||||
// "$type": "Microsoft.SendActivity",
|
||||
// "activity": "response: {user.updateResponse.content}"
|
||||
//}
|
||||
]
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your email account",
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
{
|
||||
"$schema": "../../app.schema",
|
||||
"$type": "Microsoft.AdaptiveDialog",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.IfCondition",
|
||||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
"$schema": "../../app.schema",
|
||||
"$type": "Microsoft.AdaptiveDialog",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your email account",
|
||||
"Property": "dialog.token"
|
||||
"$type": "Microsoft.IfCondition",
|
||||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your email account",
|
||||
"Property": "dialog.token"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.HttpRequest",
|
||||
"url": "https://graph.microsoft.com/v1.0/me/contacts?$filter=startswith(displayName,'{user.email}')",
|
||||
"method": "GET",
|
||||
"header": {
|
||||
"Authorization": "Bearer {dialog.token.Token}"
|
||||
},
|
||||
"Property": "dialog.getResponse"
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.SendActivity",
|
||||
"activity": "The contact you find is {dialog.getResponse.content.value[0].displayName}, email address is {dialog.getResponse.content.value[0].emailAddresses[0].address}."
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.SetProperty",
|
||||
"value": "dialog.getResponse.content.value[0].emailAddresses[0].address",
|
||||
"property": "user.email"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.HttpRequest",
|
||||
"url": "https://graph.microsoft.com/v1.0/me/contacts?$filter=startswith(displayName,'{user.email}')",
|
||||
"method": "GET",
|
||||
"header": {
|
||||
"Authorization": "Bearer {dialog.token.Token}"
|
||||
},
|
||||
"Property": "dialog.getResponse"
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.SendActivity",
|
||||
"activity": "The contact you find is {dialog.getResponse.value[0].displayName}, email address is {dialog.getResponse.value[0].emailAddresses[0].address}."
|
||||
},
|
||||
{
|
||||
"$type": "Microsoft.SetProperty",
|
||||
"value": "dialog.getResponse.value[0].emailAddresses[0].address",
|
||||
"property": "user.email"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your email account",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your email account",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"condition": "dialog.token == null",
|
||||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.OAuthPrompt",
|
||||
"$type": "Microsoft.OAuthInput",
|
||||
"ConnectionName": "msgraph",
|
||||
"Title": "Log in",
|
||||
"Text": "Please log in to your email account",
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.InitProperty",
|
||||
"property": "user.lists.{dialog.listName}",
|
||||
"property": "user.lists[dialog.listName]",
|
||||
"type": "array"
|
||||
}
|
||||
]
|
||||
|
@ -108,7 +108,7 @@
|
|||
{
|
||||
"$type": "Microsoft.EditArray",
|
||||
"changeType": "Push",
|
||||
"arrayProperty": "user.lists.{dialog.listName}",
|
||||
"arrayProperty": "user.lists[dialog.listName]",
|
||||
"value": "dialog.item"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
"actions": [
|
||||
{
|
||||
"$type": "Microsoft.InitProperty",
|
||||
"property": "user.lists.{dialog.listName}",
|
||||
"property": "user.lists[dialog.listName]",
|
||||
"type": "array"
|
||||
}
|
||||
]
|
||||
|
@ -108,7 +108,7 @@
|
|||
{
|
||||
"$type": "Microsoft.EditArray",
|
||||
"changeType": "Remove",
|
||||
"arrayProperty": "user.lists.{dialog.listName}",
|
||||
"arrayProperty": "user.lists[dialog.listName]",
|
||||
"value": "dialog.item"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
@ -11,10 +14,14 @@ using Microsoft.Bot.Builder.Dialogs.Adaptive;
|
|||
using Microsoft.Bot.Builder.Dialogs.Adaptive.Actions;
|
||||
using Microsoft.Bot.Builder.Dialogs.Adaptive.Events;
|
||||
using Microsoft.Bot.Builder.Dialogs.Adaptive.Input;
|
||||
using Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers;
|
||||
using Microsoft.Bot.Builder.Dialogs.Choices;
|
||||
using Microsoft.Bot.Builder.Dialogs.Debugging;
|
||||
using Microsoft.Bot.Builder.Dialogs.Declarative;
|
||||
using Microsoft.Bot.Builder.Dialogs.Declarative.Resources;
|
||||
using Microsoft.Bot.Builder.Expressions.Parser;
|
||||
using Microsoft.Bot.Schema;
|
||||
using static Microsoft.Bot.Builder.Dialogs.Debugging.Source;
|
||||
|
||||
namespace Microsoft.Bot.Builder.TestBot.Json
|
||||
{
|
||||
|
@ -69,10 +76,21 @@ namespace Microsoft.Bot.Builder.TestBot.Json
|
|||
|
||||
foreach (var resource in this.resourceExplorer.GetResources(".dialog").Where(r => r.Id.EndsWith(".main.dialog")))
|
||||
{
|
||||
var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(resource.Id));
|
||||
choiceInput.Choices.Add(new Choice(name));
|
||||
var dialog = DeclarativeTypeLoader.Load<IDialog>(resource, this.resourceExplorer, DebugSupport.SourceRegistry);
|
||||
handleChoice.Cases.Add(new Case($"{name}", new List<IDialog>() { dialog }));
|
||||
try
|
||||
{
|
||||
var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(resource.Id));
|
||||
choiceInput.Choices.Add(new Choice(name));
|
||||
var dialog = DeclarativeTypeLoader.Load<IDialog>(resource, this.resourceExplorer, DebugSupport.SourceRegistry);
|
||||
handleChoice.Cases.Add(new Case($"{name}", new List<IDialog>() { dialog }));
|
||||
}
|
||||
catch (SyntaxErrorException err)
|
||||
{
|
||||
Trace.TraceError($"{err.Source}: Error: {err.Message}");
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
Trace.TraceError(err.Message);
|
||||
}
|
||||
}
|
||||
|
||||
choiceInput.Style = ListStyle.Auto;
|
||||
|
|
|
@ -281,9 +281,9 @@
|
|||
"$ref": "#/definitions/Microsoft.TrueSelector"
|
||||
},
|
||||
{
|
||||
"title": "Testbot.JavascriptStep",
|
||||
"title": "Testbot.JavascriptAction",
|
||||
"description": "This gives you the ability to execute javascript to manipulate memory",
|
||||
"$ref": "#/definitions/Testbot.JavascriptStep"
|
||||
"$ref": "#/definitions/Testbot.JavascriptAction"
|
||||
},
|
||||
{
|
||||
"title": "Testbot.Multiply",
|
||||
|
@ -500,6 +500,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -879,6 +888,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -1247,6 +1265,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -1486,6 +1513,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -2534,7 +2570,7 @@
|
|||
"property": {
|
||||
"$role": "expression",
|
||||
"title": "Property",
|
||||
"description": "The property to store the result of the HTTP call in (as object or string)",
|
||||
"description": "The property to store the result of the HTTP call in. The result will have 4 properties from the http response: statusCode|reasonPhrase|content|headers. If the content is json it will be an deserialized object, otherwise it will be a string",
|
||||
"examples": [
|
||||
"dialog.contosodata"
|
||||
],
|
||||
|
@ -2755,9 +2791,9 @@
|
|||
"title": "string"
|
||||
},
|
||||
{
|
||||
"title": "Testbot.JavascriptStep",
|
||||
"title": "Testbot.JavascriptAction",
|
||||
"description": "This gives you the ability to execute javascript to manipulate memory",
|
||||
"$ref": "#/definitions/Testbot.JavascriptStep"
|
||||
"$ref": "#/definitions/Testbot.JavascriptAction"
|
||||
},
|
||||
{
|
||||
"title": "Testbot.Multiply",
|
||||
|
@ -3544,6 +3580,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -3722,6 +3767,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -5733,6 +5787,15 @@
|
|||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"defaultValueResponse": {
|
||||
"$type": "Microsoft.IActivityTemplate",
|
||||
"title": "Default Value Response",
|
||||
"description": "The message to send to when max turn count has been exceeded and the default value is selected as the value.",
|
||||
"examples": [
|
||||
"I didn't understand your responses, so I will just use the default value of 10. Let me know if you want to change it."
|
||||
],
|
||||
"$ref": "#/definitions/Microsoft.IActivityTemplate"
|
||||
},
|
||||
"maxTurnCount": {
|
||||
"type": "integer",
|
||||
"title": "Max Turn Count",
|
||||
|
@ -5970,7 +6033,7 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"Testbot.JavascriptStep": {
|
||||
"Testbot.JavascriptAction": {
|
||||
"$role": "unionType(Microsoft.IDialog)",
|
||||
"title": "Javascript Action",
|
||||
"description": "This gives you the ability to execute javascript to manipulate memory",
|
||||
|
@ -5982,7 +6045,7 @@
|
|||
"description": "Defines the valid properties for the component you are configuring (from a dialog .schema file)",
|
||||
"type": "string",
|
||||
"pattern": "^[a-zA-Z][a-zA-Z0-9.]*$",
|
||||
"const": "Testbot.JavascriptStep"
|
||||
"const": "Testbot.JavascriptAction"
|
||||
},
|
||||
"$copy": {
|
||||
"title": "$copy",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@echo off
|
||||
|
||||
erase app.schema
|
||||
dialogSchema ../../libraries/**/*.schema ./**/*.schema -o app.schema
|
||||
dialogschema ../../libraries/**/*.schema ./**/*.schema -o app.schema
|
Загрузка…
Ссылка в новой задаче