Merge master-> streaming
158
.editorconfig
|
@ -34,6 +34,7 @@ charset = utf-8-bom
|
|||
[*.{cs,vb}]
|
||||
# Organize usings
|
||||
dotnet_sort_system_directives_first = true
|
||||
dotnet_separate_import_directive_groups = false
|
||||
|
||||
# this. preferences
|
||||
dotnet_style_qualification_for_field = false:suggestion
|
||||
|
@ -45,6 +46,11 @@ dotnet_style_qualification_for_event = false:suggestion
|
|||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||
|
||||
# Parentheses preferences
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
|
||||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
|
||||
# Modifier preferences
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
|
||||
dotnet_style_readonly_field = true:suggestion
|
||||
|
@ -52,8 +58,6 @@ dotnet_style_readonly_field = true:suggestion
|
|||
# Expression-level preferences
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
|
@ -61,24 +65,26 @@ dotnet_style_prefer_is_null_check_over_reference_equality_method = true:none
|
|||
dotnet_prefer_inferred_tuple_names = true:suggestion
|
||||
dotnet_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||
dotnet_style_prefer_auto_properties = true:suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||
|
||||
###############################
|
||||
# Naming Conventions #
|
||||
###############################
|
||||
|
||||
# Style Definitions
|
||||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||
|
||||
# Use PascalCase for constant fields
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
|
||||
dotnet_naming_symbols.constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
|
||||
dotnet_naming_symbols.constant_fields.required_modifiers = const
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
|
||||
dotnet_naming_symbols.constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
|
||||
dotnet_naming_symbols.constant_fields.required_modifiers = const
|
||||
|
||||
###############################
|
||||
# C# Coding Conventions #
|
||||
# C# Code Style Rules #
|
||||
###############################
|
||||
[*.cs]
|
||||
# var preferences
|
||||
|
@ -87,14 +93,14 @@ csharp_style_var_when_type_is_apparent = true:suggestion
|
|||
csharp_style_var_elsewhere = true:suggestion
|
||||
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_methods = true:suggestion
|
||||
csharp_style_expression_bodied_methods = false:none
|
||||
csharp_style_expression_bodied_constructors = false:none
|
||||
csharp_style_expression_bodied_operators = true:suggestion
|
||||
csharp_style_expression_bodied_properties = true:suggestion
|
||||
csharp_style_expression_bodied_indexers = true:suggestion
|
||||
csharp_style_expression_bodied_accessors = true:suggestion
|
||||
|
||||
# Pattern matching preferences
|
||||
# Pattern-matching preferences
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
|
||||
|
@ -125,132 +131,8 @@ csharp_new_line_before_members_in_anonymous_types = true
|
|||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
# Indentation preferences
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_labels = flush_left
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
|
||||
# Expression-level preferences
|
||||
csharp_prefer_braces = true:none
|
||||
csharp_style_deconstructed_variable_declaration = true:suggestion
|
||||
csharp_prefer_simple_default_expression = true:suggestion
|
||||
csharp_style_pattern_local_over_anonymous_function = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
|
||||
###############################
|
||||
# C# Formatting Rules #
|
||||
###############################
|
||||
# New line preferences
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
# Indentation preferences
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_labels = flush_left
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_style_expression_bodied_indexers = true:none
|
||||
csharp_style_expression_bodied_accessors = true:none
|
||||
|
||||
# Pattern matching preferences
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
|
||||
# Null-checking preferences
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
|
||||
# Modifier preferences
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
|
||||
|
||||
# Expression-level preferences
|
||||
csharp_prefer_braces = true:none
|
||||
csharp_style_deconstructed_variable_declaration = true:suggestion
|
||||
csharp_prefer_simple_default_expression = true:suggestion
|
||||
csharp_style_pattern_local_over_anonymous_function = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
|
||||
###############################
|
||||
# C# Formatting Rules #
|
||||
###############################
|
||||
# New line preferences
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
# Indentation preferences
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_labels = flush_left
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
|
||||
# Expression-level preferences
|
||||
csharp_prefer_braces = true:none
|
||||
csharp_style_deconstructed_variable_declaration = true:suggestion
|
||||
csharp_prefer_simple_default_expression = true:suggestion
|
||||
csharp_style_pattern_local_over_anonymous_function = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
|
||||
###############################
|
||||
# C# Formatting Rules #
|
||||
###############################
|
||||
# New line preferences
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
# Indentation preferences
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_labels = flush_left
|
||||
|
||||
# Space preferences
|
||||
|
@ -265,6 +147,8 @@ csharp_space_around_binary_operators = before_and_after
|
|||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_after_dot = false
|
||||
|
||||
# Wrapping preferences
|
||||
csharp_preserve_single_line_statements = true
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# Blanket ignore zip files
|
||||
# Related to Teams Scenarios work
|
||||
*.zip
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
|
@ -284,4 +288,6 @@ Documentation/docs/
|
|||
*.pubxml
|
||||
PublishProfiles/
|
||||
|
||||
appsettings.local.json
|
||||
appsettings.local.json
|
||||
**/*/.luisrc
|
||||
/.vscode/launch.json
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"*.schema": "json"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/tests/Microsoft.Bot.Builder.TestBot.Json/Microsoft.Bot.Builder.TestBot.Json.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "publish",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"publish",
|
||||
"${workspaceFolder}/tests/Microsoft.Bot.Builder.TestBot.Json/Microsoft.Bot.Builder.TestBot.Json.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"watch",
|
||||
"run",
|
||||
"${workspaceFolder}/tests/Microsoft.Bot.Builder.TestBot.Json/Microsoft.Bot.Builder.TestBot.Json.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/samples/Microsoft.Bot.Builder.TestBot.Json/Microsoft.Bot.Builder.TestBot.Json.csproj"
|
||||
],
|
||||
"problemMatcher": "$tsc"
|
||||
},
|
||||
{
|
||||
"label": "publish",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"publish",
|
||||
"${workspaceFolder}/samples/Microsoft.Bot.Builder.TestBot.Json/Microsoft.Bot.Builder.TestBot.Json.csproj"
|
||||
],
|
||||
"problemMatcher": "$tsc"
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"watch",
|
||||
"run",
|
||||
"${workspaceFolder}/samples/Microsoft.Bot.Builder.TestBot.Json/Microsoft.Bot.Builder.TestBot.Json.csproj"
|
||||
],
|
||||
"problemMatcher": "$tsc"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,199 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="Rules for StyleCop.Analyzers" Description="Source analysis rules treat as errors for BotBuilder-DotNet solution." ToolsVersion="15.0">
|
||||
<RuleSet Name="Rules for StyleCop.Analyzers" Description="Source analysis rules treat as errors for BotBuilder-DotNet solution." ToolsVersion="16.0">
|
||||
<Rules AnalyzerId="AsyncUsageAnalyzers" RuleNamespace="AsyncUsageAnalyzers">
|
||||
<Rule Id="AvoidAsyncSuffix" Action="Error" />
|
||||
<Rule Id="AvoidAsyncVoid" Action="Error" />
|
||||
<Rule Id="UseAsyncSuffix" Action="Error" />
|
||||
<Rule Id="UseConfigureAwait" Action="Error" />
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp.Features" RuleNamespace="Microsoft.CodeAnalysis.CSharp.Features">
|
||||
<Rule Id="IDE0003" Action="None" />
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
|
||||
<Rule Id="SA0001" Action="None" />
|
||||
<Rule Id="SA0002" Action="Error" />
|
||||
<Rule Id="SA1000" Action="Error" />
|
||||
<Rule Id="SA1001" Action="Error" />
|
||||
<Rule Id="SA1002" Action="Error" />
|
||||
<Rule Id="SA1003" Action="Error" />
|
||||
<Rule Id="SA1004" Action="Error" />
|
||||
<Rule Id="SA1005" Action="Error" />
|
||||
<Rule Id="SA1006" Action="Error" />
|
||||
<Rule Id="SA1007" Action="Error" />
|
||||
<Rule Id="SA1008" Action="Error" />
|
||||
<Rule Id="SA1009" Action="Error" />
|
||||
<Rule Id="SA1010" Action="Error" />
|
||||
<Rule Id="SA1011" Action="Error" />
|
||||
<Rule Id="SA1012" Action="Error" />
|
||||
<Rule Id="SA1013" Action="Error" />
|
||||
<Rule Id="SA1014" Action="Error" />
|
||||
<Rule Id="SA1015" Action="Error" />
|
||||
<Rule Id="SA1016" Action="Error" />
|
||||
<Rule Id="SA1017" Action="Error" />
|
||||
<Rule Id="SA1018" Action="Error" />
|
||||
<Rule Id="SA1019" Action="Error" />
|
||||
<Rule Id="SA1020" Action="Error" />
|
||||
<Rule Id="SA1021" Action="Error" />
|
||||
<Rule Id="SA1022" Action="Error" />
|
||||
<Rule Id="SA1023" Action="Error" />
|
||||
<Rule Id="SA1024" Action="Error" />
|
||||
<Rule Id="SA1025" Action="Error" />
|
||||
<Rule Id="SA1026" Action="Error" />
|
||||
<Rule Id="SA1027" Action="Error" />
|
||||
<Rule Id="SA1028" Action="Error" />
|
||||
<Rule Id="SA1100" Action="Error" />
|
||||
<Rule Id="SA1101" Action="None" />
|
||||
<Rule Id="SA1102" Action="Error" />
|
||||
<Rule Id="SA1103" Action="Error" />
|
||||
<Rule Id="SA1104" Action="Error" />
|
||||
<Rule Id="SA1105" Action="Error" />
|
||||
<Rule Id="SA1106" Action="Error" />
|
||||
<Rule Id="SA1107" Action="Error" />
|
||||
<Rule Id="SA1108" Action="Error" />
|
||||
<Rule Id="SA1110" Action="Error" />
|
||||
<Rule Id="SA1111" Action="Error" />
|
||||
<Rule Id="SA1112" Action="Error" />
|
||||
<Rule Id="SA1113" Action="Error" />
|
||||
<Rule Id="SA1114" Action="Error" />
|
||||
<Rule Id="SA1115" Action="Error" />
|
||||
<Rule Id="SA1116" Action="Error" />
|
||||
<Rule Id="SA1117" Action="Error" />
|
||||
<Rule Id="SA1118" Action="Error" />
|
||||
<Rule Id="SA1119" Action="Error" />
|
||||
<Rule Id="SA1120" Action="Error" />
|
||||
<Rule Id="SA1121" Action="Error" />
|
||||
<Rule Id="SA1122" Action="Error" />
|
||||
<Rule Id="SA1123" Action="Error" />
|
||||
<Rule Id="SA1124" Action="Error" />
|
||||
<Rule Id="SA1125" Action="Error" />
|
||||
<Rule Id="SA1127" Action="Error" />
|
||||
<Rule Id="SA1128" Action="Error" />
|
||||
<Rule Id="SA1129" Action="None" />
|
||||
<Rule Id="SA1130" Action="Error" />
|
||||
<Rule Id="SA1131" Action="Error" />
|
||||
<Rule Id="SA1132" Action="Error" />
|
||||
<Rule Id="SA1133" Action="Error" />
|
||||
<Rule Id="SA1134" Action="Error" />
|
||||
<Rule Id="SA1135" Action="Error" />
|
||||
<Rule Id="SA1136" Action="Error" />
|
||||
<Rule Id="SA1137" Action="Error" />
|
||||
<Rule Id="SA1139" Action="Error" />
|
||||
<Rule Id="SA1200" Action="None" />
|
||||
<Rule Id="SA1201" Action="Error" />
|
||||
<Rule Id="SA1202" Action="Error" />
|
||||
<Rule Id="SA1203" Action="Error" />
|
||||
<Rule Id="SA1204" Action="Error" />
|
||||
<Rule Id="SA1205" Action="Error" />
|
||||
<Rule Id="SA1206" Action="Error" />
|
||||
<Rule Id="SA1207" Action="Error" />
|
||||
<Rule Id="SA1208" Action="Error" />
|
||||
<Rule Id="SA1209" Action="Error" />
|
||||
<Rule Id="SA1210" Action="Error" />
|
||||
<Rule Id="SA1211" Action="Error" />
|
||||
<Rule Id="SA1212" Action="Error" />
|
||||
<Rule Id="SA1213" Action="Error" />
|
||||
<Rule Id="SA1214" Action="None" />
|
||||
<Rule Id="SA1216" Action="Error" />
|
||||
<Rule Id="SA1217" Action="Error" />
|
||||
<Rule Id="SA1300" Action="Error" />
|
||||
<Rule Id="SA1302" Action="Error" />
|
||||
<Rule Id="SA1303" Action="Error" />
|
||||
<Rule Id="SA1304" Action="Error" />
|
||||
<Rule Id="SA1305" Action="Error" />
|
||||
<Rule Id="SA1306" Action="Error" />
|
||||
<Rule Id="SA1307" Action="Error" />
|
||||
<Rule Id="SA1308" Action="Error" />
|
||||
<Rule Id="SA1309" Action="None" />
|
||||
<Rule Id="SA1310" Action="Error" />
|
||||
<Rule Id="SA1311" Action="Error" />
|
||||
<Rule Id="SA1312" Action="Error" />
|
||||
<Rule Id="SA1313" Action="Error" />
|
||||
<Rule Id="SA1314" Action="Error" />
|
||||
<Rule Id="SA1400" Action="Error" />
|
||||
<Rule Id="SA1401" Action="Error" />
|
||||
<Rule Id="SA1402" Action="Error" />
|
||||
<Rule Id="SA1403" Action="Error" />
|
||||
<Rule Id="SA1404" Action="Error" />
|
||||
<Rule Id="SA1405" Action="Error" />
|
||||
<Rule Id="SA1406" Action="Error" />
|
||||
<Rule Id="SA1407" Action="Error" />
|
||||
<Rule Id="SA1408" Action="Error" />
|
||||
<Rule Id="SA1410" Action="Error" />
|
||||
<Rule Id="SA1411" Action="Error" />
|
||||
<Rule Id="SA1412" Action="Error" />
|
||||
<Rule Id="SA1413" Action="Error" />
|
||||
<Rule Id="SA1500" Action="Error" />
|
||||
<Rule Id="SA1501" Action="Error" />
|
||||
<Rule Id="SA1502" Action="Error" />
|
||||
<Rule Id="SA1503" Action="Error" />
|
||||
<Rule Id="SA1504" Action="Error" />
|
||||
<Rule Id="SA1505" Action="Error" />
|
||||
<Rule Id="SA1506" Action="Error" />
|
||||
<Rule Id="SA1507" Action="Error" />
|
||||
<Rule Id="SA1508" Action="Error" />
|
||||
<Rule Id="SA1509" Action="Error" />
|
||||
<Rule Id="SA1510" Action="Error" />
|
||||
<Rule Id="SA1511" Action="Error" />
|
||||
<Rule Id="SA1512" Action="Error" />
|
||||
<Rule Id="SA1513" Action="Error" />
|
||||
<Rule Id="SA1514" Action="Error" />
|
||||
<Rule Id="SA1515" Action="Error" />
|
||||
<Rule Id="SA1516" Action="Error" />
|
||||
<Rule Id="SA1517" Action="Error" />
|
||||
<Rule Id="SA1518" Action="Error" />
|
||||
<Rule Id="SA1519" Action="Error" />
|
||||
<Rule Id="SA1520" Action="Error" />
|
||||
<Rule Id="SA1600" Action="None" />
|
||||
<Rule Id="SA1601" Action="Error" />
|
||||
<Rule Id="SA1602" Action="Error" />
|
||||
<Rule Id="SA1604" Action="Error" />
|
||||
<Rule Id="SA1605" Action="Error" />
|
||||
<Rule Id="SA1606" Action="Error" />
|
||||
<Rule Id="SA1607" Action="Error" />
|
||||
<Rule Id="SA1608" Action="Error" />
|
||||
<Rule Id="SA1609" Action="Error" />
|
||||
<Rule Id="SA1610" Action="Error" />
|
||||
<Rule Id="SA1611" Action="Error" />
|
||||
<Rule Id="SA1612" Action="Error" />
|
||||
<Rule Id="SA1613" Action="Error" />
|
||||
<Rule Id="SA1614" Action="Error" />
|
||||
<Rule Id="SA1615" Action="Error" />
|
||||
<Rule Id="SA1616" Action="Error" />
|
||||
<Rule Id="SA1617" Action="Error" />
|
||||
<Rule Id="SA1618" Action="Error" />
|
||||
<Rule Id="SA1619" Action="Error" />
|
||||
<Rule Id="SA1620" Action="Error" />
|
||||
<Rule Id="SA1621" Action="Error" />
|
||||
<Rule Id="SA1622" Action="Error" />
|
||||
<Rule Id="SA1623" Action="Error" />
|
||||
<Rule Id="SA1624" Action="Error" />
|
||||
<Rule Id="SA1625" Action="Error" />
|
||||
<Rule Id="SA1626" Action="Error" />
|
||||
<Rule Id="SA1627" Action="Error" />
|
||||
<Rule Id="SA1629" Action="Error" />
|
||||
<Rule Id="SA1633" Action="None" />
|
||||
<Rule Id="SA1634" Action="Error" />
|
||||
<Rule Id="SA1635" Action="Error" />
|
||||
<Rule Id="SA1636" Action="Error" />
|
||||
<Rule Id="SA1637" Action="Error" />
|
||||
<Rule Id="SA1638" Action="Error" />
|
||||
<Rule Id="SA1640" Action="Error" />
|
||||
<Rule Id="SA1641" Action="Error" />
|
||||
<Rule Id="SA1642" Action="Error" />
|
||||
<Rule Id="SA1643" Action="Error" />
|
||||
<Rule Id="SA1648" Action="Error" />
|
||||
<Rule Id="SA1649" Action="Error" />
|
||||
<Rule Id="SA1651" Action="Error" />
|
||||
<Rule Id="IDE0022" Action="None" />
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="Microsoft.CodeQuality.Analyzers" RuleNamespace="Microsoft.CodeQuality.Analyzers">
|
||||
<Rule Id="CA1054" Action="None" /> <!-- UriParametersShouldNotBeStrings -->
|
||||
<Rule Id="CA1056" Action="None" /> <!-- UriPropertiesShouldNotBeStrings -->
|
||||
<Rule Id="CA1062" Action="None" /> <!-- ValidateArgumentsOfPublicMethods -->
|
||||
<Rule Id="CA2227" Action="None" /> <!-- CollectionPropertiesShouldBeReadOnly -->
|
||||
<Rule Id="CA1054" Action="None" />
|
||||
<Rule Id="CA1056" Action="None" />
|
||||
<Rule Id="CA1062" Action="None" />
|
||||
<Rule Id="CA2227" Action="None" />
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="Microsoft.NetCore.Analyzers" RuleNamespace="Microsoft.NetCore.Analyzers">
|
||||
<Rule Id="CA1303" Action="None" /> <!-- DoNotPassLiteralsAsLocalizedParameters -->
|
||||
</Rules>
|
||||
<Rule Id="CA1303" Action="None" />
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
|
||||
<Rule Id="SA0001" Action="Info" />
|
||||
<Rule Id="SA1028" Action="None" />
|
||||
<Rule Id="SA1101" Action="None" />
|
||||
<Rule Id="SA1118" Action="None" />
|
||||
<Rule Id="SA1121" Action="None" />
|
||||
<Rule Id="SA1129" Action="None" />
|
||||
<Rule Id="SA1131" Action="None" />
|
||||
<Rule Id="SA1200" Action="None" />
|
||||
<Rule Id="SA1214" Action="None" />
|
||||
<Rule Id="SA1309" Action="None" />
|
||||
<Rule Id="SA1412" Action="Warning" />
|
||||
<Rule Id="SA1413" Action="None" />
|
||||
<Rule Id="SA1512" Action="None" />
|
||||
<Rule Id="SA1515" Action="None" />
|
||||
<Rule Id="SA1518" Action="None" />
|
||||
<Rule Id="SA1600" Action="None" />
|
||||
<Rule Id="SA1629" Action="None" />
|
||||
<Rule Id="SA1633" Action="None" />
|
||||
</Rules>
|
||||
</RuleSet>
|
|
@ -5,6 +5,7 @@ consolidating using generics with POCO objects and shared base class
|
|||
* Added BotContextWrapper so developer can easily create custom BotContext with their own helpers/methods
|
||||
|
||||
|
||||
|
||||
## 4.0.0-alpha201802027a
|
||||
* Milan release
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<ModulePaths>
|
||||
<Include>
|
||||
<ModulePath>.*\Microsoft.Bot.Builder.dll$</ModulePath>
|
||||
<ModulePath>.*\Microsoft.Bot.Builder.Adapters.Twilio.dll$</ModulePath>
|
||||
<ModulePath>.*\Microsoft.Bot.Builder.Teams.dll$</ModulePath>
|
||||
<ModulePath>.*\Microsoft.Bot.Builder.AI.Luis.dll$</ModulePath>
|
||||
<ModulePath>.*\Microsoft.Bot.Builder.AI.QnA.dll$</ModulePath>
|
||||
|
@ -22,9 +23,16 @@
|
|||
<ModulePath>.*\Microsoft.Bot.Builder.Integration.AspNet.Core.dll$</ModulePath>
|
||||
<ModulePath>.*\Microsoft.Bot.Builder.TemplateManager.dll$</ModulePath>
|
||||
<ModulePath>.*\Microsoft.Bot.Builder.Testing.dll$</ModulePath>
|
||||
<ModulePath>.*\Microsoft.Bot.Builder.Adapters.Webex.dll$</ModulePath>
|
||||
<!-- <ModulePath>Microsoft.Bot.Builder.Schema.dll$</ModulePath> -->
|
||||
</Include>
|
||||
</ModulePaths>
|
||||
<Sources>
|
||||
<Exclude>
|
||||
<Source>.*\\WebexMessageRequest.cs</Source>
|
||||
<Source>.*\\WebexClientWrapper.cs</Source>
|
||||
</Exclude>
|
||||
</Sources>
|
||||
</CodeCoverage>
|
||||
</Configuration>
|
||||
</DataCollector>
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
<PropertyGroup>
|
||||
<PackageOutputPath>$(MSBuildThisFileDirectory)outputpackages\</PackageOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<CodeAnalysisRuleSet>$(SolutionDir)BotBuilder-DotNet.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRuleSet>$(SolutionDir)\BotBuilder-DotNet.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -20,28 +20,39 @@
|
|||
|
||||
<!-- Rules found at: https://aka.ms/Microsoft-NuGet-Compliance -->
|
||||
|
||||
<!-- Per rules,this must be *EXACTLY* "Microsoft. Otherwise Nuget.org will reject the packages." -->
|
||||
<!-- Per rules,this must be *EXACTLY* "Microsoft. Otherwise Nuget.org will reject the packages." -->
|
||||
|
||||
<Authors>Microsoft</Authors>
|
||||
<Product>Microsoft Bot Builder SDK</Product>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AssemblyOriginatorKeyFile>$(SolutionDir)\build\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn),1573,1591,1712</NoWarn>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<DelaySign>true</DelaySign>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(SignAssembly)'=='True' ">
|
||||
<DefineConstants>SIGNASSEMBLY</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebugType>full</DebugType>
|
||||
<DebugType>portable</DebugType>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<!-- For debug builds, we don't generate documentation. Supress the StyleCop rule that warns about this. -->
|
||||
<NoWarn>$(NoWarn);SA0001</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<PropertyGroup Condition="'$(GeneratePackageOnBuild)' == 'True'">
|
||||
<!-- Rules found at: https://aka.ms/Microsoft-NuGet-Compliance -->
|
||||
<PackageProjectUrl>https://github.com/Microsoft/botbuilder-dotnet</PackageProjectUrl>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/microsoft/botframework-sdk/master/icon.png</PackageIconUrl>
|
||||
<PackageLicenseUrl>https://github.com/Microsoft/BotBuilder/blob/master/LICENSE</PackageLicenseUrl>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<RepositoryUrl>https://github.com/Microsoft/botbuilder-dotnet</RepositoryUrl>
|
||||
<LicenseUrl>https://github.com/Microsoft/BotBuilder-dotnet/blob/master/LICENSE</LicenseUrl>
|
||||
<PackageTags>bots;ai;botframework;botbuilder</PackageTags>
|
||||
|
@ -53,14 +64,12 @@
|
|||
-->
|
||||
<NoWarn>$(NoWarn);NU5125</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(Configuration) == 'Debug'">
|
||||
<!-- For debug builds, we don't generate documentation. Supress the StyleCop rule that warns about this. -->
|
||||
<NoWarn>$(NoWarn);SA0001</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(Configuration) == 'Debug - NuGet Packages'">
|
||||
<!-- For debug Nuget builds, we don't generate documentation. Supress the StyleCop rule that warns about this. -->
|
||||
<NoWarn>$(NoWarn);SA0001</NoWarn>
|
||||
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<ItemGroup Condition="'$(GeneratePackageOnBuild)' == 'True'">
|
||||
<None Include="icon.png" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<DefaultItemExcludes>.git\**;**\node_modules\**;$(DefaultItemExcludes)</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,49 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIIvjCCBqagAwIBAgITIAAJ5+kZen6NQMkNHwAAAAnn6TANBgkqhkiG9w0BAQsF
|
||||
ADCBizELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
|
||||
B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEVMBMGA1UE
|
||||
CxMMTWljcm9zb2Z0IElUMR4wHAYDVQQDExVNaWNyb3NvZnQgSVQgVExTIENBIDIw
|
||||
HhcNMTkwODIzMTgyNTA1WhcNMjEwODIzMTgyNTA1WjAlMSMwIQYDVQQDExp0ZXN0
|
||||
LmF1dGguYm90ZnJhbWV3b3JrLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
||||
AQoCggEBANZJFZHzfW8L9R0Iqd3DydCDHGhELNgr7ijO9nI/swl1v4rBlKWV24ML
|
||||
O0zxRmQhddpqSoWPFeF+MDo/OLv+FLwTexUC+ajf7iMiX7G+oG1PS9W4IU1B9tRR
|
||||
8w4Dn7rkAhrRZUZOkdyE1Y/mTogDslJuQUWtVndrwFO+QA4Yu21KvZo/bq9CBBDE
|
||||
CCWPWsZ27yVEqCKnx7+IKzmYUi1ukB9qWReahcLCckPoL5vQjNjNRIKWdSO36Mck
|
||||
fRks92mXI5DgKJcJoSN7k6DfauSTytvrnlMd99WSieQXJ8zT/rUKd2Vi48ugjNWp
|
||||
Dn/C529rlwgPGCL5DtXwevB/ByYi8rECAwEAAaOCBH4wggR6MIIB9AYKKwYBBAHW
|
||||
eQIEAgSCAeQEggHgAd4AdgB9PvL4j/+IVWgkwsDKnlKJeSvFDngJfy5ql2iZfiLw
|
||||
1wAAAWy/wsRqAAAEAwBHMEUCIEyrS3y+oHZMXGD5w6Z4pq7WDFYYEKoBUzHq4wAH
|
||||
sqy4AiEAk3lGjhbE90OW5JNZWYp72UULgAG3cwPueBGbtJrv8wEAdQBc3EOS/uar
|
||||
RUSxXprUVuYQN/vV+kfcoXOUsl7m9scOygAAAWy/wsTiAAAEAwBGMEQCICYW5kwo
|
||||
K5ddS+z435yg1r2zXrLPrMP2/b7i+L7co8xmAiATm5PJmS7OTC+gDNfGNtXXNB/K
|
||||
qA2fBiuJeRRqsGWTeQB1AESUZS6w7s6vxEAH2Kj+KMDa5oK+2MsxtT/TM5a1toGo
|
||||
AAABbL/Cw/EAAAQDAEYwRAIgdh73y6qInn82ZQk28zH+ddJKojS1NwrkARveu0je
|
||||
UpwCIHUKb0a7JgUWlmOstrO5oRwGd512hfVkUItxMUqHhqvtAHYA7ku9t3XOYLrh
|
||||
Qmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFsv8LEawAABAMARzBFAiEA59w8fd9g
|
||||
0MslZsKHRpMmaJiwEgZzfxxpTQ12TK7izBACIDx5+pVPWry1hRTI1EcJJxl23v7G
|
||||
bpv1/1oHO5QhNDeQMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwIwCgYIKwYB
|
||||
BQUHAwEwPgYJKwYBBAGCNxUHBDEwLwYnKwYBBAGCNxUIh9qGdYPu2QGCyYUbgbWe
|
||||
YYX062CBXYTS30KC55N6AgFkAgEdMIGFBggrBgEFBQcBAQR5MHcwUQYIKwYBBQUH
|
||||
MAKGRWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvbXNjb3JwL01pY3Jvc29m
|
||||
dCUyMElUJTIwVExTJTIwQ0ElMjAyLmNydDAiBggrBgEFBQcwAYYWaHR0cDovL29j
|
||||
c3AubXNvY3NwLmNvbTAdBgNVHQ4EFgQUubs1xOZtHFIMNVz6xisEQO1FT+AwCwYD
|
||||
VR0PBAQDAgSwMCUGA1UdEQQeMByCGnRlc3QuYXV0aC5ib3RmcmFtZXdvcmsuY29t
|
||||
MIGsBgNVHR8EgaQwgaEwgZ6ggZuggZiGS2h0dHA6Ly9tc2NybC5taWNyb3NvZnQu
|
||||
Y29tL3BraS9tc2NvcnAvY3JsL01pY3Jvc29mdCUyMElUJTIwVExTJTIwQ0ElMjAy
|
||||
LmNybIZJaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9tc2NvcnAvY3JsL01p
|
||||
Y3Jvc29mdCUyMElUJTIwVExTJTIwQ0ElMjAyLmNybDBNBgNVHSAERjBEMEIGCSsG
|
||||
AQQBgjcqATA1MDMGCCsGAQUFBwIBFidodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v
|
||||
cGtpL21zY29ycC9jcHMwHwYDVR0jBBgwFoAUkZ47RGw9V5xCdyo010/RzEqXLNow
|
||||
HQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IC
|
||||
AQBFStzhi1ihTC2jgbjqOL60rBTXhAoo8ieSRoHBg4vNeGG5oiH26/P/6A9Z3uYc
|
||||
Ld+I0o0t4AcbTRREITQijcWj/Zw4i4kNAdf4cPNQZcqKWpnBcWBmuvisVOpsKEna
|
||||
Xj7v/UFcHJGNvF2RHLd5s3lNn1xKfT3FWWkBmk6aFjXjlX3vWlulzpZlZUPE0XjM
|
||||
irKHwpqPun+xhTPItv1+1rgMfbv4U+biZCl0a6WbadbJ0Ro/s46sSlFHwNlZwOnB
|
||||
v8wwLW5m4+6ta1Z2gdL+kuLsIxaH2dJaL+vWHSjnPtyAKuizuI7Yezr1dYeNfE4h
|
||||
pK6qY/39q/Tbge8Z4/nQtkCuepQmTKih7kayK8INlmEpDS6fCPivxS/GARit/nIG
|
||||
P68aZ4rE7Lsq14nRNeY7B4rr8M6koKQmU/42D8R6uFnviM7BFH6Xb8zm973430BU
|
||||
nEKB0BQiLmVWsrl62VPcAf8jmT6D5ewy/x57z0M0Sp42OG0rdhOTwcwiJZ9H9K11
|
||||
Z7APnOfpADJ9U7IotsWtJK+skHftlXd9e8/2kRZJVXAEAOVX0RMh9w/p6GvVsPrp
|
||||
XfKMurEUf4sjaydo0w0NqL+tvt6uyCm0CvgWY+K/MHQeg2xAPqxANhJqR3G2cF1W
|
||||
+g72MY37XiT9CDvreyfuGLozcEFqoFpRayzLzyn0Rhi1oQ==
|
||||
-----END CERTIFICATE-----
|
Двоичные данные
FunctionalTests/Microsoft.Bot.Builder.FunctionalTests/Certificates/test.auth.botframework.com.pfx
Normal file
|
@ -3,6 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Configurations>Debug;Release;</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
|
|
|
@ -26,8 +26,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.AI.Lu
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.AI.Luis.Tests", "tests\Microsoft.Bot.Builder.AI.LUIS.Tests\Microsoft.Bot.Builder.AI.Luis.Tests.csproj", "{7BCEBDC1-D57F-4717-9B15-4FACD5473489}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Integration.AspNet.WebApi", "libraries\integration\Microsoft.Bot.Builder.Integration.AspNet.WebApi\Microsoft.Bot.Builder.Integration.AspNet.WebApi.csproj", "{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Integration.AspNet.Core", "libraries\integration\Microsoft.Bot.Builder.Integration.AspNet.Core\Microsoft.Bot.Builder.Integration.AspNet.Core.csproj", "{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.TemplateManager", "libraries\Microsoft.Bot.Builder.TemplateManager\Microsoft.Bot.Builder.TemplateManager.csproj", "{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}"
|
||||
|
@ -48,8 +46,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Integration", "Integration"
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Integration.AspNet.Core.Tests", "tests\integration\Microsoft.Bot.Builder.Integration.AspNet.Core.Tests\Microsoft.Bot.Builder.Integration.AspNet.Core.Tests.csproj", "{62C4DC83-3B07-45D7-856E-224FFB368E5F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Bot.Builder.Integration.AspNet.WebApi.Tests", "tests\integration\Microsoft.Bot.Builder.Integration.AspNet.WebApi.Tests\Microsoft.Bot.Builder.Integration.AspNet.WebApi.Tests.csproj", "{2614D290-1345-4A41-BE90-F85F817CEADE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Tests", "tests\Microsoft.Bot.Builder.Tests\Microsoft.Bot.Builder.Tests.csproj", "{35F9B8A8-1974-4795-930B-5E4980EE85E5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Transcripts.Tests", "tests\Microsoft.Bot.Builder.Transcripts.Tests\Microsoft.Bot.Builder.Transcripts.Tests.csproj", "{71698D71-4C6F-40D5-8BDE-2587514CA21C}"
|
||||
|
@ -64,16 +60,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Appli
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.ApplicationInsights.Core.Tests", "tests\integration\Microsoft.Bot.ApplicationInsights.Core.Tests\Microsoft.Bot.ApplicationInsights.Core.Tests.csproj", "{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Integration.ApplicationInsights.WebApi", "libraries\integration\Microsoft.Bot.Builder.Integration.ApplicationInsights.WebApi\Microsoft.Bot.Builder.Integration.ApplicationInsights.WebApi.csproj", "{400BB78F-AFDC-4B1C-AD85-BE159B576FCE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Bot.ApplicationInsights.WebApi.Tests", "tests\integration\Microsoft.Bot.ApplicationInsights.WebApi.Tests\Microsoft.Bot.ApplicationInsights.WebApi.Tests.csproj", "{873BCC1F-ED12-424E-93FA-D76F4BA022C2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.ApplicationInsights.Tests", "tests\Microsoft.Bot.Builder.ApplicationInsights.Tests\Microsoft.Bot.Builder.ApplicationInsights.Tests.csproj", "{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.TestBot", "tests\Microsoft.Bot.Builder.TestBot\Microsoft.Bot.Builder.TestBot.csproj", "{C113E0AE-5564-4389-BA39-183A8D574210}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Bot.Builder.TestBot.WebApi", "tests\Microsoft.Bot.Builder.TestBot.WebApi\Microsoft.Bot.Builder.TestBot.WebApi.csproj", "{610963BB-2717-47AB-BFEB-C8856A4A7CA7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.FunctionalTests", "FunctionalTests\Microsoft.Bot.Builder.FunctionalTests\Microsoft.Bot.Builder.FunctionalTests.csproj", "{B9DDC8CB-8EDF-4D98-913A-22F19E642223}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FunctionalTests", "FunctionalTests", "{8667F820-8ADA-4498-91AE-AE95DEE5227E}"
|
||||
|
@ -84,9 +74,49 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Testi
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.TestBot.Tests", "tests\Microsoft.Bot.Builder.TestBot.Tests\Microsoft.Bot.Builder.TestBot.Tests.csproj", "{76391566-9F22-4994-8B0F-02EFC0E9E228}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.AI.Luis.TestUtils", "tests\Microsoft.Bot.Builder.AI.Luis.TestUtils\Microsoft.Bot.Builder.AI.Luis.TestUtils.csproj", "{685271A8-6C69-46E4-9B11-89AF9761CE0A}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialogs.Declarative", "libraries\Microsoft.Bot.Builder.Dialogs.Declarative\Microsoft.Bot.Builder.Dialogs.Declarative.csproj", "{1BC05915-044E-4776-8956-B44BBEFF2F84}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.AI.LuisV3", "libraries\Microsoft.Bot.Builder.AI.LuisV3\Microsoft.Bot.Builder.AI.LuisV3.csproj", "{EF46ABF9-0405-4EAA-BC1E-A2BC48DD1A69}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialogs.Adaptive", "libraries\Microsoft.Bot.Builder.Dialogs.Adaptive\Microsoft.Bot.Builder.Dialogs.Adaptive.csproj", "{3CF175CF-1AF4-4109-96CB-221684DCED7D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialogs.Adaptive.Tests", "tests\Microsoft.Bot.Builder.Dialogs.Adaptive.Tests\Microsoft.Bot.Builder.Dialogs.Adaptive.Tests.csproj", "{CA008713-655E-46DA-BBDF-1EF6B8CE7DCA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Expressions.Tests", "tests\Microsoft.Bot.Expressions.Tests\Microsoft.Bot.Expressions.Tests.csproj", "{AE3FC7F6-B212-4438-B1D7-C121BB4C15ED}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Expressions", "libraries\Microsoft.Bot.Expressions\Microsoft.Bot.Expressions.csproj", "{8DC1257B-7650-40EB-97A2-C1CBA306DA6A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialogs.Declarative.Tests", "tests\Microsoft.Bot.Builder.Dialogs.Declarative.Tests\Microsoft.Bot.Builder.Dialogs.Declarative.Tests.csproj", "{D5E70443-4BA2-42ED-992A-010268440B08}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialogs.Debugging", "libraries\Microsoft.Bot.Builder.Dialogs.Debugging\Microsoft.Bot.Builder.Dialogs.Debugging.csproj", "{84E3B6A2-42D9-498A-9CD2-1C5F5BE0D526}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.LanguageGeneration", "libraries\Microsoft.Bot.Builder.LanguageGeneration\Microsoft.Bot.Builder.LanguageGeneration.csproj", "{52CDBBA9-E5AF-433C-80F0-5EF3C8B14946}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialogs.Debugging.Tests", "tests\Microsoft.Bot.Builder.Dialogs.Debugging.Tests\Microsoft.Bot.Builder.Dialogs.Debugging.Tests.csproj", "{F59673EA-2D0D-441A-BB85-CD343DE6BE45}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.LanguageGeneration.Tests", "tests\Microsoft.Bot.Builder.LanguageGeneration.Tests\Microsoft.Bot.Builder.LanguageGeneration.Tests.csproj", "{72EE26E2-E8BE-4169-82AD-93E021539C34}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.StreamingExtensions.Tests", "tests\Microsoft.Bot.StreamingExtensions.Test\Microsoft.Bot.StreamingExtensions.Tests.csproj", "{B7DB6561-7D83-4706-9DE0-02C5520DE2B7}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6B6AFE9D-6FA5-4699-B0EB-62335FD431C8}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
bot.png = bot.png
|
||||
bot_icon.png = bot_icon.png
|
||||
BotBuilder-DotNet.ruleset = BotBuilder-DotNet.ruleset
|
||||
Directory.Build.props = Directory.Build.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Schemas", "Schemas", "{EE56F2B6-4995-4E8F-ACFF-310AF0A4DA0F}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
schemas\baseComponent.schema = schemas\baseComponent.schema
|
||||
schemas\component.schema = schemas\component.schema
|
||||
schemas\readme.md = schemas\readme.md
|
||||
schemas\sdk.schema = schemas\sdk.schema
|
||||
schemas\update.cmd = schemas\update.cmd
|
||||
schemas\updateBranch.cmd = schemas\updateBranch.cmd
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.TestBot.Json", "tests\Microsoft.Bot.Builder.TestBot.Json\Microsoft.Bot.Builder.TestBot.Json.csproj", "{2454BBCD-77BC-4E3D-B5A6-3562BED898D6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.AI.Luis.TestUtils", "tests\Microsoft.Bot.Builder.AI.Luis.TestUtils\Microsoft.Bot.Builder.AI.Luis.TestUtils.csproj", "{685271A8-6C69-46E4-9B11-89AF9761CE0A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.AI.LuisV3.Tests", "tests\Microsoft.Bot.Builder.Ai.LUISV3.tests\Microsoft.Bot.Builder.AI.LuisV3.Tests.csproj", "{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7}"
|
||||
EndProject
|
||||
|
@ -98,11 +128,21 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Adapters", "Adapters", "{E8
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Adapters.Twilio.Tests", "tests\Adapters\Microsoft.Bot.Builder.Adapters.Twilio.Tests\Microsoft.Bot.Builder.Adapters.Twilio.Tests.csproj", "{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Schema.Teams", "libraries\Microsoft.Bot.Schema.Teams\Microsoft.Bot.Schema.Teams.csproj", "{1F8ACA9B-7721-4D83-8545-6EE449B3A100}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Integration.ApplicationInsights.WebApi", "libraries\integration\Microsoft.Bot.Builder.Integration.ApplicationInsights.WebApi\Microsoft.Bot.Builder.Integration.ApplicationInsights.WebApi.csproj", "{E0223463-97C6-4108-B5A9-AFBA16B9D5CC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Connector.Teams", "libraries\Microsoft.Bot.Connector.Teams\Microsoft.Bot.Connector.Teams.csproj", "{630CF216-BA97-4128-8563-214660B153DC}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Integration.AspNet.WebApi", "libraries\integration\Microsoft.Bot.Builder.Integration.AspNet.WebApi\Microsoft.Bot.Builder.Integration.AspNet.WebApi.csproj", "{EE76BD65-FB01-498F-B053-4E1B2693D85F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Teams", "libraries\Microsoft.Bot.Builder.Teams\Microsoft.Bot.Builder.Teams.csproj", "{56230F58-02EF-4C88-9C28-BE37B8A4D074}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Bot.ApplicationInsights.WebApi.Tests", "tests\integration\Microsoft.Bot.ApplicationInsights.WebApi.Tests\Microsoft.Bot.ApplicationInsights.WebApi.Tests.csproj", "{873BCC1F-ED12-424E-93FA-D76F4BA022C2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Bot.Builder.Integration.AspNet.WebApi.Tests", "tests\integration\Microsoft.Bot.Builder.Integration.AspNet.WebApi.Tests\Microsoft.Bot.Builder.Integration.AspNet.WebApi.Tests.csproj", "{2614D290-1345-4A41-BE90-F85F817CEADE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Adapters.Webex", "libraries\Adapters\Microsoft.Bot.Builder.Adapters.Webex\Microsoft.Bot.Builder.Adapters.Webex.csproj", "{F3669415-319E-4C4C-A398-89321589B3A9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Adapters.Webex.Tests", "tests\Adapters\Microsoft.Bot.Builder.Adapters.Webex.Tests\Microsoft.Bot.Builder.Adapters.Webex.Tests.csproj", "{9878B523-BD1E-4285-A875-3CAB4127F7E6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Adapters.Webex.TestBot", "tests\Adapters\Microsoft.Bot.Builder.Adapters.Webex.TestBot\Microsoft.Bot.Builder.Adapters.Webex.TestBot.csproj", "{6E39C647-902F-4CFF-A4E4-194B295E3AF4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialogs.Adaptive.Templates.Tests", "tests\Microsoft.Bot.Builder.Dialogs.Adaptive.Templates.Tests\Microsoft.Bot.Builder.Dialogs.Adaptive.Templates.Tests.csproj", "{EFAA1D3D-3102-4307-A5DD-EAB4DB9B0386}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Streaming", "libraries\Microsoft.Bot.Streaming\Microsoft.Bot.Streaming.csproj", "{4C82FD14-418F-43E4-AC59-3D926B55CEA3}"
|
||||
EndProject
|
||||
|
@ -119,287 +159,460 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Streaming.Tes
|
|||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug - NuGet Packages|Any CPU = Debug - NuGet Packages|Any CPU
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug-Windows|Any CPU = Debug-Windows|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release-Windows|Any CPU = Release-Windows|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B2C5EED9-21B2-4763-AB92-C1995B76DA3A}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{B2C5EED9-21B2-4763-AB92-C1995B76DA3A}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{B2C5EED9-21B2-4763-AB92-C1995B76DA3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B2C5EED9-21B2-4763-AB92-C1995B76DA3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B2C5EED9-21B2-4763-AB92-C1995B76DA3A}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B2C5EED9-21B2-4763-AB92-C1995B76DA3A}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B2C5EED9-21B2-4763-AB92-C1995B76DA3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B2C5EED9-21B2-4763-AB92-C1995B76DA3A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B2C5EED9-21B2-4763-AB92-C1995B76DA3A}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B2C5EED9-21B2-4763-AB92-C1995B76DA3A}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E325A0E2-716A-49E0-9767-5087CF05727C}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E325A0E2-716A-49E0-9767-5087CF05727C}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{E325A0E2-716A-49E0-9767-5087CF05727C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E325A0E2-716A-49E0-9767-5087CF05727C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E325A0E2-716A-49E0-9767-5087CF05727C}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E325A0E2-716A-49E0-9767-5087CF05727C}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E325A0E2-716A-49E0-9767-5087CF05727C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E325A0E2-716A-49E0-9767-5087CF05727C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6462DA5D-27DC-4CD5-9467-5EFB998FD838}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{6462DA5D-27DC-4CD5-9467-5EFB998FD838}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{E325A0E2-716A-49E0-9767-5087CF05727C}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E325A0E2-716A-49E0-9767-5087CF05727C}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{6462DA5D-27DC-4CD5-9467-5EFB998FD838}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6462DA5D-27DC-4CD5-9467-5EFB998FD838}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6462DA5D-27DC-4CD5-9467-5EFB998FD838}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6462DA5D-27DC-4CD5-9467-5EFB998FD838}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6462DA5D-27DC-4CD5-9467-5EFB998FD838}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6462DA5D-27DC-4CD5-9467-5EFB998FD838}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C1F54CDC-AD1D-45BB-8F7D-F49E411AFAF1}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{C1F54CDC-AD1D-45BB-8F7D-F49E411AFAF1}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{6462DA5D-27DC-4CD5-9467-5EFB998FD838}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6462DA5D-27DC-4CD5-9467-5EFB998FD838}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{C1F54CDC-AD1D-45BB-8F7D-F49E411AFAF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C1F54CDC-AD1D-45BB-8F7D-F49E411AFAF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C1F54CDC-AD1D-45BB-8F7D-F49E411AFAF1}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C1F54CDC-AD1D-45BB-8F7D-F49E411AFAF1}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C1F54CDC-AD1D-45BB-8F7D-F49E411AFAF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C1F54CDC-AD1D-45BB-8F7D-F49E411AFAF1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{C1F54CDC-AD1D-45BB-8F7D-F49E411AFAF1}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C1F54CDC-AD1D-45BB-8F7D-F49E411AFAF1}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BF414C86-DB3B-4022-9B29-DCE8AA954C12}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BF414C86-DB3B-4022-9B29-DCE8AA954C12}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{BF414C86-DB3B-4022-9B29-DCE8AA954C12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BF414C86-DB3B-4022-9B29-DCE8AA954C12}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BF414C86-DB3B-4022-9B29-DCE8AA954C12}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BF414C86-DB3B-4022-9B29-DCE8AA954C12}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BF414C86-DB3B-4022-9B29-DCE8AA954C12}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BF414C86-DB3B-4022-9B29-DCE8AA954C12}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{67AA3C00-E2C5-4D13-BA5E-72EB0E5B8DAA}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{67AA3C00-E2C5-4D13-BA5E-72EB0E5B8DAA}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{BF414C86-DB3B-4022-9B29-DCE8AA954C12}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BF414C86-DB3B-4022-9B29-DCE8AA954C12}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{67AA3C00-E2C5-4D13-BA5E-72EB0E5B8DAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{67AA3C00-E2C5-4D13-BA5E-72EB0E5B8DAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{67AA3C00-E2C5-4D13-BA5E-72EB0E5B8DAA}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{67AA3C00-E2C5-4D13-BA5E-72EB0E5B8DAA}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{67AA3C00-E2C5-4D13-BA5E-72EB0E5B8DAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{67AA3C00-E2C5-4D13-BA5E-72EB0E5B8DAA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7BCEBDC1-D57F-4717-9B15-4FACD5473489}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7BCEBDC1-D57F-4717-9B15-4FACD5473489}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{67AA3C00-E2C5-4D13-BA5E-72EB0E5B8DAA}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{67AA3C00-E2C5-4D13-BA5E-72EB0E5B8DAA}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{7BCEBDC1-D57F-4717-9B15-4FACD5473489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7BCEBDC1-D57F-4717-9B15-4FACD5473489}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7BCEBDC1-D57F-4717-9B15-4FACD5473489}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7BCEBDC1-D57F-4717-9B15-4FACD5473489}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7BCEBDC1-D57F-4717-9B15-4FACD5473489}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7BCEBDC1-D57F-4717-9B15-4FACD5473489}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{7BCEBDC1-D57F-4717-9B15-4FACD5473489}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7BCEBDC1-D57F-4717-9B15-4FACD5473489}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A4184239-F13F-4A09-B2D3-0B9532609248}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A4184239-F13F-4A09-B2D3-0B9532609248}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{A4184239-F13F-4A09-B2D3-0B9532609248}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A4184239-F13F-4A09-B2D3-0B9532609248}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A4184239-F13F-4A09-B2D3-0B9532609248}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A4184239-F13F-4A09-B2D3-0B9532609248}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A4184239-F13F-4A09-B2D3-0B9532609248}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A4184239-F13F-4A09-B2D3-0B9532609248}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D9B2EF5D-0515-460F-948A-2BB70C8DCF62}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{D9B2EF5D-0515-460F-948A-2BB70C8DCF62}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{A4184239-F13F-4A09-B2D3-0B9532609248}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A4184239-F13F-4A09-B2D3-0B9532609248}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{D9B2EF5D-0515-460F-948A-2BB70C8DCF62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D9B2EF5D-0515-460F-948A-2BB70C8DCF62}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D9B2EF5D-0515-460F-948A-2BB70C8DCF62}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D9B2EF5D-0515-460F-948A-2BB70C8DCF62}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D9B2EF5D-0515-460F-948A-2BB70C8DCF62}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D9B2EF5D-0515-460F-948A-2BB70C8DCF62}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0F639EB4-FB64-4909-8A10-FB93E7BE3AFB}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{0F639EB4-FB64-4909-8A10-FB93E7BE3AFB}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{D9B2EF5D-0515-460F-948A-2BB70C8DCF62}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D9B2EF5D-0515-460F-948A-2BB70C8DCF62}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{0F639EB4-FB64-4909-8A10-FB93E7BE3AFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0F639EB4-FB64-4909-8A10-FB93E7BE3AFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0F639EB4-FB64-4909-8A10-FB93E7BE3AFB}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0F639EB4-FB64-4909-8A10-FB93E7BE3AFB}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0F639EB4-FB64-4909-8A10-FB93E7BE3AFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0F639EB4-FB64-4909-8A10-FB93E7BE3AFB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0F639EB4-FB64-4909-8A10-FB93E7BE3AFB}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0F639EB4-FB64-4909-8A10-FB93E7BE3AFB}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{62C4DC83-3B07-45D7-856E-224FFB368E5F}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{62C4DC83-3B07-45D7-856E-224FFB368E5F}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{62C4DC83-3B07-45D7-856E-224FFB368E5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{62C4DC83-3B07-45D7-856E-224FFB368E5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{62C4DC83-3B07-45D7-856E-224FFB368E5F}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{62C4DC83-3B07-45D7-856E-224FFB368E5F}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{62C4DC83-3B07-45D7-856E-224FFB368E5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{62C4DC83-3B07-45D7-856E-224FFB368E5F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{35F9B8A8-1974-4795-930B-5E4980EE85E5}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{35F9B8A8-1974-4795-930B-5E4980EE85E5}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{62C4DC83-3B07-45D7-856E-224FFB368E5F}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{62C4DC83-3B07-45D7-856E-224FFB368E5F}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{35F9B8A8-1974-4795-930B-5E4980EE85E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{35F9B8A8-1974-4795-930B-5E4980EE85E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{35F9B8A8-1974-4795-930B-5E4980EE85E5}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{35F9B8A8-1974-4795-930B-5E4980EE85E5}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{35F9B8A8-1974-4795-930B-5E4980EE85E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{35F9B8A8-1974-4795-930B-5E4980EE85E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{71698D71-4C6F-40D5-8BDE-2587514CA21C}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{71698D71-4C6F-40D5-8BDE-2587514CA21C}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{35F9B8A8-1974-4795-930B-5E4980EE85E5}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{35F9B8A8-1974-4795-930B-5E4980EE85E5}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{71698D71-4C6F-40D5-8BDE-2587514CA21C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{71698D71-4C6F-40D5-8BDE-2587514CA21C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{71698D71-4C6F-40D5-8BDE-2587514CA21C}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{71698D71-4C6F-40D5-8BDE-2587514CA21C}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{71698D71-4C6F-40D5-8BDE-2587514CA21C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{71698D71-4C6F-40D5-8BDE-2587514CA21C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0B8ABFDB-F9CF-4EC6-988E-9C32D9E01C26}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0B8ABFDB-F9CF-4EC6-988E-9C32D9E01C26}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{71698D71-4C6F-40D5-8BDE-2587514CA21C}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{71698D71-4C6F-40D5-8BDE-2587514CA21C}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{0B8ABFDB-F9CF-4EC6-988E-9C32D9E01C26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0B8ABFDB-F9CF-4EC6-988E-9C32D9E01C26}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0B8ABFDB-F9CF-4EC6-988E-9C32D9E01C26}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0B8ABFDB-F9CF-4EC6-988E-9C32D9E01C26}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0B8ABFDB-F9CF-4EC6-988E-9C32D9E01C26}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0B8ABFDB-F9CF-4EC6-988E-9C32D9E01C26}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1B7920E6-5262-4054-B72D-3A8DBBA057D2}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1B7920E6-5262-4054-B72D-3A8DBBA057D2}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0B8ABFDB-F9CF-4EC6-988E-9C32D9E01C26}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0B8ABFDB-F9CF-4EC6-988E-9C32D9E01C26}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{1B7920E6-5262-4054-B72D-3A8DBBA057D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1B7920E6-5262-4054-B72D-3A8DBBA057D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1B7920E6-5262-4054-B72D-3A8DBBA057D2}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1B7920E6-5262-4054-B72D-3A8DBBA057D2}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1B7920E6-5262-4054-B72D-3A8DBBA057D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1B7920E6-5262-4054-B72D-3A8DBBA057D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8FC920C6-E895-4A17-AB2F-452FAAA36CC8}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8FC920C6-E895-4A17-AB2F-452FAAA36CC8}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1B7920E6-5262-4054-B72D-3A8DBBA057D2}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1B7920E6-5262-4054-B72D-3A8DBBA057D2}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{8FC920C6-E895-4A17-AB2F-452FAAA36CC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8FC920C6-E895-4A17-AB2F-452FAAA36CC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8FC920C6-E895-4A17-AB2F-452FAAA36CC8}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8FC920C6-E895-4A17-AB2F-452FAAA36CC8}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8FC920C6-E895-4A17-AB2F-452FAAA36CC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8FC920C6-E895-4A17-AB2F-452FAAA36CC8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B609DB2C-5C1F-46D1-A0FA-A0FF9216899A}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B609DB2C-5C1F-46D1-A0FA-A0FF9216899A}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8FC920C6-E895-4A17-AB2F-452FAAA36CC8}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8FC920C6-E895-4A17-AB2F-452FAAA36CC8}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{B609DB2C-5C1F-46D1-A0FA-A0FF9216899A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B609DB2C-5C1F-46D1-A0FA-A0FF9216899A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B609DB2C-5C1F-46D1-A0FA-A0FF9216899A}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B609DB2C-5C1F-46D1-A0FA-A0FF9216899A}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B609DB2C-5C1F-46D1-A0FA-A0FF9216899A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B609DB2C-5C1F-46D1-A0FA-A0FF9216899A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B609DB2C-5C1F-46D1-A0FA-A0FF9216899A}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B609DB2C-5C1F-46D1-A0FA-A0FF9216899A}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{400BB78F-AFDC-4B1C-AD85-BE159B576FCE}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{400BB78F-AFDC-4B1C-AD85-BE159B576FCE}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{400BB78F-AFDC-4B1C-AD85-BE159B576FCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{400BB78F-AFDC-4B1C-AD85-BE159B576FCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{400BB78F-AFDC-4B1C-AD85-BE159B576FCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{400BB78F-AFDC-4B1C-AD85-BE159B576FCE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C113E0AE-5564-4389-BA39-183A8D574210}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C113E0AE-5564-4389-BA39-183A8D574210}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{C113E0AE-5564-4389-BA39-183A8D574210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C113E0AE-5564-4389-BA39-183A8D574210}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C113E0AE-5564-4389-BA39-183A8D574210}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C113E0AE-5564-4389-BA39-183A8D574210}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C113E0AE-5564-4389-BA39-183A8D574210}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C113E0AE-5564-4389-BA39-183A8D574210}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{610963BB-2717-47AB-BFEB-C8856A4A7CA7}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{610963BB-2717-47AB-BFEB-C8856A4A7CA7}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{610963BB-2717-47AB-BFEB-C8856A4A7CA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{610963BB-2717-47AB-BFEB-C8856A4A7CA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{610963BB-2717-47AB-BFEB-C8856A4A7CA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{610963BB-2717-47AB-BFEB-C8856A4A7CA7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C113E0AE-5564-4389-BA39-183A8D574210}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C113E0AE-5564-4389-BA39-183A8D574210}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{685271A8-6C69-46E4-9B11-89AF9761CE0A}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{685271A8-6C69-46E4-9B11-89AF9761CE0A}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{3CF175CF-1AF4-4109-96CB-221684DCED7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3CF175CF-1AF4-4109-96CB-221684DCED7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3CF175CF-1AF4-4109-96CB-221684DCED7D}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3CF175CF-1AF4-4109-96CB-221684DCED7D}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3CF175CF-1AF4-4109-96CB-221684DCED7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3CF175CF-1AF4-4109-96CB-221684DCED7D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3CF175CF-1AF4-4109-96CB-221684DCED7D}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3CF175CF-1AF4-4109-96CB-221684DCED7D}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA008713-655E-46DA-BBDF-1EF6B8CE7DCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA008713-655E-46DA-BBDF-1EF6B8CE7DCA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA008713-655E-46DA-BBDF-1EF6B8CE7DCA}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA008713-655E-46DA-BBDF-1EF6B8CE7DCA}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA008713-655E-46DA-BBDF-1EF6B8CE7DCA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA008713-655E-46DA-BBDF-1EF6B8CE7DCA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA008713-655E-46DA-BBDF-1EF6B8CE7DCA}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA008713-655E-46DA-BBDF-1EF6B8CE7DCA}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{AE3FC7F6-B212-4438-B1D7-C121BB4C15ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AE3FC7F6-B212-4438-B1D7-C121BB4C15ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AE3FC7F6-B212-4438-B1D7-C121BB4C15ED}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AE3FC7F6-B212-4438-B1D7-C121BB4C15ED}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AE3FC7F6-B212-4438-B1D7-C121BB4C15ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AE3FC7F6-B212-4438-B1D7-C121BB4C15ED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AE3FC7F6-B212-4438-B1D7-C121BB4C15ED}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AE3FC7F6-B212-4438-B1D7-C121BB4C15ED}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{8DC1257B-7650-40EB-97A2-C1CBA306DA6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8DC1257B-7650-40EB-97A2-C1CBA306DA6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8DC1257B-7650-40EB-97A2-C1CBA306DA6A}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8DC1257B-7650-40EB-97A2-C1CBA306DA6A}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8DC1257B-7650-40EB-97A2-C1CBA306DA6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8DC1257B-7650-40EB-97A2-C1CBA306DA6A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8DC1257B-7650-40EB-97A2-C1CBA306DA6A}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8DC1257B-7650-40EB-97A2-C1CBA306DA6A}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{D5E70443-4BA2-42ED-992A-010268440B08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D5E70443-4BA2-42ED-992A-010268440B08}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D5E70443-4BA2-42ED-992A-010268440B08}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D5E70443-4BA2-42ED-992A-010268440B08}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D5E70443-4BA2-42ED-992A-010268440B08}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D5E70443-4BA2-42ED-992A-010268440B08}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D5E70443-4BA2-42ED-992A-010268440B08}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D5E70443-4BA2-42ED-992A-010268440B08}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{84E3B6A2-42D9-498A-9CD2-1C5F5BE0D526}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{84E3B6A2-42D9-498A-9CD2-1C5F5BE0D526}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{84E3B6A2-42D9-498A-9CD2-1C5F5BE0D526}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{84E3B6A2-42D9-498A-9CD2-1C5F5BE0D526}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{84E3B6A2-42D9-498A-9CD2-1C5F5BE0D526}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{84E3B6A2-42D9-498A-9CD2-1C5F5BE0D526}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{84E3B6A2-42D9-498A-9CD2-1C5F5BE0D526}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{84E3B6A2-42D9-498A-9CD2-1C5F5BE0D526}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{52CDBBA9-E5AF-433C-80F0-5EF3C8B14946}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{52CDBBA9-E5AF-433C-80F0-5EF3C8B14946}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{52CDBBA9-E5AF-433C-80F0-5EF3C8B14946}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{52CDBBA9-E5AF-433C-80F0-5EF3C8B14946}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{52CDBBA9-E5AF-433C-80F0-5EF3C8B14946}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{52CDBBA9-E5AF-433C-80F0-5EF3C8B14946}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{52CDBBA9-E5AF-433C-80F0-5EF3C8B14946}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{52CDBBA9-E5AF-433C-80F0-5EF3C8B14946}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{F59673EA-2D0D-441A-BB85-CD343DE6BE45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F59673EA-2D0D-441A-BB85-CD343DE6BE45}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F59673EA-2D0D-441A-BB85-CD343DE6BE45}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F59673EA-2D0D-441A-BB85-CD343DE6BE45}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F59673EA-2D0D-441A-BB85-CD343DE6BE45}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F59673EA-2D0D-441A-BB85-CD343DE6BE45}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F59673EA-2D0D-441A-BB85-CD343DE6BE45}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F59673EA-2D0D-441A-BB85-CD343DE6BE45}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{72EE26E2-E8BE-4169-82AD-93E021539C34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{72EE26E2-E8BE-4169-82AD-93E021539C34}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{72EE26E2-E8BE-4169-82AD-93E021539C34}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{72EE26E2-E8BE-4169-82AD-93E021539C34}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{72EE26E2-E8BE-4169-82AD-93E021539C34}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{72EE26E2-E8BE-4169-82AD-93E021539C34}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{72EE26E2-E8BE-4169-82AD-93E021539C34}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{72EE26E2-E8BE-4169-82AD-93E021539C34}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{B7DB6561-7D83-4706-9DE0-02C5520DE2B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B7DB6561-7D83-4706-9DE0-02C5520DE2B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B7DB6561-7D83-4706-9DE0-02C5520DE2B7}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B7DB6561-7D83-4706-9DE0-02C5520DE2B7}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B7DB6561-7D83-4706-9DE0-02C5520DE2B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B7DB6561-7D83-4706-9DE0-02C5520DE2B7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B7DB6561-7D83-4706-9DE0-02C5520DE2B7}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B7DB6561-7D83-4706-9DE0-02C5520DE2B7}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{2454BBCD-77BC-4E3D-B5A6-3562BED898D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2454BBCD-77BC-4E3D-B5A6-3562BED898D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2454BBCD-77BC-4E3D-B5A6-3562BED898D6}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2454BBCD-77BC-4E3D-B5A6-3562BED898D6}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2454BBCD-77BC-4E3D-B5A6-3562BED898D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2454BBCD-77BC-4E3D-B5A6-3562BED898D6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2454BBCD-77BC-4E3D-B5A6-3562BED898D6}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2454BBCD-77BC-4E3D-B5A6-3562BED898D6}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{685271A8-6C69-46E4-9B11-89AF9761CE0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{685271A8-6C69-46E4-9B11-89AF9761CE0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{685271A8-6C69-46E4-9B11-89AF9761CE0A}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{685271A8-6C69-46E4-9B11-89AF9761CE0A}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{685271A8-6C69-46E4-9B11-89AF9761CE0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{685271A8-6C69-46E4-9B11-89AF9761CE0A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EF46ABF9-0405-4EAA-BC1E-A2BC48DD1A69}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EF46ABF9-0405-4EAA-BC1E-A2BC48DD1A69}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EF46ABF9-0405-4EAA-BC1E-A2BC48DD1A69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EF46ABF9-0405-4EAA-BC1E-A2BC48DD1A69}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EF46ABF9-0405-4EAA-BC1E-A2BC48DD1A69}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EF46ABF9-0405-4EAA-BC1E-A2BC48DD1A69}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{685271A8-6C69-46E4-9B11-89AF9761CE0A}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{685271A8-6C69-46E4-9B11-89AF9761CE0A}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1D1AD39B-EBCF-4960-930E-84246DEF6AAE}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug - NuGet Packages|Any CPU
|
||||
{1D1AD39B-EBCF-4960-930E-84246DEF6AAE}.Debug - NuGet Packages|Any CPU.Build.0 = Debug - NuGet Packages|Any CPU
|
||||
{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{1D1AD39B-EBCF-4960-930E-84246DEF6AAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1D1AD39B-EBCF-4960-930E-84246DEF6AAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1D1AD39B-EBCF-4960-930E-84246DEF6AAE}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1D1AD39B-EBCF-4960-930E-84246DEF6AAE}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1D1AD39B-EBCF-4960-930E-84246DEF6AAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1D1AD39B-EBCF-4960-930E-84246DEF6AAE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1D1AD39B-EBCF-4960-930E-84246DEF6AAE}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1D1AD39B-EBCF-4960-930E-84246DEF6AAE}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1F8ACA9B-7721-4D83-8545-6EE449B3A100}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1F8ACA9B-7721-4D83-8545-6EE449B3A100}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1F8ACA9B-7721-4D83-8545-6EE449B3A100}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1F8ACA9B-7721-4D83-8545-6EE449B3A100}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1F8ACA9B-7721-4D83-8545-6EE449B3A100}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1F8ACA9B-7721-4D83-8545-6EE449B3A100}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{630CF216-BA97-4128-8563-214660B153DC}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{630CF216-BA97-4128-8563-214660B153DC}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{630CF216-BA97-4128-8563-214660B153DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{630CF216-BA97-4128-8563-214660B153DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{630CF216-BA97-4128-8563-214660B153DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{630CF216-BA97-4128-8563-214660B153DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{56230F58-02EF-4C88-9C28-BE37B8A4D074}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{56230F58-02EF-4C88-9C28-BE37B8A4D074}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{56230F58-02EF-4C88-9C28-BE37B8A4D074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{56230F58-02EF-4C88-9C28-BE37B8A4D074}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{56230F58-02EF-4C88-9C28-BE37B8A4D074}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{56230F58-02EF-4C88-9C28-BE37B8A4D074}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4C82FD14-418F-43E4-AC59-3D926B55CEA3}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4C82FD14-418F-43E4-AC59-3D926B55CEA3}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{E0223463-97C6-4108-B5A9-AFBA16B9D5CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E0223463-97C6-4108-B5A9-AFBA16B9D5CC}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E0223463-97C6-4108-B5A9-AFBA16B9D5CC}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E0223463-97C6-4108-B5A9-AFBA16B9D5CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E0223463-97C6-4108-B5A9-AFBA16B9D5CC}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E0223463-97C6-4108-B5A9-AFBA16B9D5CC}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{EE76BD65-FB01-498F-B053-4E1B2693D85F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EE76BD65-FB01-498F-B053-4E1B2693D85F}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EE76BD65-FB01-498F-B053-4E1B2693D85F}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EE76BD65-FB01-498F-B053-4E1B2693D85F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EE76BD65-FB01-498F-B053-4E1B2693D85F}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EE76BD65-FB01-498F-B053-4E1B2693D85F}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{F3669415-319E-4C4C-A398-89321589B3A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F3669415-319E-4C4C-A398-89321589B3A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F3669415-319E-4C4C-A398-89321589B3A9}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F3669415-319E-4C4C-A398-89321589B3A9}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F3669415-319E-4C4C-A398-89321589B3A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F3669415-319E-4C4C-A398-89321589B3A9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F3669415-319E-4C4C-A398-89321589B3A9}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F3669415-319E-4C4C-A398-89321589B3A9}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{9878B523-BD1E-4285-A875-3CAB4127F7E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9878B523-BD1E-4285-A875-3CAB4127F7E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9878B523-BD1E-4285-A875-3CAB4127F7E6}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9878B523-BD1E-4285-A875-3CAB4127F7E6}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9878B523-BD1E-4285-A875-3CAB4127F7E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9878B523-BD1E-4285-A875-3CAB4127F7E6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9878B523-BD1E-4285-A875-3CAB4127F7E6}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9878B523-BD1E-4285-A875-3CAB4127F7E6}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{6E39C647-902F-4CFF-A4E4-194B295E3AF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6E39C647-902F-4CFF-A4E4-194B295E3AF4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6E39C647-902F-4CFF-A4E4-194B295E3AF4}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6E39C647-902F-4CFF-A4E4-194B295E3AF4}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6E39C647-902F-4CFF-A4E4-194B295E3AF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6E39C647-902F-4CFF-A4E4-194B295E3AF4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6E39C647-902F-4CFF-A4E4-194B295E3AF4}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6E39C647-902F-4CFF-A4E4-194B295E3AF4}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{EFAA1D3D-3102-4307-A5DD-EAB4DB9B0386}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EFAA1D3D-3102-4307-A5DD-EAB4DB9B0386}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EFAA1D3D-3102-4307-A5DD-EAB4DB9B0386}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EFAA1D3D-3102-4307-A5DD-EAB4DB9B0386}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EFAA1D3D-3102-4307-A5DD-EAB4DB9B0386}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EFAA1D3D-3102-4307-A5DD-EAB4DB9B0386}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EFAA1D3D-3102-4307-A5DD-EAB4DB9B0386}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EFAA1D3D-3102-4307-A5DD-EAB4DB9B0386}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{4C82FD14-418F-43E4-AC59-3D926B55CEA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4C82FD14-418F-43E4-AC59-3D926B55CEA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4C82FD14-418F-43E4-AC59-3D926B55CEA3}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4C82FD14-418F-43E4-AC59-3D926B55CEA3}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4C82FD14-418F-43E4-AC59-3D926B55CEA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4C82FD14-418F-43E4-AC59-3D926B55CEA3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{77BD3C7F-34D9-47FC-AFC0-6D92A2081770}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{77BD3C7F-34D9-47FC-AFC0-6D92A2081770}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4C82FD14-418F-43E4-AC59-3D926B55CEA3}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4C82FD14-418F-43E4-AC59-3D926B55CEA3}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{77BD3C7F-34D9-47FC-AFC0-6D92A2081770}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{77BD3C7F-34D9-47FC-AFC0-6D92A2081770}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{77BD3C7F-34D9-47FC-AFC0-6D92A2081770}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{77BD3C7F-34D9-47FC-AFC0-6D92A2081770}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{77BD3C7F-34D9-47FC-AFC0-6D92A2081770}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{77BD3C7F-34D9-47FC-AFC0-6D92A2081770}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D243AC2D-7823-4177-9D8A-23FDFDA274D2}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D243AC2D-7823-4177-9D8A-23FDFDA274D2}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{77BD3C7F-34D9-47FC-AFC0-6D92A2081770}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{77BD3C7F-34D9-47FC-AFC0-6D92A2081770}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
{D243AC2D-7823-4177-9D8A-23FDFDA274D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D243AC2D-7823-4177-9D8A-23FDFDA274D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D243AC2D-7823-4177-9D8A-23FDFDA274D2}.Debug-Windows|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D243AC2D-7823-4177-9D8A-23FDFDA274D2}.Debug-Windows|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D243AC2D-7823-4177-9D8A-23FDFDA274D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D243AC2D-7823-4177-9D8A-23FDFDA274D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D243AC2D-7823-4177-9D8A-23FDFDA274D2}.Release-Windows|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D243AC2D-7823-4177-9D8A-23FDFDA274D2}.Release-Windows|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -415,7 +628,6 @@ Global
|
|||
{276EBE79-A13A-46BD-A566-B01DC0477A9B} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{67AA3C00-E2C5-4D13-BA5E-72EB0E5B8DAA} = {763168FA-A590-482C-84D8-2922F7ADB1A2}
|
||||
{7BCEBDC1-D57F-4717-9B15-4FACD5473489} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0} = {276EBE79-A13A-46BD-A566-B01DC0477A9B}
|
||||
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2} = {276EBE79-A13A-46BD-A566-B01DC0477A9B}
|
||||
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{C93F6192-0123-4121-AD92-374A71E4B0F3} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
|
@ -426,7 +638,6 @@ Global
|
|||
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{0A0E26B0-7A46-4F1A-8BFE-9A763FDF6CF8} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{62C4DC83-3B07-45D7-856E-224FFB368E5F} = {0A0E26B0-7A46-4F1A-8BFE-9A763FDF6CF8}
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE} = {0A0E26B0-7A46-4F1A-8BFE-9A763FDF6CF8}
|
||||
{35F9B8A8-1974-4795-930B-5E4980EE85E5} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{71698D71-4C6F-40D5-8BDE-2587514CA21C} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{0B8ABFDB-F9CF-4EC6-988E-9C32D9E01C26} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
|
@ -434,25 +645,38 @@ Global
|
|||
{8FC920C6-E895-4A17-AB2F-452FAAA36CC8} = {276EBE79-A13A-46BD-A566-B01DC0477A9B}
|
||||
{B609DB2C-5C1F-46D1-A0FA-A0FF9216899A} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{3F4A0DD8-4D47-4B9C-939A-3146E68C84F7} = {0A0E26B0-7A46-4F1A-8BFE-9A763FDF6CF8}
|
||||
{400BB78F-AFDC-4B1C-AD85-BE159B576FCE} = {276EBE79-A13A-46BD-A566-B01DC0477A9B}
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2} = {0A0E26B0-7A46-4F1A-8BFE-9A763FDF6CF8}
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{C113E0AE-5564-4389-BA39-183A8D574210} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{610963BB-2717-47AB-BFEB-C8856A4A7CA7} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223} = {8667F820-8ADA-4498-91AE-AE95DEE5227E}
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{3CF175CF-1AF4-4109-96CB-221684DCED7D} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{CA008713-655E-46DA-BBDF-1EF6B8CE7DCA} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{AE3FC7F6-B212-4438-B1D7-C121BB4C15ED} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{8DC1257B-7650-40EB-97A2-C1CBA306DA6A} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{D5E70443-4BA2-42ED-992A-010268440B08} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{84E3B6A2-42D9-498A-9CD2-1C5F5BE0D526} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{52CDBBA9-E5AF-433C-80F0-5EF3C8B14946} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{F59673EA-2D0D-441A-BB85-CD343DE6BE45} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{72EE26E2-E8BE-4169-82AD-93E021539C34} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{B7DB6561-7D83-4706-9DE0-02C5520DE2B7} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{2454BBCD-77BC-4E3D-B5A6-3562BED898D6} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{685271A8-6C69-46E4-9B11-89AF9761CE0A} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{EF46ABF9-0405-4EAA-BC1E-A2BC48DD1A69} = {763168FA-A590-482C-84D8-2922F7ADB1A2}
|
||||
{474C57B1-C9FC-4B71-A92B-B25BA27FAFA7} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{6230B915-B238-4E57-AAC4-06B4498F540F} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{1D1AD39B-EBCF-4960-930E-84246DEF6AAE} = {6230B915-B238-4E57-AAC4-06B4498F540F}
|
||||
{E8CD434A-306F-41D9-B67D-BFFF3287354D} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{6B51F54F-86E8-4FBC-8FDD-3C386E97D0E1} = {E8CD434A-306F-41D9-B67D-BFFF3287354D}
|
||||
{1F8ACA9B-7721-4D83-8545-6EE449B3A100} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{630CF216-BA97-4128-8563-214660B153DC} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{56230F58-02EF-4C88-9C28-BE37B8A4D074} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{E0223463-97C6-4108-B5A9-AFBA16B9D5CC} = {276EBE79-A13A-46BD-A566-B01DC0477A9B}
|
||||
{EE76BD65-FB01-498F-B053-4E1B2693D85F} = {276EBE79-A13A-46BD-A566-B01DC0477A9B}
|
||||
{873BCC1F-ED12-424E-93FA-D76F4BA022C2} = {0A0E26B0-7A46-4F1A-8BFE-9A763FDF6CF8}
|
||||
{2614D290-1345-4A41-BE90-F85F817CEADE} = {0A0E26B0-7A46-4F1A-8BFE-9A763FDF6CF8}
|
||||
{F3669415-319E-4C4C-A398-89321589B3A9} = {6230B915-B238-4E57-AAC4-06B4498F540F}
|
||||
{9878B523-BD1E-4285-A875-3CAB4127F7E6} = {E8CD434A-306F-41D9-B67D-BFFF3287354D}
|
||||
{6E39C647-902F-4CFF-A4E4-194B295E3AF4} = {E8CD434A-306F-41D9-B67D-BFFF3287354D}
|
||||
{EFAA1D3D-3102-4307-A5DD-EAB4DB9B0386} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{4C82FD14-418F-43E4-AC59-3D926B55CEA3} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{77BD3C7F-34D9-47FC-AFC0-6D92A2081770} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{D243AC2D-7823-4177-9D8A-23FDFDA274D2} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
|
|
|
@ -56,7 +56,13 @@ For more information see the [Code of Conduct FAQ](https://opensource.microsoft.
|
|||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
## Reporting Security Issues
|
||||
Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at [secure@microsoft.com](mailto:secure@microsoft.com). You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the [MSRC PGP](https://technet.microsoft.com/en-us/security/dn606155) key, can be found in the [Security TechCenter](https://technet.microsoft.com/en-us/security/default).
|
||||
Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC)
|
||||
at [secure@microsoft.com](mailto:secure@microsoft.com). You should receive a response within 24 hours. If for some
|
||||
reason you do not, please follow up via email to ensure we received your original message. Further information,
|
||||
including the [MSRC PGP](https://technet.microsoft.com/en-us/security/dn606155) key, can be found in the
|
||||
[Security TechCenter](https://technet.microsoft.com/en-us/security/default).
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Licensed under the [MIT](https://github.com/Microsoft/vscode/blob/master/LICENSE.txt) License.
|
||||
|
||||
|
|
|
@ -25,3 +25,5 @@ If you are experiencing 404 errors when trying to install the MyGet packages che
|
|||
|
||||
`https://botbuilder.myget.org/F/botbuilder-v4-dotnet-daily/api/v3/index.json`
|
||||
|
||||
.
|
||||
|
||||
|
|
После Ширина: | Высота: | Размер: 8.4 KiB |
После Ширина: | Высота: | Размер: 1.9 KiB |
|
@ -0,0 +1,723 @@
|
|||
# Memory
|
||||
Memory (aka state) is the data which is being tracked for your dialogs. There are a number
|
||||
of scoped memory which you can use. All memory properties are property bags, meaning you
|
||||
can store arbitrary information on them.
|
||||
|
||||
## User Memory
|
||||
User memory is persistent data scoped to the id of the user you are conversing with.
|
||||
|
||||
Example user memory expressions
|
||||
|
||||
user.name
|
||||
user.address.city
|
||||
|
||||
## Conversation Memory
|
||||
Conversation memory is persistent data scoped to the id of the conversation you are having.
|
||||
|
||||
Example conversation memory expressions
|
||||
|
||||
conversation.hasAcceptedTOU
|
||||
conversation.dateStarted
|
||||
conversation.lastMaleReference
|
||||
conversation.lastFemaleReference
|
||||
conversation.lastLocationReference
|
||||
|
||||
## Dialog Memory
|
||||
Dialog memory is persistent data scoped for a giving executing dialog, providing an memory space for each dialog to have internal persistent bookkeeping. Dialog memory is cleared when dialog ends.
|
||||
|
||||
Example dialog memory expressions
|
||||
|
||||
dialog.orderStarted
|
||||
dialog.shoppingCart
|
||||
|
||||
## Turn Memory
|
||||
Turn memory is non-persistent data scoped for *only the current turn*, providing a place to share data for the lifetime of the current turn.
|
||||
|
||||
Example turn memory expressions
|
||||
|
||||
turn.DialogEvent
|
||||
turn.recognitionResult
|
||||
|
||||
|
||||
# Microsoft.AdaptiveDialog
|
||||
The **Microsoft.AdaptiveDialog** is a new dialog which ties everything together into an adaptive package
|
||||
* It was designed to be declarative from the start
|
||||
* It allows you to think in sequences but allow for rules to dynamically adjust to context.
|
||||
* It supports rich eventing, interruption, cancelation and execution planning semantics
|
||||
* It supports extensibility points for recognition, rules and machine learning
|
||||
|
||||
## Rules
|
||||
Rules are essentially plugins which are consulted when there are new events and based
|
||||
on the result and the policies active. Every rule is made up of
|
||||
* Some condition which must be satisfied
|
||||
* Steps to execute (technically, steps to add to the *plan* to execute.)
|
||||
|
||||
There are a number of built in rules and you can easily create new rules.
|
||||
|
||||
|
||||
### Microsoft.EventRule rule
|
||||
The **Microsoft.EventRule** rule is used to trigger based on events.
|
||||
|
||||
| Property | Description |
|
||||
|------------|-----------------------------------------------------------------------------|
|
||||
| events | array of events to trigger on |
|
||||
| steps | collection of dialogs/dialog steps to add to the plan if conditions are met |
|
||||
| constraint | additional contraint to evalute on top of the event |
|
||||
|
||||
Example
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.EventRule",
|
||||
"events": ["ActivityReceived"],
|
||||
"constraint":"user.age > 18",
|
||||
"steps": [
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Microsoft.IntentRule
|
||||
The **Microsoft.IntentRule** rule is triggered if an intent and/or entities are recognized.
|
||||
|
||||
| Property | Description |
|
||||
|------------|------------------------------------------------------------------------------------|
|
||||
| intent | intent which should be recognized |
|
||||
| entities | array of names of entities which must be recognized |
|
||||
| constraint | additional expression as a constraint expressed against memory (OPTIONAL) |
|
||||
| steps | a dialogId or inline Dialog or array of dialogIds/dialogs/steps to add to the plan |
|
||||
|
||||
|
||||
Example for intent rule
|
||||
```json
|
||||
{
|
||||
"$type": "Microsoft.IntentRule",
|
||||
"intent": "AddItem",
|
||||
"steps": [
|
||||
"ToDoLuisBot.AddItem"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Example fo intent rule and setting entities (entities from recognizer)
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.IntentRule",
|
||||
"intent":"MyIntent",
|
||||
"entities": [ "user", "userName_patternAny"]
|
||||
}
|
||||
```
|
||||
|
||||
Example for IntentRule with only contraints
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.IntentRule",
|
||||
"intent":"MyIntent",
|
||||
"constraint":"turn.DialogEvent.Value.Entities.UserName != null || turn.DialogEvent.Value.Entities.UserName_patternAny != null"
|
||||
}
|
||||
```
|
||||
example for intenet rule with entieid and constrains
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.IntentRule",
|
||||
"intent":"MyIntent",
|
||||
"entities": [ "entityx", "entity"],
|
||||
"constraint":"turn.DialogEvent.Value.Entities.UserName != null || turn.DialogEvent.Value.Entities.UserName_patternAny != null"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Microsoft.UnKnownIntentRule rule
|
||||
The **Microsoft.UnKnownIntentRule** defines the steps to take when an utterence is not recognized (aka, the None Intent).
|
||||
NOTE: UnknownIntent will defer to any specific intent that fires in a parent dialog".
|
||||
|
||||
| Property | Description |
|
||||
|------------|-----------------------------------------------------------------------------|
|
||||
| steps | collection of dialogs/dialog steps to add to the plan if conditions are met |
|
||||
|
||||
Example
|
||||
```json
|
||||
{
|
||||
"$type": "Microsoft.UnknownIntentRule",
|
||||
"steps": [
|
||||
{
|
||||
"$type": "Microsoft.SendActivity",
|
||||
"activity": "To use thie bot..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Recognizers
|
||||
Recognizers are components which inspect input and generates intents and entities as output.
|
||||
|
||||
### Microsoft.LuisRecognizer
|
||||
The **Microsoft.LuisRecognizer** is a component for using luis.ai service to generate intents
|
||||
and entities.
|
||||
|
||||
| Property | Description |
|
||||
|---------------------------|--------------------|
|
||||
| applicationId | Application ID |
|
||||
| endpoint | Endpoint to use |
|
||||
| endpointKey | endpointKey to use |
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.LuisRecognizer",
|
||||
"applicationId":"12312313123",
|
||||
"endpoint":"http://../",
|
||||
"endpointKey":"123123123123"
|
||||
}
|
||||
```
|
||||
|
||||
### Microsoft.RegexRecognizer
|
||||
The **Microsoft.RegexRecognizer** is a component for using regular expressions to generate
|
||||
intents and entities.
|
||||
|
||||
| property | description |
|
||||
|----------|------------------------------------|
|
||||
| intents | Map of intentName -> regex pattern |
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.RegexRecognizer",
|
||||
"intents": {
|
||||
"Greeting":"/greeting/",
|
||||
"TellMeAjoke":".*joke.*",
|
||||
"Help":"/help/",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Eventing
|
||||
The AdaptiveDialog models input as Events called DialogEvents. This gives us a clean model for
|
||||
capturing and bubbling information such as cancellatio, requests for help, etc.
|
||||
While majority of events happens behind the scenes, you can participate by emitting events of your own.
|
||||
|
||||
### Microsoft.EmitEvent Step
|
||||
The **Microsoft.EmitEvent** step allows you to emit an event
|
||||
|
||||
| Property | Description |
|
||||
|-----------------|-----------------------------------------------------------------|
|
||||
| eventName (string) | The name of event to emit |
|
||||
| eventValue (object) | optional value to emit along with the event |
|
||||
| bubbleEvent (boolean) | if true this event should propagate to parent dialogs |
|
||||
|
||||
Example CallDialog using dialogid
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.EmitEvent",
|
||||
"eventName": "myEvent",
|
||||
"eventValue": "this is a cool event",
|
||||
"bubbleEvent" : "true"
|
||||
}
|
||||
```
|
||||
### Events
|
||||
Here are the events we have defined so far.
|
||||
|
||||
> NOTE: The event types and names are in flux and will probably change
|
||||
|
||||
| Event | Description |
|
||||
|---------------------|---------------------------------------------------|
|
||||
| BeginDialog | Fired when a dialog is start |
|
||||
| ActivityReceived | Fired when a new activity comes in |
|
||||
| RecognizedIntent | Fired when an intent is recognized |
|
||||
| UnknownIntent | Fired when an intent is not handled or recognized |
|
||||
| StepsStarted | Fired when a plan is started |
|
||||
| StepsSaved | Fires when a plan is saved |
|
||||
| StepsEnded | Fires when a plan successful ends |
|
||||
| StepsResumed | Fires when a plan is resumed from an interruption |
|
||||
| ConsultDialog | fired when consulting |
|
||||
| CancelDialog | fired when dialog canceled |
|
||||
|
||||
|
||||
|
||||
# Input/Prompt Dialogs
|
||||
Dialogs are used to model interactions with the user. Input/Prompt dialogs are dialogs which gather typed information with simple validation. All dialogs input are part *Microsoft.Bot.Builder.Dialogs.Adaptive.Input*
|
||||
|
||||
## Microsoft.TextInput Dialog
|
||||
The **Microsoft.TextInput** dialog is used to gather text input from user, with validation option and matches pattern.
|
||||
|
||||
| Property | Description |
|
||||
|-----------------|------------------------------------------------------------------------------------------|
|
||||
| property | the property this input dialog is bound to and the dialog will set at end of dialog |
|
||||
| pattern | and optional regex to validate input |
|
||||
| Prompt | a response, LG use is optional, sent to user to start the prompt |
|
||||
| retryPrompt | a response, LG use is optional, sent to prompt the user to try again |
|
||||
| noMatchResponse | a response, LG use is optional, sent to tell the user the value didn't match the pattern |
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.TextInput",
|
||||
"property": "user.name",
|
||||
"pattern":"[0-9a-zA-Z].*",
|
||||
"Prompt":"What is your name?",
|
||||
"retryPrompt":"Let's try again, what is your name?",
|
||||
"noMatchResponse":"That response didn't match the pattern"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Microsoft.IntegerInput Dialog
|
||||
The **Microsoft.IntegerInput** dialog is used to gather a integer input from the user.
|
||||
|
||||
| Property | Description |
|
||||
|------------------|----------------------------------------------------------------------------------------|
|
||||
| property | the property this input dialog is bound to |
|
||||
| minValue | The min value which is valid |
|
||||
| maxValue | The max value which is valid |
|
||||
| prompt | the LG response to start the prompt |
|
||||
| retryPrompt | the LG response to prompt the user to try again |
|
||||
| invalidPrompt | a response, LG use is optional, sent to tell the user the when value is not a number |
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.IntegerInput",
|
||||
"property": "user.age",
|
||||
"minValue": 0,
|
||||
"maxValue": 120,
|
||||
"prompt":"What is your age?",
|
||||
"retryPrompt":"Let's try again, what is your age?",
|
||||
"invalidPrompt":"I didn't recognize an age."
|
||||
}
|
||||
```
|
||||
|
||||
## Microsoft.FloatInput
|
||||
The **Microsoft.FloatInput** dialog is used to gather a float input from the user.
|
||||
|
||||
| Property | Description |
|
||||
|------------------|------------------------------------------------------------------------------------|
|
||||
| property | the property this input dialog is bound to |
|
||||
| minValue | The min value which is valid |
|
||||
| maxValue | The max value which is valid |
|
||||
| prompt | the LG response to start the prompt |
|
||||
| retryPrompt | the LG response to prompt the user to try again |
|
||||
| invalidPrompt | a response, LG use is optional, sent to tell the user when then input was not recognized or not valid for the input typ |
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.FloatInput",
|
||||
"property": "user.height",
|
||||
"minValue": 0.0,
|
||||
"maxValue": 3.0,
|
||||
"initialPrompt":"What is your height in meters?",
|
||||
"retryPrompt":"Let's try again, what is your height in meters?",
|
||||
"invalidPrompt":"I didn't recognize an number."
|
||||
}
|
||||
```
|
||||
|
||||
## Microsoft.ChoiceInput
|
||||
The **Microsoft.ChoiceInput** represents a dialog which gathers a choice responses
|
||||
|
||||
| Property | Description |
|
||||
|------------------|------------------------------------------------------------------------------------|
|
||||
| property | the property this input dialog is bound to |
|
||||
| prompt | the LG response to start the prompt |
|
||||
| retryPrompt | the LG response to prompt the user to try again |
|
||||
| invalidPrompt | a response, LG use is optional, sent to tell the user when then input was not recognized or not valid for the input typ |
|
||||
| style | the kind of choice list style to generate: Inline; List; SugestedActions; HeroCard |
|
||||
| choices | array representing possible values sent to the user |
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"$type": "Microsoft.ChoiceInput",
|
||||
"property": "user.pizzaSize",
|
||||
"choices": [
|
||||
{
|
||||
"value": "Small"
|
||||
},
|
||||
{
|
||||
"value": "Medium"
|
||||
},
|
||||
{
|
||||
"value": "Large"
|
||||
}
|
||||
],
|
||||
"prompt": "What size of pizza you want?",
|
||||
"retryPrompt": ""
|
||||
"style": "List",
|
||||
"alwaysPrompt": true
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## Microsoft.ConfirmInput
|
||||
The **Microsoft.ConfirmInput** This represents a dialog which gathers a yes/no style responses
|
||||
|
||||
| Property | Description |
|
||||
|------------------|------------------------------------------------------------------------------------|
|
||||
| property | the property this input dialog is bound to |
|
||||
| prompt | the LG response to start the prompt |
|
||||
| retryPrompt | the LG response to prompt the user to try again |
|
||||
| invalidPrompt | a response, LG use is optional, sent to tell the user when then input was not recognized or not valid for the input typ |
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"$type": "Microsoft.ConfirmInput",
|
||||
"property": "user.confirmed",
|
||||
"prompt": "Are you sure?",
|
||||
"retryPrompt": "let's try again, are you sure?",
|
||||
"invalidPrompt": "I didn't recognize a yes/no response",
|
||||
"alwaysPrompt": true
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
# Dialog Steps
|
||||
Dialog Steps are special dialog primitives which are used to control the flow of the conversation. Steps help put together the flow of conversation when a specific event is captured via a Rule. Note: unlike Waterfall dialog where each step is a function, each step in an Adaptive dialog is in itself. This enables Adaptive dialogs by design to have a much cleaner ability to handle and deal with interruptions. Adaptive dialogs support the following
|
||||
|
||||
## sending a response
|
||||
### Microsoft.SendActivity Step
|
||||
The **Microsoft.SendActivity** step gives you the ability to send an activity to the user. The activity can be a string, an inline LG template, or an actual Activity definition.
|
||||
|
||||
| Property | Description |
|
||||
|-------------------|----------------------------------------|
|
||||
| activity (string) | an inline LG template for the activity |
|
||||
| activity (object) | an Activity object definition |
|
||||
|
||||
Example with LG template inline
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.SendActivity",
|
||||
"activity":"Hi {user.name}. How are you?"
|
||||
}
|
||||
```
|
||||
|
||||
Example with activity, using the special typing indicator
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.SendActivity",
|
||||
"activity":
|
||||
{
|
||||
"type":"typing"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Example with LG template. You can use LG to send cards.
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.SendActivity",
|
||||
"activity":"[cardTemplate]"
|
||||
}
|
||||
```
|
||||
## Tracing and logging
|
||||
Set of declarative steps used to emit Bot Framework traces that get routed as a transcript and logging for the bot.
|
||||
|
||||
### Microsoft.TraceActivity Step
|
||||
The **Microsoft.TraceActivity** step sends an TraceActivity to the transcript.
|
||||
|
||||
| Property | Description |
|
||||
|-------------------------|----------------------------------------|
|
||||
| name (string) | name of the trace activity |
|
||||
| valueType (string) | Value type of the trace activity |
|
||||
| valueProperty (string) | Property path to memory object to send as the value of the trace activity |
|
||||
|
||||
Example
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.TraceActivity",
|
||||
"name" : "Trace1",
|
||||
"valyeType":"this is the actual value to be trace",
|
||||
"valueProperty" : "user.name"
|
||||
}
|
||||
```
|
||||
|
||||
## Memory manipulation
|
||||
Set of declarative steps used to declarativly manipulte bot's memory
|
||||
|
||||
### Microsoft.SaveEntity Step
|
||||
The **Microsoft.SaveEntity** saves a memory property as an entity - used to extract an entity returned by recognizer into memory.
|
||||
|
||||
| Property | Description |
|
||||
|-------------------------|--------------------------------------------------|
|
||||
| entity (string) | name of the entity to save activity |
|
||||
| property (string) | name of the property in memory to save th entity |
|
||||
|
||||
Example
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.SaveEntity",
|
||||
"entity" : "ToCity",
|
||||
"property" : "user.destination"
|
||||
}
|
||||
```
|
||||
|
||||
### Microsoft.EditArray Step
|
||||
The **Microsoft.EditArray** modifies an array in memory.
|
||||
|
||||
| Property | Description |
|
||||
|-------------------------|-----------------------------------------------------------------|
|
||||
| ChangeType | the array operation to perform: Push; Pop; Take; Remove; Clear |
|
||||
| arrayProperty | the name of the (target) aray in memory to manipulat |
|
||||
| itemProperty | Memory expression for the item use to update the array |
|
||||
|
||||
Example
|
||||
```json
|
||||
{
|
||||
"$type": "Microsoft.EditArray",
|
||||
"changeType": "Push",
|
||||
"arrayProperty": "user.lists.{dialog.listName}",
|
||||
"itemProperty": "dialog.item"
|
||||
},
|
||||
```
|
||||
|
||||
### Microsoft.InitProperty Step
|
||||
The **Microsoft.InitProperty** innitial a property to either an object or array.
|
||||
|
||||
| Property | Description |
|
||||
|-------------------------|-----------------------------------------------------------------|
|
||||
| property (string) | the memroy property to set |
|
||||
| type (string) | type of value to set the property to, object or array |
|
||||
|
||||
Example
|
||||
```json
|
||||
{
|
||||
"$type": "Microsoft.InitProperty",
|
||||
"property": "user.lists",
|
||||
"type": "array",
|
||||
},
|
||||
```
|
||||
|
||||
### Microsoft.SetProperty Step
|
||||
The **Microsoft.SetProperty** sets memory to the value of an expression.
|
||||
|
||||
| Property | Description |
|
||||
|-------------------------|-----------------------------------------------------------------|
|
||||
| property | the memroy property to set |
|
||||
| value | type of value to set the property |
|
||||
|
||||
Example
|
||||
```json
|
||||
{
|
||||
"$type": "Microsoft.SetProperty",
|
||||
"property": "user.age",
|
||||
"type": "-1",
|
||||
},
|
||||
```
|
||||
|
||||
### Microsoft.DeletProperty Step
|
||||
The **Microsoft.DeleteProperty** removes a property from memory.
|
||||
|
||||
| Property | Description |
|
||||
|-------------------------|-----------------------------------------------------------------|
|
||||
| property | the memroy property to remove |
|
||||
|
||||
Example
|
||||
```json
|
||||
{
|
||||
"$type": "Microsoft.DeleteProperty",
|
||||
"property": "user.age",
|
||||
},
|
||||
```
|
||||
|
||||
## Conversational flow and dialog management
|
||||
Set of steps to control the flow of a given set of steps, within a dialog, and steps to control a dialog.
|
||||
|
||||
### Microsoft.IfCondition Step
|
||||
The **Microsoft.IfCondition** step gives you the ability to inspect memory and **branch** between dialogs.
|
||||
|
||||
| Property | Description |
|
||||
|------------|-----------------------------------------------------------------------------------|
|
||||
| condition | a expression to evaluate |
|
||||
| steps | a dialogId, dialog, or array of dialogs (steps) to execute if expression is true |
|
||||
| elseSteps | a dialogId, dialog, or array of dialogs (steps) to execute if expression is true |
|
||||
|
||||
Example with LG template inline
|
||||
```json
|
||||
{
|
||||
"$type": "Microsoft.IfCondition",
|
||||
"condition": "user.age < 18 ",
|
||||
"steps": [
|
||||
"UnderAgeDialog"
|
||||
],
|
||||
"elseSteps" : [
|
||||
"UnderAgeDialog"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Microsoft.SwitchCondition Step
|
||||
The **Microsoft.SwitchCondition** step conditionally decides which step to execute next.
|
||||
|
||||
| Property | Description |
|
||||
|------------|-----------------------------------------------------------------------------------|
|
||||
| condition | a expression to evaluate |
|
||||
| cases | aray defining the set of steps to execute per case |
|
||||
| default | set of steps to execute for the default case |
|
||||
|
||||
example for a swtich condition on type of helps
|
||||
```json
|
||||
{
|
||||
"$type": "Microsoft.SwitchCondition",
|
||||
"condition": "user.helpType",
|
||||
"cases": {
|
||||
"Customer Support": [
|
||||
{
|
||||
"$type": "Microsoft.SendActivity",
|
||||
"activity": "Case Customer Support"
|
||||
}
|
||||
],
|
||||
"ecommarce": [
|
||||
{
|
||||
"$type": "Microsoft.SendActivity",
|
||||
"activity": "Case 2"
|
||||
}
|
||||
],
|
||||
"Other": [
|
||||
{
|
||||
"steps": [
|
||||
{
|
||||
"$type": "Microsoft.CallDialog",
|
||||
"dialog": "ecommarceDialog",
|
||||
"options": {
|
||||
"a": "a"
|
||||
},
|
||||
"property": "dialog.result"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"defult": [
|
||||
{
|
||||
"$type": "Microsoft.SendActivity",
|
||||
"activity": "Default"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Microsoft.BeginDialog Step
|
||||
The **Microsoft.BeginDialog** begins another dialog. When the new dialog completes, it will return to the caller.
|
||||
You can bind peopertyies to dialog, which the dialog will set before returning to the caller.
|
||||
|
||||
> NOTE: When the called dialog is completed, the caller will continue.
|
||||
|
||||
| Property | Description |
|
||||
|-----------------|-----------------------------------------------------------------|
|
||||
| property | the property in memory to store the result of the called dialog |
|
||||
| dialog (string) | the id (string) of a dialog to be called |
|
||||
| dialog (object) | an inline dialog definition to be called |
|
||||
|
||||
Example BeginDialog using dialogid
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.BeginDialog",
|
||||
"property": "user.address",
|
||||
"dialog": "GetAddressDialog"
|
||||
}
|
||||
```
|
||||
Example BeginDialog using inline dialog definition
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.BeginDialog",
|
||||
"property": "user.cat.name",
|
||||
"dialog": {
|
||||
"$type":"Microsoft.TextPrompt",
|
||||
"initialPrompt":"What is your cat's name?"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Microsoft.EndDialog Step
|
||||
The **Microsoft.EndDialog** step gives you the ability to **end** the calling dialog returning a result to caller.
|
||||
|
||||
> NOTE: EndDialog ends the *caller* and returns a value
|
||||
|
||||
| Property | Description |
|
||||
|----------|---------------------------------------------------------------------------------|
|
||||
| property | an expression against memory which will be returned as the result to the caller |
|
||||
|
||||
Example returning the dialog's .address property as the result of the dialog to the caller.
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.EndDialog",
|
||||
"property":"dialog.address"
|
||||
}
|
||||
```
|
||||
|
||||
### Microsoft.CancelAllDialogs Step
|
||||
The **Microsoft.CancelAllDialogs** step cancels all of the current dialogs by emitting an event that propogate through the dialog stack. This event can be caught (at each dialog) to prevent cancelation from propagating.
|
||||
|
||||
| Property | Description |
|
||||
|----------|---------------------------------------------------------------------------------|
|
||||
| eventName | Name of the event which is emitted |
|
||||
| eventValue | object value which is a payload to communicate to the parent dialogs so that they can decide how to process it |
|
||||
|
||||
|
||||
|
||||
### Microsoft.ReplaceDialog Step
|
||||
The **Microsoft.ReplaceDialog** step gives you the ability to **replace** the current dialog
|
||||
with another dialog and bind it's result to memory. Some dialogs don't have data binding built in, and GotoDialog gives you the
|
||||
ability to do that.
|
||||
|
||||
> NOTE: When the called dialog is completed, the caller will **NOT** continue as it has been replaced.
|
||||
|
||||
| Property | Description |
|
||||
|-----------------|-----------------------------------------------------------------|
|
||||
| dialog (string) | the id (string) of a dialog to be called |
|
||||
| options (object) | Options to pass to the dialog |
|
||||
| property (string) |The property to bind to the dialog and store the result in |
|
||||
|
||||
Example CallDialog using dialogid
|
||||
```json
|
||||
{
|
||||
"$type":"Microsoft.ReplaceDialog",
|
||||
"property": "user.address",
|
||||
"dialog": "GetAddressDialog"
|
||||
}
|
||||
```
|
||||
|
||||
## Custom code and HTTP request
|
||||
Even when using declarative form of dialogs, you can use custom code and make HTTP calls.
|
||||
|
||||
See CustomStep.dialog in Sample #13
|
||||
|
||||
## Microsoft.HttpRequest Step
|
||||
The **Microsoft.HttoRequest** step makes an http call
|
||||
|
||||
| Property | Description |
|
||||
|-----------------|-----------------------------------------------------------------|
|
||||
| method (string) | the HTTP method for the http call: GET; POST |
|
||||
| url (string) | The url to call (supports data binding) |
|
||||
| Body (object) | The body to send in the HTTP call (supports data binding) |
|
||||
| header (object) | Http headers to include with the HTTP request (supports data binding)t |
|
||||
| responseTypes (object) | Describes how to parse the response from the http request. If Activity or Activities, then the they will be sent to the user. |
|
||||
| property (string) | The property to store the result of the HTTP call in (as object or string) |
|
||||
|
||||
Example CallDialog using dialogid
|
||||
```json
|
||||
{
|
||||
"$type": "Microsoft.HttpRequest",
|
||||
"url": "http://petstore.swagger.io/v2/pet",
|
||||
"method": "POST",
|
||||
"header": {
|
||||
"test": "test",
|
||||
"test2": "test2"
|
||||
},
|
||||
"body": {
|
||||
"id": "{dialog.petid}",
|
||||
"category": {
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
},
|
||||
"name": "{dialog.petname}",
|
||||
"photoUrls": [ "string" ],
|
||||
"tags": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
}
|
||||
],
|
||||
"status": "available"
|
||||
},
|
||||
"property": "dialog.postResponse"
|
||||
},
|
||||
```
|
|
@ -0,0 +1,60 @@
|
|||
# Adaptive Dialog
|
||||
|
||||
Pre-read: [Dialogs library][1] in Bot Builder V4 SDK.
|
||||
|
||||
Dialogs are a central concept in the SDK, and provide a useful way to manage a conversation with the user. Bot Builder V4 SDK offers waterfall, prompts and component dialogs as the 3 core types.
|
||||
|
||||
As a quick recap
|
||||
- Prompts provide an easy way to ask user for information and evaluate their response. You can use a specific type of prompt e.g. number prompt if you are looking to collect a number from user etc.
|
||||
- Waterfall dialogs help you sequentially execute a set of steps that enable you to collect information from user. Each waterfall step is an asynchronous function. Often, waterfall steps include a series of prompts to the user to collect information in a linear order.
|
||||
- Component dialogs help build re-usable dialogs each of which have their own dialog set, and helps avoid name collisions with the dialog set that consumes it.
|
||||
|
||||
Current set of dialog types offered by Bot Builder V4 SDK put you in control of managing your bot's conversations however they also require me to write a bunch of boiler plate code for sophisticated conversation modelling concepts like building a dialog dispatcher, ability handle interruptions elegantly and to build a pluggable and extensible dialog system.
|
||||
|
||||
The new **Adaptive dialog** and the event model simplify sophisticated conversation modelling primitives, eliminate much of the boiler plate code and helps you focus on the model of the conversation rather than the mechanics of dialog management.
|
||||
|
||||
See [here](./memoryRulesSteps.md) to learn more about memory, adaptive dialog constructs.
|
||||
|
||||
***Adaptive dialogs*** at the core comprise of 4 main concepts -
|
||||
- _Recognizers_ help understand user input. You use recognizers to extract meaningful pieces of information from user's input. All recognizers emit events - of specific interest is the 'recognizedIntent' event that fires when the recognizer picks up an intent (or extracts entities) from given user utterance. Adaptive Dialogs support the following recognizers -
|
||||
- RegEx recognizer
|
||||
- LUIS recognizer
|
||||
- Multi-language recogizer
|
||||
- _Rules_ enable you to catch and respond to events. The broadest rule is the EventRule that allows you to catch and attach a set of steps to execute when a specific event is emitted by any sub-system. Adaptive dialogs support the following Rules -
|
||||
- EventRule - catch and respond to a specific event.
|
||||
- IntentRule - catch and respond to 'recognizedIntent' event emitted by a recognizer.
|
||||
- UnknownIntentRule - is used to catch and respond to a case when a 'recognizedIntent' event was not caught and handled by any of the other rules. This is especially helpful to capture and handle cases where your dialog wishes to participate in consultation.
|
||||
- _Steps_ help put together the flow of conversation when a specific event is captured via a Rule. **_Note:_** unlike Waterfall dialog where each step is a function, each step in an Adaptive dialog is in itself a dialog. This enables adaptive dialogs by design to have a much cleaner ability to handle and deal with interruptions. Adaptive dialogs support the following steps -
|
||||
- Sending a response
|
||||
- SendActivity
|
||||
- Tracing and logging
|
||||
- TraceActivity
|
||||
- LogStep
|
||||
- Memory manipulation
|
||||
- SaveEntity - used to extract an entity returned by recognizer into memory.
|
||||
- EditArray
|
||||
- InitProperty
|
||||
- SetProperty - used to set a property's value in memory. See [here](../CommonExpressionLanguage) to learn more about expressions.
|
||||
- DeleteProperty
|
||||
- Conversational flow and dialog management
|
||||
- IfCondition - used to evaluate an expression. See [here](../CommonExpressionLanguage) to learn more about expressions.
|
||||
- SwitchCondition
|
||||
- EndTurn
|
||||
- BeginDialog
|
||||
- EndDialog
|
||||
- CancelAllDialog
|
||||
- ReplaceDialog
|
||||
- RepeatDialog
|
||||
- Eventing
|
||||
- EmitEvent
|
||||
- Roll your own code
|
||||
- CodeStep
|
||||
- HttpRequest
|
||||
- _Inputs_ are wrappers around [prompts][2] that you can use in an adaptive dialog step to ask and collect a piece of input from user, validate and accept it into memory. Inputs include these additional features - Accepts a property to bind to off the new V3 style memory scope in V4. Performs existential check before prompting. Grounds input to the specified property if the input from user matches the type of entity expected. Accepts constraints - min, max, etc. Adaptive dialogs support the following inputs -
|
||||
- TextInput
|
||||
- ChoiceInput
|
||||
- ConfirmInput
|
||||
- NumberInput
|
||||
|
||||
[1]:https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-dialog?view=azure-bot-service-4.0
|
||||
[2]:https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-dialog?view=azure-bot-service-4.0#prompts
|
|
@ -0,0 +1,170 @@
|
|||
# Adaptive Dialog and prompt wrappers BOM - //BUILD 2019
|
||||
**Ship vehicle:** 4.x-preview
|
||||
**Target code complete:** 4/5/2019
|
||||
|
||||
**Story arc**: _As a bot developer, I’ve been using the prompt, waterfall and component dialog systems available in V4. These absolutely put me in control of managing my bot's conversations however they also require me to write a bunch of boiler plate code for sophisticated conversation modelling concepts like building a dialog dispatcher, ability handle interruptions elegantly and to build a pluggable and extensible dialog system._
|
||||
|
||||
_The new Adaptive dialog and the event model simplify sophisticated conversation modelling primitives, eliminate much of the boiler plate code and helps me focus on the model of the conversation rather than the mechanics of dialog management_
|
||||
|
||||
## Remaining work
|
||||
- - [x] ~~Close on scope of work for //BUILD for Adaptive dialogs - [recognizers](#Recognizers), [steps](#Steps), [rules](#Rules), [interruption handling](#Interrpution-handling) supported; [prompt wrappers](#Prompt-wrappers)~~
|
||||
- - [x] ~~Close on naming for rules, steps, prompt wrappers and interruption handling scopes~~
|
||||
- - [x] ~~Close on scope of prompt wrappers~~
|
||||
- ~~C# implementation introduces properties on existing prompts. TS does not have any implementation of the new properties~~
|
||||
- ~~TS added new prompt++ (suffix input) that does binding to memory as well as existential check before prompting. C# does not appear to do any existential checks~~
|
||||
- ~~C# has float prompt added while TS does not have this.~~
|
||||
- - [ ] Breaking change for OnContinueDialogAsync - roll back breaking change. [Steve]
|
||||
- - [ ] Redo of consultation and event bubbling [Steve]
|
||||
- - [ ] Alignment on Bot + Run method. C# needs DialogManager [Tom; 4/16]
|
||||
- - [ ] Prompting into turn scope - event payload values; activity [Tom; 4/17]
|
||||
- - [ ] Document and ship debugger [Vishwac + Tom]
|
||||
- - [ ] Input DCR on C# [Tom; Carlos]
|
||||
- - [ ] ~~make sure card recognizer is part of adaptive on C# side.~~ [Tom]
|
||||
- - [ ] ~~Typescript~~
|
||||
- - [ ] Packages for npm; daily updates of packages
|
||||
- - [ ] Close on support for Switch...Case..Default step. Exists in C# but not in TS. [Tom and Steve]
|
||||
- - [x] LG and common expression language integration on TS. [Steve]
|
||||
- - [ ] Typeloader and resource explorer for TS [Carlos; ETA 4/17]
|
||||
- - [ ] QnADialog step [Steve]
|
||||
- - [ ] langauge generation renderer [Carlos]
|
||||
- - [ ] TextMessageActivityGenerator [Carlos]
|
||||
- - [ ] ActivityTemplate [Carlos]
|
||||
- - [ ] Functional parity across C# and TS for planned set of steps, rules, interruption handling and prompt wrappers
|
||||
- - [ ] Class level consistency
|
||||
- - [ ] Property, Methods and method signatures are consistent
|
||||
- - [ ] Functionally consistent
|
||||
- - [ ] [Documentation](#Documentation)
|
||||
- - [ ] [Samples](#Samples)
|
||||
|
||||
Deferred to post //BUILD
|
||||
- - [ ] Move dialog internal state to a dialog_internal or dialogInternal scope and not have this under 'dialog' scope.
|
||||
- - [ ] LG integration per Adaptive dialog via outputGeneration. Model this similar to recognizer.
|
||||
### Post //BUILD
|
||||
- - [ ] Move dialog internal state to a dialog_internal or dialogInternal scope and not have this under 'dialog' scope.
|
||||
- - [ ] Inputs
|
||||
- - [ ] dateInput
|
||||
- - [ ] timeInput
|
||||
- - [ ] attachmentInput
|
||||
|
||||
### Recognizers
|
||||
|
||||
We will support the following recognizers in Adaptive dialogs
|
||||
|
||||
| Recognizer type | C# | TS |
|
||||
|--------------------------|------------------------|------------------------|
|
||||
| RegexRecognizer |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| MultiLanguageRecognizer |<ul><li>- [x] </li></ul>|<ul><li>- [ ] </li></ul>|
|
||||
| LuisRecognizer |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| ~~QnARecognizer~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>|
|
||||
|
||||
|
||||
### Rules
|
||||
|
||||
**Rules** in scope for //BUILD
|
||||
|
||||
| Rule name | C# | TS | Comments |
|
||||
|-------------------------------|------------------------|------------------------|---------------------------------------------------------------------------------------------------------|
|
||||
| unrecognizedIntentRule |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| rename DefaultRule -> NoMatchRule -> noneIntentRule -> unrecognizedIntentRule |
|
||||
| EventRule |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| IfPropertyRule |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| Table this - follow up; command? |
|
||||
| IntentRule |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| ~~WelcomeRule~~ |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| AdaptiveRule (base class) |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| rename rule -> AdaptiveRule and get rid of IRule |
|
||||
| ~~BeginDialogRule~~ |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| achieve via top level property as peer to rule that covers the initial set of steps when dialog begins. |
|
||||
| ~~StateTransitionRule~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| ~~ReplacePlanRule~~ |<ul><li>- [x] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
| ~~UtteranceRecognizerRule~~ |<ul><li>- [x] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
| ~~ActivityRule~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
|
||||
### Steps
|
||||
|
||||
**Steps** in scope for //BUILD
|
||||
|
||||
| Step name | C# | TS | Comments |
|
||||
|-----------------------|------------------------|------------------------|---------------------------------------------------------------------|
|
||||
| BeginDialog |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| CallDialog -> BeginDialog |
|
||||
| EndDialog |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| ReplaceDialog |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| GotoDialog -> ReplaceWithDialog |
|
||||
| CancelDialog |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| RepeatDialog |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| CodeStep |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| EditArray |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| ChangeList -> EditArray; move to functions in expression language|
|
||||
| SetProperty |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| DeleteProperty |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| ClearProperty -> DeleteProperty |
|
||||
| IfCondition |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| IfProperty -> IfCondition |
|
||||
| SwitchCondition |<ul><li>- [x] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
| HttpRequest |<ul><li>- [x] </li></ul>|<ul><li>- [ ] </li></ul>| Post //BUILD - Ability for service to return activity json; logic for automatically sending typing activity after Xms |
|
||||
| SendActivity |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| EmitEvent |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| EmitEvents -> EmitEvent |
|
||||
| EndTurn |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| WaitForInput -> EndTurn |
|
||||
| ~~EditSteps~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| Should allow plan push, pop, insert at position |
|
||||
| ReplaceSteps |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| QnADialog |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
| SaveEntity |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| SetProperty - '@EntityName' resolves to turn.entities.EntityName[0] |
|
||||
| ~~EditPlanTitle~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| SetPlanTitle -> EditPlanTitle |
|
||||
| ~~OnCatch~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| ~~ChangeCollection~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| use setproperty for objects/map |
|
||||
| ~~IfNotProperty~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| ~~DoStepsBeforeTags~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| If we bring them back, we should align with EditPlan.. |
|
||||
| ~~DoStepsLater~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| ~~ForEach~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| ~~ForEachPage~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| ~~SendCharts~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| Do a sample with this to demonstrate a custom step. |
|
||||
| ~~SendList~~ |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
|
||||
### Prompt wrappers
|
||||
|
||||
We will add new \<entityType\>Input class that does the follwing -
|
||||
1. Accepts a property to bind to off the new V3 style memory scope in V4
|
||||
2. Performs existential check before prompting
|
||||
3. Grounds input to the specified property if the input from user machines the type of entity expected.
|
||||
4. Accepts constraints - min, max, ...
|
||||
|
||||
| Input type | C# | TS | Comments |
|
||||
|-----------------------|------------------------|------------------------|-------------------------------------|
|
||||
| confirmInput |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| boolInput -> confirmInput |
|
||||
| choiceInput |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| numberInput |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| textInput |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| ~~dateInput~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
| ~~timeInput~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
| ~~attachmentInput~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
| ~~OAuthPrompt~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
| ~~ActivityPrompt~~ |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
|
||||
### Interrpution handling
|
||||
|
||||
CUT PlanChangeType off rule.
|
||||
|
||||
<strike>**Interruption plan change types** in scope for //BUILD
|
||||
|
||||
| Interruption handling | C# | TS |
|
||||
|-------------------------------|------------------------|------------------------|
|
||||
| doSteps |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| doStepsBeforeTags |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| doStepsLater |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| endPlan |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| newPlan |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| replacePlan |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
</strike>
|
||||
|
||||
|
||||
### Documentation
|
||||
- [ ] API reference doc
|
||||
- [ ] List all API signatures with example invocation code snippets for C# and TS
|
||||
- [ ] Conceptual document
|
||||
- [ ] Introduces Adaptive dialog
|
||||
- [ ] Lists use cases for Adaptive dialog. When would you use adaptive .vs. waterfall .vs. component .vs. roll your own
|
||||
|
||||
### Samples
|
||||
|
||||
| Sample bot | C# | TS |
|
||||
|-------------------------------|------------------------|------------------------|
|
||||
| Core bot |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>|
|
||||
| To-do bot with regex |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>|
|
||||
| To-do bot with LUIS |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>|
|
||||
| To-do bot with interruptions |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>|
|
||||
| To-do bot with QnA |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>|
|
||||
| Cafe Bot |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>|
|
||||
| VA template |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>|
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
# Declarative Dialog and Prompts BOM - //BUILD 2019
|
||||
**Doc status: draft (review is needed)**
|
||||
|
||||
**Ship vehicle:** 4.x-preview
|
||||
|
||||
**Target code complete:** 4/5/2019
|
||||
|
||||
**Story arc**: _As a developer, I want to create a sophisticated conversation using the new Adaptive Dialog and Prompts and express them in a declarative form. The a declarative form (JSON) has a 1:1 mapping to core SDK concepts and represents SDK objects. As a develoepr, I can use the declarative form to represent dialgos in programing langauge agnostic way and transfar them between bots/ systems._
|
||||
|
||||
## Remaining work
|
||||
- [] Update C# schemas to the latest names and drive consistency across C# and jS
|
||||
- [] Implement TypeLoader for Javascript (TS) to parity with C# (supporting .lg, .lu, .dialog)
|
||||
- [] Update JS schema to latest names and drive concistency acorss JS and C#
|
||||
- [] Identify, review and agree on scope of SDK objects exposed by declarative schemas
|
||||
- [] Update CLI tools (DialogSchema and DialogLint) to match latest schema updates
|
||||
- [] [Documenation](#Documentation)
|
||||
- [] [Samples](#Samples)
|
||||
|
||||
|
||||
### Recognizers
|
||||
|
||||
We will support the following recognizers in declarative form
|
||||
|
||||
| Recognizer type | Schema |
|
||||
|--------------------------|------------------------|
|
||||
| RegexRecognizer |<ul><li>- [x] </li></ul>|
|
||||
| MultiLanguageRecognizer |<ul><li>- [x] </li></ul>|
|
||||
| LuisRecognizer |<ul><li>- [x] </li></ul>|
|
||||
| QnARecognizer |<ul><li>- [ ] </li></ul>|
|
||||
|
||||
### Rules
|
||||
|
||||
|
||||
**Rules** in scope for //BUILD
|
||||
|
||||
We will support the following rules (within Adaptive Dialog) in declarative form
|
||||
|
||||
| Rule name | Schema | Comments |
|
||||
|-------------------------------|------------------------|---------------------------------------------------------------------------------------------------------|
|
||||
| NoMatchRule |<ul><li>- [x] </li></ul>| |
|
||||
| EventRule |<ul><li>- [x] </li></ul>| |
|
||||
| IfPropertyRule |<ul><li>- [x] </li></ul>| |
|
||||
| IntentRule |<ul><li>- [x] </li></ul>| |
|
||||
| WelcomeRule |<ul><li>- [x] </li></ul>| |
|
||||
| AdaptiveRule (base class) |<ul><li> NA </li></ul>| Not being used in declarative form |
|
||||
|
||||
|
||||
**Declarative Dialogs** in scope for //Build
|
||||
|
||||
| Dialog name | Schema | Comments |
|
||||
|-------------------------------|------------------------|---------------------------------------------------------------------------------------------------------|
|
||||
| AdaptiveDialog |<ul><li>- [x] </li></ul>| The only supported dialog in declarative form? |
|
||||
|
||||
|
||||
### Prompt
|
||||
|
||||
**Input wrappers** in scope for //BUILD
|
||||
|
||||
We will support the following input wrappers (over SDK prompts) in declarative form.
|
||||
|
||||
| Input type | Schema | Comments |
|
||||
|-----------------------|------------------------|-----------------------------------------------|
|
||||
| confirmInput |<ul><li>- [x] </li></ul>| boolInput -> confirmInput |
|
||||
| choiceInput |<ul><li>- [ ] </li></ul>| |
|
||||
| NumberInput |<ul><li>- [ ] </li></ul>| Lock on which number/int/flot input we support|
|
||||
| IntegerInput |<ul><li>- [x] </li></ul>| |
|
||||
| FloatInput |<ul><li>- [x] </li></ul>| |
|
||||
| textInput |<ul><li>- [x] </li></ul>| |
|
||||
| dateInput |<ul><li>- [ ] </li></ul>| |
|
||||
| timeInput |<ul><li>- [ ] </li></ul>| |
|
||||
| attachmentInput |<ul><li>- [ ] </li></ul>| |
|
||||
|
||||
|
||||
### Steps
|
||||
|
||||
**Steps** in scope for //BUILD
|
||||
|
||||
| Step name | Schema | Comments |
|
||||
|-----------------------|------------------------|---------------------------------------------------------------------|
|
||||
| BeginDialog |<ul><li>- [x] </li></ul>| |
|
||||
| EndDialog |<ul><li>- [x] </li></ul>| |
|
||||
| ReplaceWithDialog |<ul><li>- [x] </li></ul>| |
|
||||
| CancelDialog |<ul><li>- [x] </li></ul>| |
|
||||
| RepeatWithDialog |<ul><li>- [ ] </li></ul>| |
|
||||
| CodeStep |<ul><li>- [ ] </li></ul>| Do we want to support for Declarative (if so when?) |
|
||||
| EditArray |<ul><li>- [x] </li></ul>| |
|
||||
| SaveEntity |<ul><li>- [x] </li></ul>| |
|
||||
| SetProperty |<ul><li>- [x] </li></ul>| Need to figure right name compare to SaveEntity/SetProperty |
|
||||
| DeleteProperty |<ul><li>- [x] </li></ul>| Need to figure right name compare to SaveEntity |
|
||||
| IfCondition |<ul><li>- [x] </li></ul>| |
|
||||
| HttpRequest |<ul><li>- [x] </li></ul>| |
|
||||
| SendActivity |<ul><li>- [x] </li></ul>| |
|
||||
| EmitEvent |<ul><li>- [ ] </li></ul>| Do we want to support this in declarative? |
|
||||
| EndTurn |<ul><li>- [x] </li></ul>| |
|
||||
| SwitchCondision |<ul><li>- [ ] </li></ul>| |
|
||||
|
||||
|
||||
|
||||
### Prompt wrappers
|
||||
|
||||
| Input type | C# | TS | Comments |
|
||||
|-----------------------|------------------------|------------------------|-------------------------------------|
|
||||
| confirmInput |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| boolInput -> confirmInput |
|
||||
| choiceInput |<ul><li>- [ ] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| numberInput |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| textInput |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>| |
|
||||
| dateInput |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
| timeInput |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
| attachmentInput |<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| |
|
||||
|
||||
|
||||
|
||||
### Documentation
|
||||
- [ ] Conceptual document
|
||||
- - [ ] Declarative represenation of dilaogs (schema, memory, expressions, rules, steps)
|
||||
- - [ ] Top level schema overview ($Type; $Copy; etc.)
|
||||
- - [ ] Object and Type loading
|
||||
- - [ ] Refernces to LG and Adaptive Dialog
|
||||
- [ ] Schema specification
|
||||
- - [ ] Include inline of supported schema types (point to git vs docs?)
|
||||
|
||||
### Samples
|
||||
TBD
|
||||
Declarative sample per type(?)
|
|
@ -0,0 +1,71 @@
|
|||
# Language Generation BOM - //BUILD 2019
|
||||
**Ship vehicle:** 4.x-preview
|
||||
**Target code complete:** 4/15/2019
|
||||
|
||||
**Story arc**: _As a bot developer, I’ve been used to hard coding bot responses and related resources. With .LG file format, MSLG CLI tool, LG resolver runtime, common expression library I can completely de-couple language resources for my bot and manage them in separate files like I have been doing for LU. With that I can now make my bot sound more natural and lively._
|
||||
|
||||
## Remaining work
|
||||
- - [X] Find new home for LanguageGenerationRenderer, LGLanguageGenerator
|
||||
- - [X] Expression analyzer (CCI ask) – we will just provide parse tree + sample. Nothing baked into the library
|
||||
- - [X] Wrap up C# and JS libraries – improved library error and exception bubbling, actionable and informative exception messages.
|
||||
- - [ ] Parse, collate and translate TS/ JS library that can be surfaced through a CLI tool (or consumed by an UI based authoring experience)
|
||||
- - [X] Expose parse functionality through a CLI shell (snap to new one CLI spec from Eyal)
|
||||
- - [X] Expose collate
|
||||
- - [ ] Expose translate [P1]
|
||||
- - [X] Support get all parsedTemplate and combine with AnalyzeTemplate API, user can get all template analyzing results
|
||||
- - [X] Support handle multiple files in TemplateEngine
|
||||
- - [X] Update implementation to match IF .. ELSEIF instead of the current SWITCH label. [Spec](https://microsoft-my.sharepoint.com/:w:/p/vkannan/ERMS_VL3nEBIhNwlgYAmv-8BIUP3WCM3-XSY-fETqjFOxw?e=0f8zYA)
|
||||
- - [ ] [Post //BUILD] ~~Add support for SWITCH .. CASE construct in conditional response template. [Spec](https://microsoft-my.sharepoint.com/:w:/p/vkannan/ERMS_VL3nEBIhNwlgYAmv-8BIUP3WCM3-XSY-fETqjFOxw?e=0f8zYA)~~
|
||||
- - [ ] Final API shape review
|
||||
- - [ ] Final packaging, naming review
|
||||
- - [ ] On board to build and release DevOps pipeline
|
||||
- - [ ] [Documentation](#Documentation)
|
||||
- - [ ] [Samples](#Samples)
|
||||
|
||||
### Functional parity across C# and TS
|
||||
|
||||
| Class | C# | TS |
|
||||
|------------------------------|------------------------|------------------------|
|
||||
| TextMessageActivityGenerator |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| Analyzer |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| Evaluator |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| ExpressionAnalyzerVisitor |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| GetMethodExtension |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| LanguageGenerationRenderer |<ul><li>- [x] </li></ul>|<ul><li>- [ ] </li></ul>|
|
||||
| LGLanguageGenerator |<ul><li>- [x] </li></ul>|<ul><li>- [ ] </li></ul>|
|
||||
| StaticChecker |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| TemplateEngine |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| ErrorListener |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| LGTemplate |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| LGFileParserVisitor |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
| LGFileParserListener |<ul><li>- [x] </li></ul>|<ul><li>- [x] </li></ul>|
|
||||
|
||||
### Documentation
|
||||
- [ ] API reference doc
|
||||
- [ ] List all API signatures with example invocation code snippets for C# and TS
|
||||
- [x] Conceptual document
|
||||
- - [x] Language Generation concepts overview
|
||||
- - [x] List scenarios based use cases for Language Generation
|
||||
- - [x] Ability to specify cards via Language Generation
|
||||
- - [x] Ability to specify speak .vs. display variation via Languge Generation
|
||||
- - [x] Resoure manager and langauge fall back policies
|
||||
- - [x] Grammar correction and other generation capabilites
|
||||
- [x] .LG file format specification
|
||||
- - [x] Include inline .LG file snippets as example for each concept
|
||||
### Samples
|
||||
|
||||
|C#|TS| Sample bot | Scenarios | LG capabilities to demo | Notes | Bot/LG Template |
|
||||
|--|--|---------------|------------|--------------------------|-------|-----------------|
|
||||
|<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| MultiTurn Prompt | Welcome, ask for name, confirm name, ask for age, confirm age, Summary |1. Pass variables to template Template 2. Template reference - Summary template can reference to name/age confirmation | | template |
|
||||
|<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| Card bot | Send 8 different card types | Define cards in a template | | Template |
|
||||
|<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| Adaptive card bot | Send adaptive card | Define adaptive card in a template | |Template|
|
||||
|<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| Suggested action bot | Send suggested action |Define suggested action in a template | | Template|
|
||||
|<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| Core bot | Core bot template |No new function. Reference code to use various templates | | Optional|
|
||||
|<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>| Multi-language | Support multi-language | Use bot resoure manager and languge fall back policy | | Bot |
|
||||
|<ul><li>- [ ] </li></ul>|<ul><li>- [ ] </li></ul>|Cafe bot | Full blown cafe bot that shows sohpisticated LG use, LG for QnA pairs | All LG concepts | | Bot |
|
||||
|
||||
## Post BUILD backlog
|
||||
- - [ ] Support for SWITCH .. CASE .. DEFAULT in conditional response templates
|
||||
- - [ ] Support for file scoped template reference in evaluation/ expansion
|
||||
- - [ ] Support for external file references with json card definitions (Steve Ickman's suggestion)
|
||||
- - [ ] Plugin to telemetry pipeline for bot analytics.
|
|
@ -0,0 +1,63 @@
|
|||
# Common Expression Language BOM - //BUILD 2019
|
||||
**Ship vehicle:** 4.x-preview
|
||||
**Target code complete:** 4/15/2019
|
||||
|
||||
**Story arc**: _As a developer, I understand the value the common expression language provides and can use it across the Bot Builder Core SDK components including language generation & declarative dialogs._
|
||||
|
||||
## Remaining work
|
||||
- - [X] Implement Common Expression Language [Spec](https://microsoft.sharepoint.com/:w:/t/ConversationalAI785/EfIx5-gPhE5HlAGhvNEoKLIBo0AeoWmq1ITRhai2q2trLA?e=x9uKyb)
|
||||
- - [X] Rewrite parser using ANTLR
|
||||
- - [X] Implement R0 set of pre-built functions for C# and JS
|
||||
- - [X] Migrate to new style C#
|
||||
- - [X] Migrate to new style JS
|
||||
- - [X] Implement support for short hand entity resolution - $entityName, #entityName, @entityName
|
||||
- - [X] Close on JSON .vs. native object support in expression language
|
||||
- - [X] Pick up new changes from Chris McConnell on expression evaluate, parse tree walk
|
||||
- - [X] Wire up expression language in LG subsystem
|
||||
- - [X] Wire up expression language support in Adaptive dialog rules and steps
|
||||
- - [X] Add support for explicit values with both 'value' and "value". [Spec](https://microsoft.sharepoint.com/:w:/t/ConversationalAI785/EfIx5-gPhE5HlAGhvNEoKLIBo0AeoWmq1ITRhai2q2trLA?e=zX8HSY)
|
||||
- - [ ] New pre-built functions ask
|
||||
- - [X] [4/11] forEach(collection, iterator, expression)
|
||||
- - [ ] [Post //BUILD] match(regExp)
|
||||
- - [X] [4/11] lgTemplate(templateName, arg1, arg2,...) - drop support for @{[]}
|
||||
- - [ ] property(scope, expression) evaluates to scope.<expressionResult>
|
||||
- - [ ] [4/11] Drop support for object manipulation functions (json, addProperty, setProperty, removeProperty) from expression library - from doc. Vishwac.
|
||||
- - [ ] [4/11] Document exists function - Vishwac.
|
||||
- - [ ] [4/11] Support for truthiness on a property - e.g. '#HaveUserName' should evaluate to true if turn.intents.HaveUserName exists.
|
||||
- - [ ] Final API shape review
|
||||
- - [ ] Final packaging, naming review
|
||||
- - [ ] On board to build and release DevOps pipeline
|
||||
- - [ ] [Documentation](#Documentation)
|
||||
- - [ ] [Samples](#Samples)
|
||||
|
||||
### Functional parity across C# and TS
|
||||
|
||||
| Class | C# | TS |
|
||||
|---------------------------|------------------------|------------------------|
|
||||
| **Exression** | | |
|
||||
| BuiltInFunctions |<ul><li>- [X] </li></ul>|<ul><li>- [X] </li></ul>|
|
||||
| Constants |<ul><li>- [X] </li></ul>|<ul><li>- [X] </li></ul>|
|
||||
| Expression |<ul><li>- [X] </li></ul>|<ul><li>- [X] </li></ul>|
|
||||
| ExpressionEvaluator |<ul><li>- [X] </li></ul>|<ul><li>- [X] </li></ul>|
|
||||
| ExpressionType |<ul><li>- [X] </li></ul>|<ul><li>- [X] </li></ul>|
|
||||
| Extensions |<ul><li>- [X] </li></ul>|<ul><li>- [X] </li></ul>|
|
||||
| IExpressionParser |<ul><li>- [X] </li></ul>|<ul><li>- [X] </li></ul>|
|
||||
| **Epxression.Parser** | | |
|
||||
| ExpressionEngine |<ul><li>- [X] </li></ul>|<ul><li>- [X] </li></ul>|
|
||||
| ErrorListener |<ul><li>- [X] </li></ul>|<ul><li>- [X] </li></ul>|
|
||||
|
||||
### Documentation
|
||||
- [ ] [4/11] API reference doc - Dong
|
||||
- [ ] List all API signatures with example invocation code snippets for C# and TS
|
||||
- [x] Conceptual document
|
||||
- [x] Introduces common expression language
|
||||
- [x] Lists use cases for common expression language in Bot Builder
|
||||
- [x] Expression language specification
|
||||
- [x] Pre-built functions documentation with examples, function signatures
|
||||
|
||||
### Samples
|
||||
No samples are planned that are specific to expression language library since this by preview is not intended to be used as a standalone library.
|
||||
- - [ ] Include pointers to samples that use expressison lanauge in
|
||||
- Language Generation samples
|
||||
- Adaptive Dialog samples
|
||||
- Declarative Dialog samples
|
|
@ -0,0 +1,70 @@
|
|||
# API reference for Expression
|
||||
|
||||
### ExpressionEngine Class
|
||||
|
||||
#### Constructors
|
||||
```C#
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="lookup">If present delegate to lookup evaluation information from type string.</param>
|
||||
public ExpressionEngine(EvaluatorLookup lookup = null)
|
||||
```
|
||||
#### Methods
|
||||
```C#
|
||||
/// <summary>
|
||||
/// Parse the input into an expression.
|
||||
/// </summary>
|
||||
/// <param name="expression">Expression to parse.</param>
|
||||
/// <returns>Expresion tree.</returns>
|
||||
public Expression Parse(string expression)
|
||||
```
|
||||
|
||||
### Expression Class
|
||||
|
||||
#### Fields
|
||||
```C#
|
||||
/// <summary>
|
||||
/// Type of expression.
|
||||
/// </summary>
|
||||
public string Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Evaluator of this expression
|
||||
/// </summary>
|
||||
public ExpressionEvaluator Evaluator { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Children expressions.
|
||||
/// </summary>
|
||||
public Expression[] Children { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Expected result of evaluating expression.
|
||||
/// </summary>
|
||||
public ReturnType ReturnType => Evaluator.ReturnType;
|
||||
```
|
||||
|
||||
#### Contructor
|
||||
```C#
|
||||
/// <summary>
|
||||
/// Expression constructor.
|
||||
/// </summary>
|
||||
/// <param name="type">Type of expression from <see cref="ExpressionType"/>.</param>
|
||||
/// <param name="evaluator">Information about how to validate and evaluate expression.</param>
|
||||
/// <param name="children">Child expressions.</param>
|
||||
public Expression(string type, ExpressionEvaluator evaluator = null, params Expression[] children)
|
||||
```
|
||||
|
||||
#### Methods
|
||||
|
||||
```C#
|
||||
/// <summary>
|
||||
/// Evaluate the expression.
|
||||
/// </summary>
|
||||
/// <param name="state">
|
||||
/// Global state to evaluate accessor expressions against. Can be <see cref="IDictionary{String}{Object}"/>, <see cref="IDictionary"/> otherwise reflection is used to access property and then indexer.
|
||||
/// </param>
|
||||
/// <returns>Computed value and an error string. If the string is non-null, then there was an evaluation error.</returns>
|
||||
public (object value, string error) TryEvaluate(object state)
|
||||
```
|
|
@ -0,0 +1,68 @@
|
|||
# Common Expression Language Concepts
|
||||
|
||||
Bots, like any other application, require use of expressions to evaluate outcome of a condition based on runtime information available in memory or to the dialog or the language generation system.
|
||||
|
||||
Common expression language was put together to address this core need as well as to rationalize and snap to a common expression language that will be used across Bot Builder SDK and other conversational AI components that need an expression language.
|
||||
|
||||
See [here](./api-reference.md) for API reference.
|
||||
|
||||
***_An expression is a sequence that can contain one or more [operators](#Operators), [variables](#Variables), [explicit values](#Explicit-values), [pre-built functions](./prebuilt-functions.md) or [Language Generation templates](../fileformats/lg/README.md#Template)._***
|
||||
|
||||
## Operators
|
||||
|
||||
| Operator | Functionality | Prebuilt function equivalent |
|
||||
|-----------|-------------------------------------------------------------------------------------------|-----------------------------------|
|
||||
|+ |Arithmetic operator – addition. E.g. A + B |[add][1] |
|
||||
|- |Arithmetic operator – subtraction. E.g. A – B |[sub][2] |
|
||||
|* |Arithmetic operator – multiplication. E.g. A * B |[mul][3] |
|
||||
|/ |Arithmetic operator – division. E.g. A / B |[div][4] |
|
||||
|^ |Arithmetic operator – exponentiation. E.g. A ^ B |[exp][5] |
|
||||
|% |Arithmetic operator – modulus. E.g. A % B |[mod][6] |
|
||||
|== |Comparison operator – equals. E.g. A == B |[equals][7] |
|
||||
|!= |Comparison operator – Not equals. E.g. A != B |[not][8]([equals][7]()) |
|
||||
|> |Comparison operator – Greater than. A > B |[greater][9] |
|
||||
|< |Comparison operator – Less than. A < B |[less][10] |
|
||||
|>= |Comparison operator – Greater than or equal. A >= B |[greaterOrEquals][11] |
|
||||
|<= |Comparison operator – Less than or equal. A <= B |[lessOrEquals][12] |
|
||||
|& |Concatenation operator. Operands will always be cast to string – E.g. A & B |N/A |
|
||||
|&& |Logical operator – AND. E.g. exp1 && exp2 |[and][13] |
|
||||
|\|\| |Logical operator – OR. E.g. exp1 \|\| exp2 |[or][14] |
|
||||
|! |Logical operator – NOT. E.g. !exp1 |[Not][8] |
|
||||
|' |Used to wrap a string literal. E.g. 'myValue' |N/A |
|
||||
|" |Used to wrap a string literal. E.g. "myValue" |N/A |
|
||||
|[] |Used to denote a Template. E.g. [MyTemplate]. |N/A |
|
||||
|[] |Used to refer to an item in a list by its index. E.g. A[3] |N/A |
|
||||
|{} |Used to denote an expression. E.g. {A == B}. |N/A |
|
||||
|{} |Used to denote a variable in template expansion. E.g. {myVariable} |N/A |
|
||||
|() |Enforces precedence order and groups sub expressions into larger expressions. E.g. (A+B)*C |N/A |
|
||||
|. |Property selector. E.g. myObject.Property1 |N/A |
|
||||
|@{} |Used to denote parts of a multi-line value that requires evaluation |N/A |
|
||||
|\ |Escape character for templates, expressions. |N/A |
|
||||
|@entityName|Short hand notation that expands to turn.entities.entityName |N/A |
|
||||
|$propertyName|Short hand notation that expands to dialog.result.property |N/A |
|
||||
|#intentName|Short hand notation that expands to turn.intents.intentName |N/A |
|
||||
|
||||
## Variables
|
||||
Variables are always referenced by their name. E.g. {myVariable}
|
||||
Variables can be complex objects. In which case they are referenced either using the property selector operator e.g. myParent.myVariable or using the item index selection operator. E.g. myParent.myList[0]. or using the [parameters](TODO) function.
|
||||
|
||||
## Explicit values
|
||||
Explicit values are enclosed in single quotes 'myExplicitValut' or double quotes - "myExplicitValue".
|
||||
|
||||
## Pre-built functions
|
||||
See [Here](./prebuilt-functions.md) for a complete list of prebuilt functions supported by the common expression language library.
|
||||
|
||||
[1]:prebuilt-functions.md#add
|
||||
[2]:prebuilt-functions.md#sub
|
||||
[3]:prebuilt-functions.md#mul
|
||||
[4]:prebuilt-functions.md#div
|
||||
[5]:prebuilt-functions.md#exp
|
||||
[6]:prebuilt-functions.md#mod
|
||||
[7]:prebuilt-functions.md#equals
|
||||
[8]:prebuilt-functions.md#not
|
||||
[9]:prebuilt-functions.md#greater
|
||||
[10]:prebuilt-functions.md#less
|
||||
[11]:prebuilt-functions.md#greaterOrEquals
|
||||
[12]:prebuilt-functions.md#essOrEquals
|
||||
[13]:prebuilt-functions.md#and
|
||||
[14]:prebuilt-functions.md#or
|
|
@ -0,0 +1,84 @@
|
|||
# API reference for LG
|
||||
|
||||
### TemplateEngine Class
|
||||
|
||||
#### Fields
|
||||
``` C#
|
||||
/// <summary>
|
||||
/// Parsed LG templates
|
||||
/// </summary>
|
||||
public List<LGTemplate> Templates = new List<LGTemplate>();
|
||||
```
|
||||
|
||||
#### Constructors
|
||||
```C#
|
||||
/// <summary>
|
||||
/// 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()
|
||||
```
|
||||
```C#
|
||||
/// <summary>
|
||||
/// Create a template engine from files, a shorthand for
|
||||
/// new TemplateEngine().AddFiles(filePath)
|
||||
/// </summary>
|
||||
/// <param name="filePaths">paths to LG files</param>
|
||||
/// <returns>Engine created</returns>
|
||||
public static TemplateEngine FromFiles(params string[] filePaths)
|
||||
```
|
||||
|
||||
```C#
|
||||
/// <summary>
|
||||
/// Create a template engine from text, equivalent to
|
||||
/// new TemplateEngine.AddText(text)
|
||||
/// </summary>
|
||||
/// <param name="text">Content of lg file</param>
|
||||
/// <returns>Engine created</returns>
|
||||
public static TemplateEngine FromText(string text)
|
||||
```
|
||||
|
||||
#### Methods
|
||||
```C#
|
||||
/// <summary>
|
||||
/// Load .lg files into template engine
|
||||
///
|
||||
/// You can add one file, or mutlple file as once
|
||||
///
|
||||
/// If you have multiple files referencing each other, make sure you add them all at once,
|
||||
/// otherwise static checking won't allow you to add it one by one
|
||||
/// </summary>
|
||||
/// <param name="filePaths">Paths to .lg files</param>
|
||||
/// <returns>Teamplate engine with parsed files</returns>
|
||||
public TemplateEngine AddFiles(params string[] filePaths)
|
||||
```
|
||||
|
||||
|
||||
```C#
|
||||
/// <summary>
|
||||
/// Add text as lg file content to template engine
|
||||
/// </summary>
|
||||
/// <param name="text">Text content contains lg templates</param>
|
||||
/// <returns>Template engine with the parsed content</returns>
|
||||
public TemplateEngine AddText(string text)
|
||||
```
|
||||
|
||||
```C#
|
||||
/// <summary>
|
||||
/// Evaluate a template with given name and scope
|
||||
/// </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></returns>
|
||||
public string EvaluateTemplate(string templateName, object scope, IGetMethod methodBinder = null)
|
||||
```
|
||||
|
||||
```C#
|
||||
/// <summary>
|
||||
/// Analyze a given template and return it's referenced variables
|
||||
/// </summary>
|
||||
/// <param name="templateName">Template name</param>
|
||||
/// <returns>list of variable names</returns>
|
||||
public List<string> AnalyzeTemplate(string templateName)
|
||||
```
|
|
@ -0,0 +1,223 @@
|
|||
# .LG file format
|
||||
.lg file will be a lot similar to the [.lu][1] file. As an overarching goal, we use simple markdown conventions as much as possible and add additional syntax and semantics only where needed.
|
||||
|
||||
.lg files help describe language generation templates with entity references and their composition. The rest of this document covers the various concepts expressed via the .lg file format. See [here][2] for API-reference.
|
||||
|
||||
## Comments
|
||||
Comments are prefixed with '>' character. All lines that have this prefix will be skipped by the parser.
|
||||
|
||||
```markdown
|
||||
> this is a comment.
|
||||
```
|
||||
## Escape character
|
||||
- Use '\' as escape character. E.g. "You can say cheese and tomato \[toppings are optional\]"
|
||||
|
||||
## Template
|
||||
At the core of rule based LG is the concept of a template. Each template has a
|
||||
- Name
|
||||
- List of one-of variation text values .or.
|
||||
- A collection of conditions, each with a
|
||||
- Condition expression which is expressed using the [Common expression language][3] and
|
||||
- List of one-of variation text values per condition.
|
||||
|
||||
Templates are defined via # \<TemplateName\> notation. Here is an example of a simple template that includes 2 variations.
|
||||
Templates follow the markdown header definition. Variations are expressed as markdown list; so you can prefix them using either '-' or '*' or '+'.
|
||||
|
||||
```markdown
|
||||
> Greeting template with 2 variations. One of the variation is picked up by the template resolution runtime.
|
||||
# GreetingPrefix
|
||||
- Hi
|
||||
- Hello
|
||||
```
|
||||
|
||||
Here are few examples of a conditional template. All conditions are expressed using the [Common expression language][3]. Condition expressions are enclosed in curly brackets - {}. Conditions are evaluated in the order specified via the IF ... ELSE or IF ... ELSEIF ... ELSE prefixes.
|
||||
|
||||
Here is an example that shows the simple IF ... ELSE conditional response template definition.
|
||||
|
||||
<a name="conditional-response-template"></a>
|
||||
```markdown
|
||||
> time of day greeting reply template with conditions.
|
||||
# timeOfDayGreeting
|
||||
- IF: {timeOfDay == 'morning'}
|
||||
- good morning
|
||||
- ELSE:
|
||||
- good evening
|
||||
```
|
||||
|
||||
Here's another example that shows IF ... ELSEIF ... ELSE conditional response template definition.
|
||||
|
||||
```markdown
|
||||
# timeOfDayGreeting
|
||||
- IF: {timeOfDay == 'morning'}
|
||||
- good morning
|
||||
- ELSEIF: {timeOfDay == 'afternoon'}
|
||||
- good afternoon
|
||||
- ELSE:
|
||||
- good evening
|
||||
```
|
||||
|
||||
### References to templates
|
||||
Variation text can include references to another named template to aid with composition and resolution of sophisticated responses.
|
||||
Reference to another named template are denoted using markdown link notation by enclosing the target template name in square brackets - [TemplateName].
|
||||
|
||||
```markdown
|
||||
> Example of a template that includes composition reference to another template
|
||||
# GreetingReply
|
||||
- [GreetingPrefix], [timeOfDayGreeting]
|
||||
|
||||
# GreetingPrefix
|
||||
- Hi
|
||||
- Hello
|
||||
|
||||
# timeOfDayGreeting
|
||||
- IF: {timeOfDay == 'morning'}
|
||||
- good morning
|
||||
- ELSEIF: {timeOfDay == 'afternoon'}
|
||||
- good afternoon
|
||||
- ELSE:
|
||||
- good evening
|
||||
```
|
||||
|
||||
Calling the `GreetingReply` template can result in one of the following expansion resolutions -
|
||||
|
||||
```
|
||||
Hi, good morning
|
||||
Hi, good afternoon
|
||||
Hi, good evening
|
||||
Hello, good morning
|
||||
Hello, good afternoon
|
||||
Hello, good evening
|
||||
```
|
||||
|
||||
### Parametrization of templates
|
||||
To aid with contextual re-usability, templates can be parametrized. With this different callers to the template can pass in different values for use in expansion resolution.
|
||||
|
||||
Here is an example of a template parametrization.
|
||||
|
||||
```markdown
|
||||
# timeOfDayGreetingTemplate (param1)
|
||||
- IF: {param1 == 'morning'}
|
||||
- good morning
|
||||
- ELSEIF: {param1 == 'afternoon'}
|
||||
- good afternoon
|
||||
- ELSE:
|
||||
- good evening
|
||||
|
||||
# morningGreeting
|
||||
- timeOfDayGreetingTemplate('morning')
|
||||
|
||||
# timeOfDayGreeting
|
||||
- timeOfDayGreetingTemplate(timeOfDay)
|
||||
```
|
||||
|
||||
## Entities
|
||||
- When used directly within a one-of variation text, entity references are denoted by enclosing them in curly brackets - {`entityName`}
|
||||
- When used as a parameter within a
|
||||
- [pre-built function][4] or
|
||||
- as a parameter to [template resolution call](#Parametrization-of-templates) or
|
||||
- a condition in [conditional response template](#conditional-response-template)
|
||||
they are simply expressed as `entityName`.
|
||||
|
||||
## Multi-line text in variations
|
||||
Each one-of variation can include multi-line text enclosed in ```...```.
|
||||
|
||||
Here is an example -
|
||||
```markdown
|
||||
# MultiLineExample
|
||||
- ```This is a multi-line list
|
||||
- one
|
||||
- two
|
||||
```
|
||||
- ```This is a multi-line variation
|
||||
- three
|
||||
- four
|
||||
```
|
||||
```
|
||||
|
||||
Multi-line variation can request template expansion and entity substitution by enclosing the requested operation in @{}.
|
||||
|
||||
Here is an example -
|
||||
```markdown
|
||||
# MultiLineExample
|
||||
- ```
|
||||
Here is what I have for the order
|
||||
- Title: @{reservation.title}
|
||||
- Location: @{reservation.location}
|
||||
- Date/ time: @{reservation.dateTimeReadBack}
|
||||
```
|
||||
```
|
||||
|
||||
With multi-line support, you can have the language generation sub-system fully resolve a complex JSON or XML (e.g. SSML wrapped text to control bot's spoken reply).
|
||||
|
||||
Here is an example of complex object that your bot's code will parse out and render appropriately.
|
||||
|
||||
```markdown
|
||||
# TitleText
|
||||
- Here are some [TitleSuffix]
|
||||
|
||||
# TitleSuffix
|
||||
- cool photos
|
||||
- pictures
|
||||
- nice snaps
|
||||
|
||||
# SubText
|
||||
- What is your favorite?
|
||||
- Don't they all look great?
|
||||
- sorry, some of them are repeats
|
||||
|
||||
# CardImages
|
||||
- https://picsum.photos/200/200?image=100
|
||||
- https://picsum.photos/300/200?image=200
|
||||
- https://picsum.photos/200/200?image=400
|
||||
|
||||
# ImageGalleryTemplate
|
||||
- ```
|
||||
{
|
||||
"titleText": "@{[TitleText]}",
|
||||
"subTitle": "@{[SubText]}",
|
||||
"images": [
|
||||
{
|
||||
"type": "Image",
|
||||
"url": "@{[CardImages]}"
|
||||
},
|
||||
{
|
||||
"type": "Image",
|
||||
"url": "@{[CardImages]}"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
Calling the `ImageGalleryTemplate` for template resolution will result in a json string that has a 'titleText', 'subTitle' and randomly selected images from the `CardImages` template.
|
||||
|
||||
## Using pre-built functions in variations
|
||||
[Pre-built functions][4] supported by the [Common expression language][3] can also be used inline in a one-of variation text to achieve even more powerful text composition. To use an expression inline, simply wrap it in curly brackets - {}.
|
||||
|
||||
Here is an example that illustrates that -
|
||||
|
||||
```markdown
|
||||
# RecentTasks
|
||||
- IF: {count(recentTasks) == 1}
|
||||
- Your most recent task is {recentTasks[0]}. You can let me know if you want to add or complete a task.
|
||||
- ELSEIF: {count(recentTasks) == 2}
|
||||
- Your most recent tasks are {join(recentTasks, ',', 'and')}. You can let me know if you want to add or complete a task.
|
||||
- ELSEIF: {count(recentTasks) > 2}
|
||||
- Your most recent {count(recentTasks)} tasks are {join(recentTasks, ',', 'and')}. You can let me know if you want to add or complete a task.
|
||||
- ELSE:
|
||||
- You don't have any tasks.
|
||||
```
|
||||
|
||||
The above example uses the [join][5] pre-built function to list all values in the `recentTasks` collection.
|
||||
|
||||
[1]:https://github.com/Microsoft/botbuilder-tools/blob/master/packages/Ludown/docs/lu-file-format.md
|
||||
[2]:api-reference.md
|
||||
[3]:../CommonExpressionLanguage/readme.md
|
||||
[4]:../CommonExpressionLanguage/prebuilt-functions.md
|
||||
[5]:../CommonExpressionLanguage/prebuilt-functions.md#join
|
||||
[6]:https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Chatdown
|
||||
[7]:https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Chatdown#chat-file-format
|
||||
[8]:https://github.com/Microsoft/botbuilder-tools/blob/master/packages/Chatdown/Examples/CardExamples.chat
|
||||
[9]:https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Chatdown#message-commands
|
||||
[10]:https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Chatdown#message-cards
|
||||
[11]:https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Chatdown#message-attachments
|
|
@ -0,0 +1,128 @@
|
|||
# Language Generation
|
||||
Language generation is the umbrella term for generating appropriate output to the user. In some sense, language generation is reverse of language understanding. While language understanding goes from user input to extracting meaningful information such as intent and entities, language generation helps construct meaningful, variable and grammatically correct responses that a bot can send back to the user.
|
||||
|
||||
At the core of language generation lies template expansion and entity substitution. You can provide one-of variation for expansion as well as conditionally expand a template. The output from language generation can be a simple text string or multi-line response or a complex object payload that a layer above language generation will use to construct a full blown [activity][1].
|
||||
|
||||
Language generation is achieved through
|
||||
- markdown based .lg file that describes the templates and their composition. See [here][3] for the .lg file format.
|
||||
- parser and runtime libraries that help achieve runtime resolution. See [here][2] for API-reference.
|
||||
|
||||
You can use language generation to
|
||||
- achieve a coherent personality, tone of voice for your bot
|
||||
- include variations and sophisticated composition based resolution for any of your bot's replies
|
||||
- construct speak .vs. display adaptations
|
||||
- construct cards, suggested actions and attachments.
|
||||
|
||||
## Language Generation in action
|
||||
When building a bot, you can use language generation in several different ways. To start with, examine your current bot's code (or the new bot you plan to write) and create [.lg file][3] to cover all possible scenarios where you would like to use the language generation sub-system with your bot's replies to user.
|
||||
|
||||
Then make sure you include the platform specific language generation library.
|
||||
|
||||
For C#, add Microsoft.Bot.Builder.LanguageGeneration.
|
||||
For NodeJS, add botbuilder-lg
|
||||
|
||||
Load the template manager with your .lg file(s)
|
||||
|
||||
For C#
|
||||
```
|
||||
TemplateEngine lgEngine = TemplateEngine.FromFiles(pathToLGFile);
|
||||
```
|
||||
|
||||
For NodeJS
|
||||
```
|
||||
let lgEngine = templateEngine.fromFiles(pathToLGFile);
|
||||
```
|
||||
|
||||
When you need template expansion, call the templateEngine and pass in the relevant template name
|
||||
|
||||
For C#
|
||||
```
|
||||
await turnContext.SendActivityAsync(lgEngine.EvaluateTemplate("<TemplateName>", entitiesCollection));
|
||||
```
|
||||
|
||||
For NodeJS
|
||||
```
|
||||
await turnContext.sendActivity(lgEngine.evaluateTemplate("<TemplateName>", entitiesCollection));
|
||||
```
|
||||
|
||||
If your template needs specific entity values to be passed for resolution/ expansion, you can pass them in on the call to `evaluateTemplate`
|
||||
|
||||
For C#
|
||||
```
|
||||
await turnContext.SendActivityAsync(lgEngine.EvaluateTemplate("WordGameReply", new { GameName = "MarcoPolo" } ));
|
||||
|
||||
```
|
||||
|
||||
For NodeJS
|
||||
```
|
||||
await turnContext.sendActivity(lgEngine.evaluateTemplate("WordGameReply", { GameName = "MarcoPolo" } ));
|
||||
```
|
||||
|
||||
## Speak .vs. display adaptation
|
||||
By design, the .lg file format does not explicitly support the ability to provide speak .vs. display adaptation. The file format supports simple constructs that are composable and supports resolution on multi-line text and so you can have syntax and semantics for speak .vs. display adaptation, cards, suggested actions etc that can be interpreted as simple text and transformed into the Bot Framework [activity][1] by a layer above language generation.
|
||||
|
||||
Bot Builder SDK supports a short hand notation that can parse and transform a piece of text separated by `displayText`||`spokenText` into speak and display text.
|
||||
|
||||
```markdown
|
||||
# greetingTemplate
|
||||
- hi || hi there
|
||||
- hello || hello, what can I help with today
|
||||
```
|
||||
|
||||
You can use the `TextMessageActivityGenerator.CreateActityFromText` method to transform the command into a Bot Framework activity to post back to the user.
|
||||
|
||||
## Using Chatdown style cards
|
||||
|
||||
[Chatdown][6] introduced a simple markdown based way to write mock conversations. Also introduced as part of the [.chat][7] file format was the ability to express different [message commands][9] via simple text representation. Message commands include [cards][10], [Attachments][11] and suggested actions.
|
||||
|
||||
You can include message commands via multi-line text in the .lg file format and use the `TextMessageActivityGenerator.CreateActityFromText` method to transform the command into a Bot Framework activity to post back to the user.
|
||||
|
||||
See [here][8] for examples of how different card types are represented in .chat file format.
|
||||
|
||||
Here is an example of a card definition.
|
||||
|
||||
```markdown
|
||||
# HeroCardTemplate(buttonsCollection)
|
||||
- ```
|
||||
[Herocard
|
||||
title=@{[TitleText]}
|
||||
subtitle=@{[SubText]}
|
||||
text=@{[DescriptionText]}
|
||||
images=@{[CardImages]}
|
||||
buttons=@{join(buttonsCollection, '|')]
|
||||
```
|
||||
|
||||
# TitleText
|
||||
- Here are some [TitleSuffix]
|
||||
|
||||
# TitleSuffix
|
||||
- cool photos
|
||||
- pictures
|
||||
- nice snaps
|
||||
|
||||
# SubText
|
||||
- What is your favorite?
|
||||
- Don't they all look great?
|
||||
- sorry, some of them are repeats
|
||||
|
||||
# DescriptionText
|
||||
- This is description for the hero card
|
||||
|
||||
# CardImages
|
||||
- https://picsum.photos/200/200?image=100
|
||||
- https://picsum.photos/300/200?image=200
|
||||
- https://picsum.photos/200/200?image=400
|
||||
```
|
||||
|
||||
## Grammar check and correction
|
||||
The current library does not include any capabilities for grammar check or correction.
|
||||
|
||||
[1]:https://github.com/Microsoft/BotBuilder/blob/master/specs/botframework-activity/botframework-activity.md
|
||||
[2]:api-reference.md
|
||||
[3]:lg-file-format.md
|
||||
[6]:https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Chatdown
|
||||
[7]:https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Chatdown#chat-file-format
|
||||
[8]:https://github.com/Microsoft/botbuilder-tools/blob/master/packages/Chatdown/Examples/CardExamples.chat
|
||||
[9]:https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Chatdown#message-commands
|
||||
[10]:https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Chatdown#message-cards
|
||||
[11]:https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Chatdown#message-attachments
|
|
@ -0,0 +1,2 @@
|
|||
set npm_config_registry=https://botbuilder.myget.org/F/botframework-cli/auth/da91578f-5b61-4224-9c46-cb2522c66033/npm/
|
||||
npm install -g @microsoft/botframework-cli@4.5.0-preview.76135
|
|
@ -1,30 +1,34 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Version Condition=" '$(PackageVersion)' == '' ">4.0.0-local</Version>
|
||||
<Version Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</Version>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' == '' ">4.0.0-local</PackageVersion>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</PackageVersion>
|
||||
<Configurations>Debug;Release;Debug - NuGet Packages</Configurations>
|
||||
<Version Condition=" '$(PreviewPackageVersion)' == '' ">4.6.0-local</Version>
|
||||
<Version Condition=" '$(PreviewPackageVersion)' != '' ">$(PreviewPackageVersion)</Version>
|
||||
<PackageVersion Condition=" '$(PreviewPackageVersion)' == '' ">4.6.0-local</PackageVersion>
|
||||
<PackageVersion Condition=" '$(PreviewPackageVersion)' != '' ">$(PreviewPackageVersion)</PackageVersion>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<PackageId>Microsoft.Bot.Builder.Adapters.Twilio</PackageId>
|
||||
<Description>description</Description>
|
||||
<Summary>This library implements C# classes for twilio adapter</Summary>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<!-- The Twilio package isn't signed, so supress the warning. There seems to not be a way to supress this for ONLY Twilio. -->
|
||||
<NoWarn>$(NoWarn),CS8002</NoWarn>
|
||||
<DefineConstants></DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU' ">
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<DelaySign>true</DelaySign>
|
||||
<AssemblyOriginatorKeyFile>..\..\..\build\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<DocumentationFile>bin\$(Configuration)\netstandard2.0\Microsoft.Bot.Builder.Adapters.Twilio.xml</DocumentationFile>
|
||||
<DefineConstants>SIGNASSEMBLY</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Twilio" Version="5.31.1" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -122,7 +122,7 @@ namespace Microsoft.Bot.Builder.Adapters.Twilio
|
|||
throw new ArgumentNullException(nameof(bot));
|
||||
}
|
||||
|
||||
var activity = TwilioHelper.RequestToActivity(httpRequest, _options.ValidationUrl, _options.AuthToken);
|
||||
var activity = await TwilioHelper.RequestToActivity(httpRequest, _options.ValidationUrl, _options.AuthToken).ConfigureAwait(false);
|
||||
|
||||
// create a conversation reference
|
||||
using (var context = new TurnContext(this, activity))
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Adapters.Twilio
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -15,7 +17,7 @@ namespace Microsoft.Bot.Builder.Adapters.Twilio
|
|||
/// <param name="accountSid">The account id.</param>
|
||||
/// <param name="authToken">The authentication token.</param>
|
||||
/// <param name="validationUrl">validation URL for incoming requests.</param>
|
||||
public TwilioAdapterOptions(string twilioNumber, string accountSid, string authToken, string validationUrl = null)
|
||||
public TwilioAdapterOptions(string twilioNumber, string accountSid, string authToken, Uri validationUrl = null)
|
||||
{
|
||||
TwilioNumber = twilioNumber;
|
||||
AccountSid = accountSid;
|
||||
|
@ -49,6 +51,6 @@ namespace Microsoft.Bot.Builder.Adapters.Twilio
|
|||
/// <value>Optional validation URL to override the automatically generated URL signature used
|
||||
/// to validate incoming requests. See the Twilio security documentation on
|
||||
/// [validating requests](https://www.twilio.com/docs/usage/security#validating-requests).</value>
|
||||
public string ValidationUrl { get; set; }
|
||||
public Uri ValidationUrl { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Newtonsoft.Json;
|
||||
using Twilio.Exceptions;
|
||||
using Twilio.Rest.Api.V2010.Account;
|
||||
using Twilio.Security;
|
||||
|
||||
|
@ -69,8 +69,8 @@ namespace Microsoft.Bot.Builder.Adapters.Twilio
|
|||
/// <param name="authToken">The authentication token for the Twilio app.</param>
|
||||
/// <returns>The activity object.</returns>
|
||||
/// <seealso cref="TwilioAdapter.ProcessAsync(HttpRequest, HttpResponse, IBot, System.Threading.CancellationToken)"/>
|
||||
/// <seealso cref="ITwilioAdapterOptions.ValidationUrl"/>
|
||||
public static Activity RequestToActivity(HttpRequest httpRequest, string validationUrl, string authToken)
|
||||
/// <seealso cref="TwilioAdapterOptions.ValidationUrl"/>
|
||||
public static async Task<Activity> RequestToActivity(HttpRequest httpRequest, Uri validationUrl, string authToken)
|
||||
{
|
||||
if (httpRequest == null)
|
||||
{
|
||||
|
@ -80,7 +80,7 @@ namespace Microsoft.Bot.Builder.Adapters.Twilio
|
|||
Dictionary<string, string> body;
|
||||
using (var bodyStream = new StreamReader(httpRequest.Body))
|
||||
{
|
||||
body = QueryStringToDictionary(bodyStream.ReadToEnd());
|
||||
body = QueryStringToDictionary(await bodyStream.ReadToEndAsync().ConfigureAwait(false));
|
||||
}
|
||||
|
||||
ValidateRequest(httpRequest, body, validationUrl, authToken);
|
||||
|
@ -120,12 +120,21 @@ namespace Microsoft.Bot.Builder.Adapters.Twilio
|
|||
/// generated URL signature used to validate incoming requests.</param>
|
||||
/// <param name="authToken">The authentication token for the Twilio app.</param>
|
||||
/// <exception cref="AuthenticationException">Validation failed.</exception>
|
||||
private static void ValidateRequest(HttpRequest httpRequest, Dictionary<string, string> body, string validationUrl, string authToken)
|
||||
private static void ValidateRequest(HttpRequest httpRequest, Dictionary<string, string> body, Uri validationUrl, string authToken)
|
||||
{
|
||||
var twilioSignature = httpRequest.Headers["x-twilio-signature"];
|
||||
validationUrl = validationUrl ?? (httpRequest.Headers["x-forwarded-proto"][0] ?? httpRequest.Protocol + "://" + httpRequest.Host + httpRequest.Path);
|
||||
var urlString = validationUrl?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(urlString))
|
||||
{
|
||||
urlString = httpRequest.Headers["x-forwarded-proto"][0];
|
||||
if (string.IsNullOrWhiteSpace(urlString))
|
||||
{
|
||||
urlString = httpRequest.Protocol + "://" + httpRequest.Host + httpRequest.Path;
|
||||
}
|
||||
}
|
||||
|
||||
var requestValidator = new RequestValidator(authToken);
|
||||
if (!requestValidator.Validate(validationUrl, body, twilioSignature))
|
||||
if (!requestValidator.Validate(urlString, body, twilioSignature))
|
||||
{
|
||||
throw new AuthenticationException("Request does not match provided signature");
|
||||
}
|
||||
|
|
|
@ -50,16 +50,16 @@ namespace Microsoft.Bot.Builder.Adapters.Twilio
|
|||
public string NumMedia { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the URLs referencing the media content included with the message, if any.
|
||||
/// Gets the URLs referencing the media content included with the message, if any.
|
||||
/// </summary>
|
||||
/// <value>URLs referencing the media content included with the message.</value>
|
||||
public List<Uri> MediaUrls { get; set; }
|
||||
public List<Uri> MediaUrls { get; } = new List<Uri>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content types for the media included with the message, if any.
|
||||
/// Gets the content types for the media included with the message, if any.
|
||||
/// </summary>
|
||||
/// <value>The content types for the media included with the message.</value>
|
||||
public List<string> MediaContentTypes { get; set; }
|
||||
public List<string> MediaContentTypes { get; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the receiver's city.
|
||||
|
|
После Ширина: | Высота: | Размер: 1.9 KiB |
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Adapters.Webex
|
||||
{
|
||||
public class AttachmentActionData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the unique identifier for the action.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The unique identifier for the action.
|
||||
/// </value>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of action performed.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of action performed.
|
||||
/// </value>
|
||||
public string Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parent message the attachment action was performed on.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The parent message the attachment action was performed on.
|
||||
/// </value>
|
||||
public string MessageId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ID of the person who performed the action.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The ID of the person who performed the action.
|
||||
/// </value>
|
||||
public string PersonId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date and time the action was created.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The date and time the action was created.
|
||||
/// </value>
|
||||
public string Created { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the action's inputs.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The action's inputs.
|
||||
/// </value>
|
||||
public Dictionary<string, string> Inputs { get; } = new Dictionary<string, string>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Version Condition=" '$(PreviewPackageVersion)' == '' ">4.6.0-local</Version>
|
||||
<Version Condition=" '$(PreviewPackageVersion)' != '' ">$(PreviewPackageVersion)</Version>
|
||||
<PackageVersion Condition=" '$(PreviewPackageVersion)' == '' ">4.6.0-local</PackageVersion>
|
||||
<PackageVersion Condition=" '$(PreviewPackageVersion)' != '' ">$(PreviewPackageVersion)</PackageVersion>
|
||||
<Configurations>Debug;Release;</Configurations>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<PackageId>Microsoft.Bot.Builder.Adapters.Webex</PackageId>
|
||||
<Description>description</Description>
|
||||
<Summary>This library implements C# classes for the WebEx Adapter</Summary>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU' ">
|
||||
<DocumentationFile>bin\$(Configuration)\netstandard2.0\Microsoft.Bot.Builder.Adapters.Webex.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Thrzn41.WebexTeams" Version="1.6.2" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\integration\Microsoft.Bot.Builder.Integration.AspNet.Core\Microsoft.Bot.Builder.Integration.AspNet.Core.csproj" />
|
||||
<ProjectReference Include="..\..\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj" />
|
||||
<ProjectReference Include="..\..\Microsoft.Bot.Schema\Microsoft.Bot.Schema.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,241 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Thrzn41.WebexTeams.Version1;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Adapters.Webex
|
||||
{
|
||||
public class WebexAdapter : BotAdapter, IBotFrameworkHttpAdapter
|
||||
{
|
||||
private readonly WebexClientWrapper _webexClient;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebexAdapter"/> class using configuration settings.
|
||||
/// </summary>
|
||||
/// <param name="configuration">An <see cref="IConfiguration"/> instance.</param>
|
||||
/// <remarks>
|
||||
/// The configuration keys are:
|
||||
/// AccessToken: An access token for the bot.
|
||||
/// PublicAddress: The root URL of the bot application.
|
||||
/// Secret: The secret used to validate incoming webhooks.
|
||||
/// WebhookName: A name for the webhook subscription.
|
||||
/// </remarks>
|
||||
public WebexAdapter(IConfiguration configuration)
|
||||
: this(new WebexClientWrapper(new WebexAdapterOptions(configuration["AccessToken"], new Uri(configuration["PublicAddress"]), configuration["Secret"], configuration["WebhookName"])))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebexAdapter"/> class.
|
||||
/// Creates a Webex adapter.
|
||||
/// </summary>
|
||||
/// <param name="webexClient">A Webex API interface.</param>
|
||||
public WebexAdapter(WebexClientWrapper webexClient)
|
||||
{
|
||||
_webexClient = webexClient ?? throw new ArgumentNullException(nameof(webexClient));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Standard BotBuilder adapter method to send a message from the bot to the messaging API.
|
||||
/// </summary>
|
||||
/// <param name="turnContext">A TurnContext representing the current incoming message and environment.</param>
|
||||
/// <param name="activities">An array of outgoing activities to be sent back to the messaging API.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public override async Task<ResourceResponse[]> SendActivitiesAsync(ITurnContext turnContext, Activity[] activities, CancellationToken cancellationToken)
|
||||
{
|
||||
var responses = new List<ResourceResponse>();
|
||||
foreach (var activity in activities)
|
||||
{
|
||||
if (activity.Type != ActivityTypes.Message)
|
||||
{
|
||||
throw new Exception("Unknown message type");
|
||||
}
|
||||
|
||||
// transform activity into the webex message format
|
||||
string personIdOrEmail;
|
||||
|
||||
if (activity.GetChannelData<WebhookEventData>()?.MessageData.PersonEmail != null)
|
||||
{
|
||||
personIdOrEmail = activity.GetChannelData<WebhookEventData>()?.MessageData.PersonEmail;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (activity.Recipient?.Id != null)
|
||||
{
|
||||
personIdOrEmail = activity.Recipient.Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Person or Email to send the message");
|
||||
}
|
||||
}
|
||||
|
||||
string responseId;
|
||||
|
||||
if (activity.Attachments != null && activity.Attachments.Count > 0)
|
||||
{
|
||||
if (activity.Attachments[0].ContentType == "application/vnd.microsoft.card.adaptive")
|
||||
{
|
||||
responseId = await _webexClient.CreateMessageWithAttachmentsAsync(personIdOrEmail, activity.Text, activity.Attachments, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
var files = new List<Uri>();
|
||||
|
||||
foreach (var attachment in activity.Attachments)
|
||||
{
|
||||
var file = new Uri(attachment.ContentUrl);
|
||||
files.Add(file);
|
||||
}
|
||||
|
||||
responseId = await _webexClient.CreateMessageAsync(personIdOrEmail, activity.Text, files.Count > 0 ? files : null, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
responseId = await _webexClient.CreateMessageAsync(personIdOrEmail, activity.Text, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
responses.Add(new ResourceResponse(responseId));
|
||||
}
|
||||
|
||||
return responses.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Standard BotBuilder adapter method to update a previous message.
|
||||
/// </summary>
|
||||
/// <param name="turnContext">A TurnContext representing the current incoming message and environment.</param>
|
||||
/// <param name="activity">An activity to be sent back to the messaging API.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public override Task<ResourceResponse> UpdateActivityAsync(ITurnContext turnContext, Activity activity, CancellationToken cancellationToken)
|
||||
{
|
||||
// Webex adapter does not support updateActivity.
|
||||
return Task.FromException<ResourceResponse>(new NotSupportedException("Webex adapter does not support updateActivity."));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Standard BotBuilder adapter method to delete a previous message.
|
||||
/// </summary>
|
||||
/// <param name="turnContext">A <see cref="ITurnContext"/> representing the current incoming message and environment.</param>
|
||||
/// <param name="reference">A <see cref="ConversationReference"/> object.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public override async Task DeleteActivityAsync(ITurnContext turnContext, ConversationReference reference, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(reference.ActivityId))
|
||||
{
|
||||
await _webexClient.DeleteMessageAsync(reference.ActivityId, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.
|
||||
/// </summary>
|
||||
/// <param name="reference">A <see cref="ConversationReference"/> to be applied to future messages.</param>
|
||||
/// <param name="logic">A bot logic function that will perform continuing action.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public async Task ContinueConversationAsync(ConversationReference reference, BotCallbackHandler logic, CancellationToken cancellationToken)
|
||||
{
|
||||
if (reference == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(reference));
|
||||
}
|
||||
|
||||
if (logic == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(logic));
|
||||
}
|
||||
|
||||
var request = reference.GetContinuationActivity().ApplyConversationReference(reference, true);
|
||||
|
||||
using (var context = new TurnContext(this, request))
|
||||
{
|
||||
await RunPipelineAsync(context, logic, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accept an incoming webhook <see cref="HttpRequest"/> and convert it into a <see cref="TurnContext"/> which can be processed by the bot's logic.
|
||||
/// </summary>
|
||||
/// <param name="request">A <see cref="HttpRequest"/> object.</param>
|
||||
/// <param name="response">A <see cref="HttpResponse"/> object.</param>
|
||||
/// <param name="bot">A bot with logic function in the form.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public async Task ProcessAsync(HttpRequest request, HttpResponse response, IBot bot, CancellationToken cancellationToken)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
if (response == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(response));
|
||||
}
|
||||
|
||||
if (bot == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(bot));
|
||||
}
|
||||
|
||||
var identity = await _webexClient.GetMeAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
WebhookEventData payload;
|
||||
string json;
|
||||
using (var bodyStream = new StreamReader(request.Body))
|
||||
{
|
||||
json = await bodyStream.ReadToEndAsync().ConfigureAwait(false);
|
||||
payload = JsonConvert.DeserializeObject<WebhookEventData>(json);
|
||||
}
|
||||
|
||||
if (!_webexClient.ValidateSignature(request, json))
|
||||
{
|
||||
throw new Exception("WARNING: Webhook received message with invalid signature. Potential malicious behavior!");
|
||||
}
|
||||
|
||||
Activity activity;
|
||||
if (payload.Resource == EventResource.Message && payload.EventType == EventType.Created)
|
||||
{
|
||||
var decryptedMessage = await WebexHelper.GetDecryptedMessageAsync(payload, _webexClient.GetMessageAsync, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
activity = WebexHelper.DecryptedMessageToActivity(decryptedMessage, identity);
|
||||
}
|
||||
else if (payload.Resource.Name == "attachmentActions" && payload.EventType == EventType.Created)
|
||||
{
|
||||
var extraData = payload.GetResourceData<TeamsData>();
|
||||
|
||||
var data = JsonConvert.SerializeObject(extraData);
|
||||
|
||||
var jsonData = JsonConvert.DeserializeObject<AttachmentActionData>(data);
|
||||
|
||||
var decryptedMessage = await _webexClient.GetAttachmentActionAsync(jsonData.Id, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
activity = WebexHelper.AttachmentActionToActivity(decryptedMessage, identity);
|
||||
}
|
||||
else
|
||||
{
|
||||
activity = WebexHelper.PayloadToActivity(payload, identity);
|
||||
}
|
||||
|
||||
using (var context = new TurnContext(this, activity))
|
||||
{
|
||||
await RunPipelineAsync(context, bot.OnTurnAsync, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Adapters.Webex
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines implementation of the WebexAdapter Options.
|
||||
/// </summary>
|
||||
public class WebexAdapterOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebexAdapterOptions"/> class.
|
||||
/// </summary>
|
||||
/// <param name="accessToken">An access token for the bot.</param>
|
||||
/// <param name="publicAddress">The root URL of the bot application.</param>
|
||||
/// <param name="secret">The secret used to validate incoming webhooks.</param>
|
||||
/// <param name="webhookName">A name for the webhook subscription.</param>
|
||||
public WebexAdapterOptions(string accessToken, Uri publicAddress, string secret, string webhookName = null)
|
||||
{
|
||||
AccessToken = accessToken;
|
||||
PublicAddress = publicAddress;
|
||||
Secret = secret;
|
||||
WebhookName = webhookName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an access token for the bot.
|
||||
/// </summary>
|
||||
/// <value>An access token for the bot. Get one from https://developer.webex.com/.</value>
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the secret used to validate incoming webhooks.
|
||||
/// </summary>
|
||||
/// <value>The secret used to validate incoming webhooks. You can define this yourself.</value>
|
||||
public string Secret { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the root URI of your bot application. Something like 'https://mybot.com/'.
|
||||
/// </summary>
|
||||
/// <value>the root URI of your bot application.</value>
|
||||
public Uri PublicAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a name for the webhook subscription that will be created to tell WebEx to send your bot webhooks.
|
||||
/// </summary>
|
||||
/// <value>A name for the webhook subscription.</value>
|
||||
public string WebhookName { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,814 @@
|
|||
// Copyright (c) Microsoft Corporation.All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Newtonsoft.Json;
|
||||
using Thrzn41.WebexTeams;
|
||||
using Thrzn41.WebexTeams.Version1;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Adapters.Webex
|
||||
{
|
||||
public class WebexClientWrapper
|
||||
{
|
||||
private const string WebhookUrl = "https://api.ciscospark.com/v1/webhooks";
|
||||
private const string MessageUrl = "https://api.ciscospark.com/v1/messages";
|
||||
private const string ActionsUrl = "https://api.ciscospark.com/v1/attachment/actions";
|
||||
|
||||
private readonly TeamsAPIClient _api;
|
||||
private readonly WebexAdapterOptions _config;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebexClientWrapper"/> class.
|
||||
/// Creates a Webex Client Wrapper. See <see cref="WebexAdapterOptions"/> for a full definition of the allowed parameters.
|
||||
/// </summary>
|
||||
/// <param name="config">An object containing API credentials, a webhook verification token and other options.</param>
|
||||
public WebexClientWrapper(WebexAdapterOptions config)
|
||||
{
|
||||
_config = config ?? throw new ArgumentNullException(nameof(config));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_config.AccessToken))
|
||||
{
|
||||
throw new ArgumentException(nameof(config.AccessToken));
|
||||
}
|
||||
|
||||
if (_config.PublicAddress == null)
|
||||
{
|
||||
throw new ArgumentException(nameof(config.PublicAddress));
|
||||
}
|
||||
|
||||
_api = TeamsAPI.CreateVersion1Client(_config.AccessToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lists all webhook subscriptions currently associated with this application.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A list of webhook subscriptions.</returns>
|
||||
public async Task<WebhookList> ListWebhookSubscriptionsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return await ListWebhooksAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears out and resets the list of webhook subscriptions.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public async Task ResetWebhookSubscriptionsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var webhookList = await ListWebhooksAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
for (var i = 0; i < webhookList.ItemCount; i++)
|
||||
{
|
||||
await DeleteWebhookAsync(webhookList.Items[i], cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register webhook subscriptions to start receiving message events and adaptive cards events.
|
||||
/// </summary>
|
||||
/// <param name="webhookPath">The path of the webhook endpoint like '/api/messages'.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>An array of registered <see cref="Webhook"/>.</returns>
|
||||
public async Task<Webhook[]> RegisterWebhookSubscriptionsAsync(string webhookPath = "api/messages", CancellationToken cancellationToken = default)
|
||||
{
|
||||
var webHookName = string.IsNullOrWhiteSpace(_config.WebhookName) ? "Webex Firehose" : _config.WebhookName;
|
||||
var webHookCardsName = string.IsNullOrWhiteSpace(_config.WebhookName) ? "Webex AttachmentActions" : $"{_config.WebhookName}_AttachmentActions)";
|
||||
|
||||
var webhookList = await ListWebhooksAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
string webhookId = null;
|
||||
string webhookCardsId = null;
|
||||
|
||||
for (var i = 0; i < webhookList.ItemCount; i++)
|
||||
{
|
||||
if (webhookList.Items[i].Name == webHookName)
|
||||
{
|
||||
webhookId = webhookList.Items[i].Id;
|
||||
}
|
||||
else if (webhookList.Items[i].Name == webHookCardsName)
|
||||
{
|
||||
webhookCardsId = webhookList.Items[i].Id;
|
||||
}
|
||||
}
|
||||
|
||||
var webhookUrl = new Uri(_config.PublicAddress + webhookPath);
|
||||
|
||||
var webhook = await RegisterWebhookSubscriptionAsync(webhookId, webHookName, webhookUrl, cancellationToken).ConfigureAwait(false);
|
||||
var cardsWebhook = await RegisterAdaptiveCardsWebhookSubscriptionAsync(webhookCardsId, webHookCardsName, webhookUrl, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new[] { webhook, cardsWebhook };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a webhook subscription with Webex Teams to start receiving message events.
|
||||
/// </summary>
|
||||
/// <param name="hookId">The id of the webhook to be registered.</param>
|
||||
/// <param name="webHookName">The name of the webhook to be registered.</param>
|
||||
/// <param name="webhookUrl">The Uri of the webhook.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The registered <see cref="Webhook"/>.</returns>
|
||||
public async Task<Webhook> RegisterWebhookSubscriptionAsync(string hookId, string webHookName, Uri webhookUrl, CancellationToken cancellationToken)
|
||||
{
|
||||
Webhook webhook;
|
||||
|
||||
if (hookId != null)
|
||||
{
|
||||
webhook = await UpdateWebhookAsync(hookId, webHookName, webhookUrl, _config.Secret, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
webhook = await CreateWebhookAsync(webHookName, webhookUrl, EventResource.All, EventType.All, null, _config.Secret, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return webhook;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a webhook subscription with Webex Teams to start receiving events related to adaptive cards.
|
||||
/// </summary>
|
||||
/// <param name="hookId">The id of the webhook to be registered.</param>
|
||||
/// <param name="webHookName">The name of the webhook to be registered.</param>
|
||||
/// <param name="webhookUrl">The Uri of the webhook.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public async Task<Webhook> RegisterAdaptiveCardsWebhookSubscriptionAsync(string hookId, string webHookName, Uri webhookUrl, CancellationToken cancellationToken)
|
||||
{
|
||||
Webhook webhook;
|
||||
|
||||
if (hookId != null)
|
||||
{
|
||||
webhook = await UpdateAdaptiveCardsWebhookAsync(hookId, webHookName, webhookUrl, _config.Secret, _config.AccessToken, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
webhook = await CreateAdaptiveCardsWebhookAsync(webHookName, webhookUrl, EventType.All, _config.Secret, _config.AccessToken, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return webhook;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the local secret against the one obtained from the request header.
|
||||
/// </summary>
|
||||
/// <param name="request">The <see cref="HttpRequest"/> with the signature.</param>
|
||||
/// <param name="json">The serialized payload to be use for comparison.</param>
|
||||
/// <returns>The result of the comparison between the signature in the request and hashed json.</returns>
|
||||
public virtual bool ValidateSignature(HttpRequest request, string json)
|
||||
{
|
||||
var signature = request.Headers.ContainsKey("x-spark-signature")
|
||||
? request.Headers["x-spark-signature"].ToString().ToUpperInvariant()
|
||||
: throw new Exception("HttpRequest is missing \"x-spark-signature\"");
|
||||
|
||||
#pragma warning disable CA5350 // Webex API uses SHA1 as cryptographic algorithm.
|
||||
using (var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(_config.Secret)))
|
||||
{
|
||||
var hashArray = hmac.ComputeHash(Encoding.UTF8.GetBytes(json));
|
||||
var hash = BitConverter.ToString(hashArray).Replace("-", string.Empty).ToUpperInvariant();
|
||||
|
||||
return signature == hash;
|
||||
}
|
||||
#pragma warning restore CA5350 // Webex API uses SHA1 as cryptographic algorithm.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's CreateDirectMessageAsync method.
|
||||
/// </summary>
|
||||
/// <param name="toPersonOrEmail">Id or email of message recipient.</param>
|
||||
/// <param name="text">Text of the message.</param>
|
||||
/// <param name="files">List of files attached to the message.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The created message id.</returns>
|
||||
public virtual async Task<string> CreateMessageAsync(string toPersonOrEmail, string text, IList<Uri> files = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var webexResponse = await _api.CreateDirectMessageAsync(toPersonOrEmail, text, files, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return webexResponse.Data.Id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's DeleteMessageAsync method.
|
||||
/// </summary>
|
||||
/// <param name="messageId">The id of the message to be deleted.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public virtual async Task DeleteMessageAsync(string messageId, CancellationToken cancellationToken)
|
||||
{
|
||||
await _api.DeleteMessageAsync(messageId, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a message with attachments.
|
||||
/// </summary>
|
||||
/// <param name="toPersonOrEmail">Id or email of message recipient.</param>
|
||||
/// <param name="text">Text of the message.</param>
|
||||
/// <param name="attachments">List of attachments attached to the message.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The created message id.</returns>
|
||||
public virtual async Task<string> CreateMessageWithAttachmentsAsync(string toPersonOrEmail, string text, IList<Attachment> attachments, CancellationToken cancellationToken)
|
||||
{
|
||||
Message result;
|
||||
var url = MessageUrl;
|
||||
|
||||
var attachmentsContent = new List<object>();
|
||||
|
||||
foreach (var attach in attachments)
|
||||
{
|
||||
attachmentsContent.Add(attach.Content);
|
||||
}
|
||||
|
||||
var request = new WebexMessageRequest
|
||||
{
|
||||
ToPersonId = toPersonOrEmail,
|
||||
Text = text ?? string.Empty,
|
||||
Attachments = attachmentsContent.Count > 0 ? attachmentsContent : null,
|
||||
};
|
||||
|
||||
var http = (HttpWebRequest)WebRequest.Create(new Uri(url));
|
||||
http.PreAuthenticate = true;
|
||||
http.Headers.Add("Authorization", "Bearer " + _config.AccessToken);
|
||||
http.Accept = "application/json";
|
||||
http.ContentType = "application/json";
|
||||
http.Method = "POST";
|
||||
|
||||
var parsedContent = JsonConvert.SerializeObject(request);
|
||||
var encoding = new ASCIIEncoding();
|
||||
var bytes = encoding.GetBytes(parsedContent);
|
||||
|
||||
var newStream = http.GetRequestStream();
|
||||
newStream.Write(bytes, 0, bytes.Length);
|
||||
newStream.Close();
|
||||
|
||||
var response = await http.GetResponseAsync().ConfigureAwait(false);
|
||||
|
||||
var stream = response.GetResponseStream();
|
||||
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
var content = sr.ReadToEnd();
|
||||
result = JsonConvert.DeserializeObject<Message>(content);
|
||||
}
|
||||
|
||||
return result.Id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows details for a attachment action, by ID.
|
||||
/// </summary>
|
||||
/// <param name="actionId">A unique identifier for the attachment action.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The attachment action details.</returns>
|
||||
public virtual async Task<Message> GetAttachmentActionAsync(string actionId, CancellationToken cancellationToken)
|
||||
{
|
||||
Message result;
|
||||
|
||||
var url = $"{ActionsUrl}/{actionId}";
|
||||
|
||||
var http = (HttpWebRequest)WebRequest.Create(new Uri(url));
|
||||
http.PreAuthenticate = true;
|
||||
http.Headers.Add("Authorization", "Bearer " + _config.AccessToken);
|
||||
http.Method = "GET";
|
||||
|
||||
var response = await http.GetResponseAsync().ConfigureAwait(false);
|
||||
|
||||
var stream = response.GetResponseStream();
|
||||
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
var content = sr.ReadToEnd();
|
||||
result = JsonConvert.DeserializeObject<Message>(content);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's GetMeAsync method.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The <see cref="Person"/> object associated with the bot.</returns>
|
||||
public virtual async Task<Person> GetMeAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var resultPerson = await _api.GetMeAsync(cancellationToken).ConfigureAwait(false);
|
||||
return resultPerson.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's GetMeFromCacheAsync method.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The <see cref="Person"/> object associated with the bot, from cache.</returns>
|
||||
public virtual async Task<CachedPerson> GetMeFromCacheAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var resultPerson = await _api.GetMeFromCacheAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultPerson.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's GetMessageAsync method.
|
||||
/// </summary>
|
||||
/// <param name="messageId">Id of the message to be recovered.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The message's data.</returns>
|
||||
public virtual async Task<Message> GetMessageAsync(string messageId, CancellationToken cancellationToken)
|
||||
{
|
||||
var message = await _api.GetMessageAsync(messageId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return message.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's ActivateWebhookAsync method.
|
||||
/// </summary>
|
||||
/// <param name="webhook"><see cref="Webhook"/> to be activated.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The Activated <see cref="Webhook"/>.</returns>
|
||||
public virtual async Task<Webhook> ActivateWebhookAsync(Webhook webhook, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultWebhook = await _api.ActivateWebhookAsync(webhook, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultWebhook.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's ListWebhooksAsync method.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A list of Webhooks associated with the application.</returns>
|
||||
public virtual async Task<WebhookList> ListWebhooksAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var webhookList = await _api.ListWebhooksAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return webhookList.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's CreateWebhookAsync method.
|
||||
/// </summary>
|
||||
/// <param name="name">Name for the webhook.</param>
|
||||
/// <param name="targetUri">Uri of the webhook.</param>
|
||||
/// <param name="resource">Event resource associated with the webhook.</param>
|
||||
/// <param name="type">Event type associated with the webhook.</param>
|
||||
/// <param name="filters">Filters for the webhook.</param>
|
||||
/// <param name="secret">Secret used to validate the webhook.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The created <see cref="Webhook"/>.</returns>
|
||||
public virtual async Task<Webhook> CreateWebhookAsync(string name, Uri targetUri, EventResource resource, EventType type, IEnumerable<EventFilter> filters, string secret, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultWebhook = await _api.CreateWebhookAsync(name, targetUri, resource, type, null, secret, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultWebhook.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Webhook subscription to handle Adaptive cards messages.
|
||||
/// </summary>
|
||||
/// <param name="name">Name for the webhook.</param>
|
||||
/// <param name="targetUri">Uri of the webhook.</param>
|
||||
/// <param name="type">Event type associated with the webhook.</param>
|
||||
/// <param name="secret">Secret used to validate the webhook.</param>
|
||||
/// <param name="token">Access Token for authorization.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The created <see cref="Webhook"/>.</returns>
|
||||
public virtual async Task<Webhook> CreateAdaptiveCardsWebhookAsync(string name, Uri targetUri, EventType type, string secret, string token, CancellationToken cancellationToken)
|
||||
{
|
||||
var url = WebhookUrl;
|
||||
|
||||
var data = new NameValueCollection
|
||||
{
|
||||
["name"] = name,
|
||||
["targetUrl"] = targetUri.AbsoluteUri,
|
||||
["resource"] = "attachmentActions",
|
||||
["event"] = "all",
|
||||
["secret"] = secret,
|
||||
};
|
||||
|
||||
using (var client = new WebClient())
|
||||
{
|
||||
client.Headers[HttpRequestHeader.Authorization] = "Bearer " + token;
|
||||
|
||||
var response = await client.UploadValuesTaskAsync(new Uri(url), "POST", data).ConfigureAwait(false);
|
||||
|
||||
var result = JsonConvert.DeserializeObject<Webhook>(Encoding.ASCII.GetString(response));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a Webhook subscription to handle Adaptive cards messages.
|
||||
/// </summary>
|
||||
/// <param name="webhookId">Id of the webhook to be updated.</param>
|
||||
/// <param name="name">Name for the webhook.</param>
|
||||
/// <param name="targetUri">Uri of the webhook.</param>
|
||||
/// <param name="secret">Secret used to validate the webhook.</param>
|
||||
/// <param name="token">Access Token for authorization.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The created <see cref="Webhook"/>.</returns>
|
||||
public virtual async Task<Webhook> UpdateAdaptiveCardsWebhookAsync(string webhookId, string name, Uri targetUri, string secret, string token, CancellationToken cancellationToken)
|
||||
{
|
||||
Webhook result;
|
||||
|
||||
var url = $"{WebhookUrl}/{webhookId}";
|
||||
var data = new NameValueCollection
|
||||
{
|
||||
["name"] = name,
|
||||
["targetUrl"] = targetUri.AbsoluteUri,
|
||||
["resource"] = "attachmentActions",
|
||||
["event"] = "all",
|
||||
["secret"] = secret,
|
||||
};
|
||||
|
||||
using (var client = new WebClient())
|
||||
{
|
||||
client.Headers[HttpRequestHeader.Authorization] = "Bearer " + token;
|
||||
|
||||
var response = await client.UploadValuesTaskAsync(new Uri(url), "PUT", data).ConfigureAwait(false);
|
||||
|
||||
result = JsonConvert.DeserializeObject<Webhook>(Encoding.ASCII.GetString(response));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's GetWebhookAsync method.
|
||||
/// </summary>
|
||||
/// <param name="webhookId">The id of the Webhook to get.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The requested Webhook.</returns>
|
||||
public virtual async Task<Webhook> GetWebhookAsync(string webhookId, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultWebhook = await _api.GetWebhookAsync(webhookId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultWebhook.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's DeleteWebhookAsync method.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the webhook to be deleted.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public virtual async Task DeleteWebhookAsync(Webhook id, CancellationToken cancellationToken)
|
||||
{
|
||||
await _api.DeleteWebhookAsync(id, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's UpdateWebhookAsync method.
|
||||
/// </summary>
|
||||
/// <param name="webhookId">Id of the webhook to be updated.</param>
|
||||
/// <param name="name">Name for the webhook.</param>
|
||||
/// <param name="targetUri">Uri of the webhook.</param>
|
||||
/// <param name="secret">Secret used to validate the webhook.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The updated <see cref="Webhook"/>.</returns>
|
||||
public virtual async Task<Webhook> UpdateWebhookAsync(string webhookId, string name, Uri targetUri, string secret, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultWebhook = await _api.UpdateWebhookAsync(webhookId, name, targetUri, secret, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultWebhook.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's CreateSpaceAsync method.
|
||||
/// </summary>
|
||||
/// <param name="title">Space title.</param>
|
||||
/// <param name="teamId">The ID for the team with which this room is associated.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The space created.</returns>
|
||||
public virtual async Task<Space> CreateSpaceAsync(string title, string teamId = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var resultSpace = await _api.CreateSpaceAsync(title, teamId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultSpace.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's CreateSpaceMembershipAsync method.
|
||||
/// </summary>
|
||||
/// <param name="spaceId">The space ID.</param>
|
||||
/// <param name="personIdOrEmail">The person ID or Email.</param>
|
||||
/// <param name="isModerator">True for moderator persons.</param>
|
||||
/// <param name="personIdType"><see cref="PersonIdType"/> for personIdOrEmail parameter.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The resulting space membership.</returns>
|
||||
public virtual async Task<SpaceMembership> CreateSpaceMembershipAsync(string spaceId, string personIdOrEmail, bool? isModerator = null, PersonIdType personIdType = PersonIdType.Detect, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var resultSpaceMembership = await _api.CreateSpaceMembershipAsync(spaceId, personIdOrEmail, isModerator, personIdType, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultSpaceMembership.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's DeleteSpaceAsync method.
|
||||
/// </summary>
|
||||
/// <param name="spaceId">The id of the space to be deleted.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public virtual async Task DeleteSpaceAsync(string spaceId, CancellationToken cancellationToken)
|
||||
{
|
||||
await _api.DeleteSpaceAsync(spaceId, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's DeleteSpaceMembershipAsync method.
|
||||
/// </summary>
|
||||
/// <param name="membershipId">The id of the membership to be deleted.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public virtual async Task DeleteSpaceMembershipAsync(string membershipId, CancellationToken cancellationToken)
|
||||
{
|
||||
await _api.DeleteSpaceMembershipAsync(membershipId, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's GetSpaceAsync method.
|
||||
/// </summary>
|
||||
/// <param name="spaceId">The id of the space to be gotten.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The space requested.</returns>
|
||||
public virtual async Task<Space> GetSpaceAsync(string spaceId, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultSpace = await _api.GetSpaceAsync(spaceId, cancellationToken).ConfigureAwait(false);
|
||||
return resultSpace.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's GetSpaceMembershipAsync method.
|
||||
/// </summary>
|
||||
/// <param name="membershipId">The id of the membership to get.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The requested space membership.</returns>
|
||||
public virtual async Task<SpaceMembership> GetSpaceMembershipAsync(string membershipId, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultSpaceMembership = await _api.GetSpaceMembershipAsync(membershipId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultSpaceMembership.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's ListSpacesAsync method.
|
||||
/// </summary>
|
||||
/// <param name="teamId">Limit the rooms to those associated with a team, by ID.</param>
|
||||
/// <param name="type"><see cref="SpaceType.Direct"/> returns all 1-to-1 rooms. <see cref="SpaceType.Group"/> returns all group rooms.If not specified or values are not matched, will return all room types.</param>
|
||||
/// <param name="sortBy">Sort results by space ID(<see cref="SpaceSortBy.Id"/>), most recent activity(<see cref="SpaceSortBy.LastActivity"/>), or most recently created(<see cref="SpaceSortBy.Created"/>).</param>
|
||||
/// <param name="max">Limit the maximum number of messages in the response.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A list of the spaces.</returns>
|
||||
public virtual async Task<SpaceList> ListSpacesAsync(string teamId = null, SpaceType type = null, SpaceSortBy sortBy = null, int? max = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var resultSpaceList = await _api.ListSpacesAsync(teamId, type, sortBy, max, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultSpaceList.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's ListSpaceMembershipsAsync method.
|
||||
/// </summary>
|
||||
/// <param name="spaceId">Limit results to a specific space, by ID.</param>
|
||||
/// <param name="personIdOrEmail">Limit results to a specific person, by ID or Email.</param>
|
||||
/// <param name="max">Limit the maximum number of items in the response.</param>
|
||||
/// <param name="personIdType"><see cref="PersonIdType"/> for personIdOrEmail parameter.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The space memberships list.</returns>
|
||||
public virtual async Task<SpaceMembershipList> ListSpaceMembershipsAsync(string spaceId = null, string personIdOrEmail = null, int? max = null, PersonIdType personIdType = PersonIdType.Detect, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var resultSpaceMembershipsList = await _api.ListSpaceMembershipsAsync(spaceId, personIdOrEmail, max, personIdType, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultSpaceMembershipsList.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's UpdateSpaceAsync method.
|
||||
/// </summary>
|
||||
/// <param name="spaceId">Space id to be updated.</param>
|
||||
/// <param name="title">A user-friendly name for the space.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The updated space.</returns>
|
||||
public virtual async Task<Space> UpdateSpaceAsync(string spaceId, string title, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultSpace = await _api.UpdateSpaceAsync(spaceId, title, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultSpace.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's UpdateSpaceMembershipAsync method.
|
||||
/// </summary>
|
||||
/// <param name="membershipId">Membership id to be updated.</param>
|
||||
/// <param name="isModerator">Set to true to make the person a space moderator.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The updated space membership.</returns>
|
||||
public virtual async Task<SpaceMembership> UpdateSpaceMembershipAsync(string membershipId, bool isModerator, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultSpaceMembership = await _api.UpdateSpaceMembershipAsync(membershipId, isModerator, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultSpaceMembership.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's CreateTeamAsync method.
|
||||
/// </summary>
|
||||
/// <param name="name">A user-friendly name for the team.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The created team.</returns>
|
||||
public virtual async Task<Team> CreateTeamAsync(string name, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultTeam = await _api.CreateTeamAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultTeam.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's CreateTeamMembershipAsync method.
|
||||
/// </summary>
|
||||
/// <param name="teamId">The team ID.</param>
|
||||
/// <param name="personIdOrEmail">The person ID or Email.</param>
|
||||
/// <param name="isModerator">Set to true to make the person a room moderator.</param>
|
||||
/// <param name="personIdType"><see cref="PersonIdType"/> for personIdOrEmail parameter.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The team membership created.</returns>
|
||||
public virtual async Task<TeamMembership> CreateTeamMembershipAsync(string teamId, string personIdOrEmail, bool? isModerator = null, PersonIdType personIdType = PersonIdType.Detect, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var resultTeamMembership = await _api.CreateTeamMembershipAsync(teamId, personIdOrEmail, isModerator, personIdType, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultTeamMembership.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's DeleteTeamAsync method.
|
||||
/// </summary>
|
||||
/// <param name="teamId">Team id to be deleted.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public virtual async Task DeleteTeamAsync(string teamId, CancellationToken cancellationToken)
|
||||
{
|
||||
await _api.DeleteTeamAsync(teamId, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's DeleteTeamMembershipAsync method.
|
||||
/// </summary>
|
||||
/// <param name="membershipId">Team Membership id to be deleted.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public virtual async Task DeleteTeamMembershipAsync(string membershipId, CancellationToken cancellationToken)
|
||||
{
|
||||
await _api.DeleteTeamMembershipAsync(membershipId, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's GetTeamAsync method.
|
||||
/// </summary>
|
||||
/// <param name="teamId">Team id that the detail info is gotten.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The requested team.</returns>
|
||||
public virtual async Task<Team> GetTeamAsync(string teamId, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultTeam = await _api.GetTeamAsync(teamId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultTeam.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's GetTeamMembershipAsync method.
|
||||
/// </summary>
|
||||
/// <param name="membershipId">Team Membership id that the detail info is gotten.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The requested team membership.</returns>
|
||||
public virtual async Task<TeamMembership> GetTeamMembershipAsync(string membershipId, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultTeamMembership = await _api.GetTeamMembershipAsync(membershipId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultTeamMembership.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's ListTeamMembershipsAsync method.
|
||||
/// </summary>
|
||||
/// <param name="teamId">List team memberships for a team, by ID.</param>
|
||||
/// <param name="max">Limit the maximum number of items in the response.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A list of team memberships.</returns>
|
||||
public virtual async Task<TeamMembershipList> ListTeamMembershipsAsync(string teamId, int? max = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var resultTeamMembershipList = await _api.ListTeamMembershipsAsync(teamId, max, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultTeamMembershipList.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's ListTeamsAsync method.
|
||||
/// </summary>
|
||||
/// <param name="max">Limit the maximum number of teams in the response.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A list of the teams.</returns>
|
||||
public virtual async Task<TeamList> ListTeamsAsync(int? max = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var resultTeamsList = await _api.ListTeamsAsync(max, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultTeamsList.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's UpdateTeamAsync method.
|
||||
/// </summary>
|
||||
/// <param name="teamId">Team id to be updated.</param>
|
||||
/// <param name="name">A user-friendly name for the team.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The updated team.</returns>
|
||||
public virtual async Task<Team> UpdateTeamAsync(string teamId, string name, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultTeam = await _api.UpdateTeamAsync(teamId, name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultTeam.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's UpdateTeamMembershipAsync method.
|
||||
/// </summary>
|
||||
/// <param name="membershipId">Membership id to be updated.</param>
|
||||
/// <param name="isModerator">Set to true to make the person a team moderator.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The updated team membership.</returns>
|
||||
public virtual async Task<TeamMembership> UpdateTeamMembershipAsync(string membershipId, bool isModerator, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultTeamMembership = await _api.UpdateTeamMembershipAsync(membershipId, isModerator, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultTeamMembership.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's GetFileDataAsync method.
|
||||
/// </summary>
|
||||
/// <param name="fileUri">Uri of the file.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The teams file data.</returns>
|
||||
public virtual async Task<TeamsFileData> GetFileDataAsync(Uri fileUri, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultTeamsFileData = await _api.GetFileDataAsync(fileUri, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultTeamsFileData.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's GetFileInfoAsync method.
|
||||
/// </summary>
|
||||
/// <param name="fileUri">Uri of the file.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>The teams file info.</returns>
|
||||
public virtual async Task<TeamsFileInfo> GetFileInfoAsync(Uri fileUri, CancellationToken cancellationToken)
|
||||
{
|
||||
var resultTeamsFileInfo = await _api.GetFileInfoAsync(fileUri, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultTeamsFileInfo.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's ListMessagesAsync method.
|
||||
/// </summary>
|
||||
/// <param name="spaceId">List messages for a space, by ID.</param>
|
||||
/// <param name="mentionedPeople">List messages where the caller is mentioned by specifying "me" or the caller personId.</param>
|
||||
/// <param name="before">List messages sent before a date and time.</param>
|
||||
/// <param name="beforeMessage">List messages sent before a message, by ID.</param>
|
||||
/// <param name="max">Limit the maximum number of messages in the response.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A list of the messages.</returns>
|
||||
public virtual async Task<MessageList> ListMessagesAsync(string spaceId, string mentionedPeople = null, DateTime? before = null, string beforeMessage = null, int? max = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var resultMessageList = await _api.ListMessagesAsync(spaceId, mentionedPeople, before, beforeMessage, max, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultMessageList.GetData(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps Webex API's ListPeopleAsync method.
|
||||
/// </summary>
|
||||
/// <param name="email">List people with this email address. For non-admin requests, either this or displayName are required.</param>
|
||||
/// <param name="displayName">List people whose name starts with this string. For non-admin requests, either this or email are required.</param>
|
||||
/// <param name="ids">List people by ID. Accepts up to 85 person IDs.</param>
|
||||
/// <param name="max">Limit the maximum number of people in the response.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A list with the requested people.</returns>
|
||||
public virtual async Task<PersonList> ListPeopleAsync(string email = null, string displayName = null, IEnumerable<string> ids = null, int? max = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var resultPersonList = await _api.ListPeopleAsync(email, displayName, ids, max, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return resultPersonList.GetData(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
// Copyright (c) Microsoft Corporation.All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Newtonsoft.Json;
|
||||
using Thrzn41.WebexTeams.Version1;
|
||||
|
||||
#if SIGNASSEMBLY
|
||||
[assembly: InternalsVisibleTo("Microsoft.Bot.Builder.Adapters.Webex.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
|
||||
#else
|
||||
[assembly: InternalsVisibleTo("Microsoft.Bot.Builder.Adapters.Webex.Tests")]
|
||||
#endif
|
||||
|
||||
namespace Microsoft.Bot.Builder.Adapters.Webex
|
||||
{
|
||||
internal static class WebexHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a <see cref="Activity"/> using the body of a request.
|
||||
/// </summary>
|
||||
/// <param name="payload">The payload obtained from the body of the request.</param>
|
||||
/// <param name="identity">The identity of the bot.</param>
|
||||
/// <returns>An <see cref="Activity"/> object.</returns>
|
||||
public static Activity PayloadToActivity(WebhookEventData payload, Person identity)
|
||||
{
|
||||
if (payload == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var activity = new Activity
|
||||
{
|
||||
Id = payload.Id,
|
||||
Timestamp = new DateTime(),
|
||||
ChannelId = "webex",
|
||||
Conversation = new ConversationAccount
|
||||
{
|
||||
Id = payload.MessageData.SpaceId,
|
||||
},
|
||||
From = new ChannelAccount
|
||||
{
|
||||
Id = payload.ActorId,
|
||||
},
|
||||
Recipient = new ChannelAccount
|
||||
{
|
||||
Id = identity.Id,
|
||||
},
|
||||
ChannelData = payload,
|
||||
Type = ActivityTypes.Event,
|
||||
};
|
||||
|
||||
if (payload.MessageData.FileCount > 0)
|
||||
{
|
||||
activity.Attachments = HandleMessageAttachments(payload.MessageData);
|
||||
}
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a decrypted message by its Id.
|
||||
/// </summary>
|
||||
/// <param name="payload">The payload obtained from the body of the request.</param>
|
||||
/// <param name="decrypterFunc">The function used to decrypt the message.</param>
|
||||
/// <param name="cancellationToken">A cancellation token for the task.</param>
|
||||
/// <returns>A <see cref="Message"/> object.</returns>
|
||||
public static async Task<Message> GetDecryptedMessageAsync(WebhookEventData payload, Func<string, CancellationToken, Task<Message>> decrypterFunc, CancellationToken cancellationToken)
|
||||
{
|
||||
if (payload == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return await decrypterFunc(payload.MessageData.Id, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a decrypted <see cref="Message"/> into an <see cref="Activity"/>.
|
||||
/// </summary>
|
||||
/// <param name="decryptedMessage">The decrypted message obtained from the body of the request.</param>
|
||||
/// <param name="identity">The identity of the bot.</param>
|
||||
/// <returns>An <see cref="Activity"/> object.</returns>
|
||||
public static Activity DecryptedMessageToActivity(Message decryptedMessage, Person identity)
|
||||
{
|
||||
if (decryptedMessage == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var activity = new Activity
|
||||
{
|
||||
Id = decryptedMessage.Id,
|
||||
Timestamp = new DateTime(),
|
||||
ChannelId = "webex",
|
||||
Conversation = new ConversationAccount
|
||||
{
|
||||
Id = decryptedMessage.SpaceId,
|
||||
},
|
||||
From = new ChannelAccount
|
||||
{
|
||||
Id = decryptedMessage.PersonId,
|
||||
Name = decryptedMessage.PersonEmail,
|
||||
},
|
||||
Recipient = new ChannelAccount
|
||||
{
|
||||
Id = identity.Id,
|
||||
},
|
||||
Text = !string.IsNullOrEmpty(decryptedMessage.Text) ? decryptedMessage.Text : string.Empty,
|
||||
ChannelData = decryptedMessage,
|
||||
Type = ActivityTypes.Message,
|
||||
};
|
||||
|
||||
// this is the bot speaking
|
||||
if (activity.From.Id == identity.Id)
|
||||
{
|
||||
activity.Type = ActivityTypes.Event;
|
||||
activity.Name = "self_message";
|
||||
}
|
||||
|
||||
if (decryptedMessage.HasHtml)
|
||||
{
|
||||
// strip the mention & HTML from the message
|
||||
var pattern = new Regex($"^(<p>|<div>)?<spark-mention .*?data-object-id=\"{identity.Id}\".*?>.*?</spark-mention>", RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
if (!pattern.IsMatch(decryptedMessage.Html))
|
||||
{
|
||||
var encodedId = $"{identity.Id}=";
|
||||
var buffer = Convert.FromBase64String(encodedId);
|
||||
var decodedId = Encoding.ASCII.GetString(buffer);
|
||||
|
||||
// this should look like ciscospark://us/PEOPLE/<id string>
|
||||
var match = Regex.Match(decodedId, "ciscospark://.*/(.*)", RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
if (match.Captures.Count > 0)
|
||||
{
|
||||
pattern = new Regex(
|
||||
$"^(<p>|<div>)?<spark-mention .*?data-object-id=\"{match.Groups[1]}\".*?>.*?</spark-mention>", RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
}
|
||||
}
|
||||
|
||||
var action = pattern.Replace(decryptedMessage.Html, string.Empty);
|
||||
|
||||
// Strip the remaining HTML tags and replace the message text with the HTML version
|
||||
var remainingHtml = new Regex("<.*?>", RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
activity.Text = remainingHtml.Replace(action, string.Empty).Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
var pattern = new Regex("^" + identity.DisplayName + "\\s+");
|
||||
activity.Text = pattern.Replace(activity.Text, string.Empty);
|
||||
}
|
||||
|
||||
if (decryptedMessage.FileCount > 0)
|
||||
{
|
||||
activity.Attachments = HandleMessageAttachments(decryptedMessage);
|
||||
}
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a decrypted related to an attachment action into an <see cref="Activity"/>.
|
||||
/// </summary>
|
||||
/// <param name="decryptedMessage">The decrypted message obtained from the body of the request.</param>
|
||||
/// <param name="identity">The identity of the bot.</param>
|
||||
/// <returns>An <see cref="Activity"/> object.</returns>
|
||||
public static Activity AttachmentActionToActivity(Message decryptedMessage, Person identity)
|
||||
{
|
||||
if (decryptedMessage == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var data = JsonConvert.SerializeObject(decryptedMessage);
|
||||
|
||||
var messageExtraData = JsonConvert.DeserializeObject<AttachmentActionData>(data);
|
||||
|
||||
var activity = new Activity
|
||||
{
|
||||
Id = decryptedMessage.Id,
|
||||
Timestamp = new DateTime(),
|
||||
ChannelId = "webex",
|
||||
Conversation = new ConversationAccount
|
||||
{
|
||||
Id = decryptedMessage.SpaceId,
|
||||
},
|
||||
From = new ChannelAccount
|
||||
{
|
||||
Id = decryptedMessage.PersonId,
|
||||
Name = decryptedMessage.PersonEmail,
|
||||
},
|
||||
Recipient = new ChannelAccount
|
||||
{
|
||||
Id = identity.Id,
|
||||
},
|
||||
Text = !string.IsNullOrEmpty(decryptedMessage.Text) ? decryptedMessage.Text : string.Empty,
|
||||
Value = messageExtraData.Inputs,
|
||||
ChannelData = decryptedMessage,
|
||||
Type = ActivityTypes.Event,
|
||||
};
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the message's files to a attachments list.
|
||||
/// </summary>
|
||||
/// <param name="message">The message with the files to process.</param>
|
||||
/// <returns>A list of attachments containing the message's files.</returns>
|
||||
public static List<Attachment> HandleMessageAttachments(Message message)
|
||||
{
|
||||
var attachmentsList = new List<Attachment>();
|
||||
|
||||
for (var i = 0; i < message.FileCount; i++)
|
||||
{
|
||||
var attachment = new Attachment
|
||||
{
|
||||
ContentUrl = message.FileUris[i].AbsoluteUri,
|
||||
};
|
||||
|
||||
attachmentsList.Add(attachment);
|
||||
}
|
||||
|
||||
if (attachmentsList.Count > 1)
|
||||
{
|
||||
throw new Exception("Currently Webex API takes only one attachment");
|
||||
}
|
||||
|
||||
return attachmentsList;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Adapters.Webex
|
||||
{
|
||||
public class WebexMessageRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebexMessageRequest"/> class.
|
||||
/// Represents the request needed to create a message with attachments.
|
||||
/// </summary>
|
||||
public WebexMessageRequest()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the room ID of the message.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The room ID of the message.
|
||||
/// </value>
|
||||
[JsonProperty(PropertyName = "roomId")]
|
||||
public string RoomId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the person ID of the recipient when sending a private 1:1 message.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The person ID of the recipient when sending a private 1:1 message.
|
||||
/// </value>
|
||||
[JsonProperty(PropertyName = "toPersonId")]
|
||||
public string ToPersonId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email address of the recipient when sending a private 1:1 message.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email address of the recipient when sending a private 1:1 message.
|
||||
/// </value>
|
||||
[JsonProperty(PropertyName = "toPersonEmail")]
|
||||
public string ToPersonEmail { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text of the message.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The text of the message.
|
||||
/// </value>
|
||||
[JsonProperty(PropertyName = "text")]
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message in Markdown format.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The message, in Markdown format.
|
||||
/// </value>
|
||||
[JsonProperty(PropertyName = "markdown")]
|
||||
public string Markdown { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the URI to a binary file to be posted into the room. Only one file is allowed per message.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The URI to a binary file to be posted into the room.
|
||||
/// </value>
|
||||
[JsonProperty(PropertyName = "files")]
|
||||
public IList<Uri> Files { get; } = new List<Uri>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content attachments to attach to the message.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The content attachments to attach to the message.
|
||||
/// </value>
|
||||
[JsonProperty(PropertyName = "attachments")]
|
||||
public object Attachments { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if Files property should be serialized or not.
|
||||
/// </summary>
|
||||
/// <returns>True if there are files in the array to be serialized, false if there aren't.</returns>
|
||||
public bool ShouldSerializeFiles()
|
||||
{
|
||||
return Files.Count > 0;
|
||||
}
|
||||
}
|
||||
}
|
После Ширина: | Высота: | Размер: 1.9 KiB |
После Ширина: | Высота: | Размер: 1.9 KiB |
|
@ -1,8 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -46,6 +46,20 @@ namespace Microsoft.Bot.Builder.AI.Luis
|
|||
/// <param name="includeApiResults">(Optional) TRUE to include raw LUIS API response.</param>
|
||||
/// <param name="clientHandler">(Optional) Custom handler for LUIS API calls to allow mocking.</param>
|
||||
public LuisRecognizer(LuisApplication application, LuisPredictionOptions predictionOptions = null, bool includeApiResults = false, HttpClientHandler clientHandler = null)
|
||||
: this(application, telemetryClient: null, logPersonalInformation: false, predictionOptions: predictionOptions, includeApiResults: includeApiResults, clientHandler: clientHandler)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LuisRecognizer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="application">The LUIS application to use to recognize text.</param>
|
||||
/// <param name="predictionOptions">(Optional) The LUIS prediction options to use.</param>
|
||||
/// <param name="includeApiResults">(Optional) TRUE to include raw LUIS API response.</param>
|
||||
/// <param name="clientHandler">(Optional) Custom handler for LUIS API calls to allow mocking.</param>
|
||||
/// <param name="telemetryClient">The IBotTelemetryClient used to log the LuisResult event.</param>
|
||||
/// <param name="logPersonalInformation">TRUE to include personally indentifiable information.</param>
|
||||
public LuisRecognizer(LuisApplication application, IBotTelemetryClient telemetryClient, bool logPersonalInformation, LuisPredictionOptions predictionOptions = null, bool includeApiResults = false, HttpClientHandler clientHandler = null)
|
||||
{
|
||||
_application = application ?? throw new ArgumentNullException(nameof(application));
|
||||
_options = predictionOptions ?? new LuisPredictionOptions();
|
||||
|
@ -189,7 +203,7 @@ namespace Microsoft.Bot.Builder.AI.Luis
|
|||
/// <param name="telemetryMetrics">Additional metrics to be logged to telemetry with the LuisResult event.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>The LUIS results of the analysis of the current message text in the current turn's context activity.</returns>
|
||||
public virtual async Task<RecognizerResult> RecognizeAsync(ITurnContext turnContext, Dictionary<string, string> telemetryProperties, Dictionary<string, double> telemetryMetrics = null, CancellationToken cancellationToken = default)
|
||||
public virtual async Task<RecognizerResult> RecognizeAsync(ITurnContext turnContext, Dictionary<string, string> telemetryProperties, Dictionary<string, double> telemetryMetrics = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
=> await RecognizeInternalAsync(turnContext, null, telemetryProperties, telemetryMetrics, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
|
@ -202,7 +216,7 @@ namespace Microsoft.Bot.Builder.AI.Luis
|
|||
/// <param name="telemetryMetrics">Additional metrics to be logged to telemetry with the LuisResult event.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>The LUIS results of the analysis of the current message text in the current turn's context activity.</returns>
|
||||
public virtual async Task<RecognizerResult> RecognizeAsync(ITurnContext turnContext, LuisPredictionOptions predictionOptions, Dictionary<string, string> telemetryProperties, Dictionary<string, double> telemetryMetrics = null, CancellationToken cancellationToken = default)
|
||||
public virtual async Task<RecognizerResult> RecognizeAsync(ITurnContext turnContext, LuisPredictionOptions predictionOptions, Dictionary<string, string> telemetryProperties, Dictionary<string, double> telemetryMetrics = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
=> await RecognizeInternalAsync(turnContext, predictionOptions, telemetryProperties, telemetryMetrics, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
|
@ -214,7 +228,7 @@ namespace Microsoft.Bot.Builder.AI.Luis
|
|||
/// <param name="telemetryMetrics">Additional metrics to be logged to telemetry with the LuisResult event.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>The LUIS results of the analysis of the current message text in the current turn's context activity.</returns>
|
||||
public virtual async Task<T> RecognizeAsync<T>(ITurnContext turnContext, Dictionary<string, string> telemetryProperties, Dictionary<string, double> telemetryMetrics = null, CancellationToken cancellationToken = default)
|
||||
public virtual async Task<T> RecognizeAsync<T>(ITurnContext turnContext, Dictionary<string, string> telemetryProperties, Dictionary<string, double> telemetryMetrics = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
where T : IRecognizerConvert, new()
|
||||
{
|
||||
var result = new T();
|
||||
|
@ -233,7 +247,7 @@ namespace Microsoft.Bot.Builder.AI.Luis
|
|||
/// <param name="telemetryMetrics">Additional metrics to be logged to telemetry with the LuisResult event.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>The LUIS results of the analysis of the current message text in the current turn's context activity.</returns>
|
||||
public virtual async Task<T> RecognizeAsync<T>(ITurnContext turnContext, LuisPredictionOptions predictionOptions, Dictionary<string, string> telemetryProperties, Dictionary<string, double> telemetryMetrics = null, CancellationToken cancellationToken = default)
|
||||
public virtual async Task<T> RecognizeAsync<T>(ITurnContext turnContext, LuisPredictionOptions predictionOptions, Dictionary<string, string> telemetryProperties, Dictionary<string, double> telemetryMetrics = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
where T : IRecognizerConvert, new()
|
||||
{
|
||||
var result = new T();
|
||||
|
@ -250,7 +264,7 @@ namespace Microsoft.Bot.Builder.AI.Luis
|
|||
/// <param name="telemetryMetrics">Additional metrics to be logged to telemetry with the LuisResult event.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns><see cref="Task"/>.</returns>
|
||||
protected virtual async Task OnRecognizerResultAsync(RecognizerResult recognizerResult, ITurnContext turnContext, Dictionary<string, string> telemetryProperties = null, Dictionary<string, double> telemetryMetrics = null, CancellationToken cancellationToken = default)
|
||||
protected virtual async Task OnRecognizerResultAsync(RecognizerResult recognizerResult, ITurnContext turnContext, Dictionary<string, string> telemetryProperties = null, Dictionary<string, double> telemetryMetrics = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var properties = await FillLuisEventPropertiesAsync(recognizerResult, turnContext, telemetryProperties, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
@ -268,7 +282,7 @@ namespace Microsoft.Bot.Builder.AI.Luis
|
|||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// additionalProperties
|
||||
/// <returns>A dictionary that is sent as "Properties" to IBotTelemetryClient.TrackEvent method for the BotMessageSend event.</returns>
|
||||
protected Task<Dictionary<string, string>> FillLuisEventPropertiesAsync(RecognizerResult recognizerResult, ITurnContext turnContext, Dictionary<string, string> telemetryProperties = null, CancellationToken cancellationToken = default)
|
||||
protected Task<Dictionary<string, string>> FillLuisEventPropertiesAsync(RecognizerResult recognizerResult, ITurnContext turnContext, Dictionary<string, string> telemetryProperties = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var topTwoIntents = (recognizerResult.Intents.Count > 0) ? recognizerResult.Intents.OrderByDescending(x => x.Value.Score).Take(2).ToArray() : null;
|
||||
|
||||
|
|
|
@ -1,37 +1,43 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Version Condition=" '$(PackageVersion)' == '' ">4.0.0-local</Version>
|
||||
<Version Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</Version>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' == '' ">4.0.0-local</PackageVersion>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</PackageVersion>
|
||||
<Configurations>Debug;Release;Debug - NuGet Packages</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<DelaySign>true</DelaySign>
|
||||
<AssemblyOriginatorKeyFile>..\..\build\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<DocumentationFile>bin\$(Configuration)\netstandard2.0\Microsoft.Bot.Builder.AI.Luis.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<PackageId>Microsoft.Bot.Builder.AI.Luis</PackageId>
|
||||
<Description>LUIS Middleware and Recognizers for the Microsoft Bot Builder SDK</Description>
|
||||
<Summary>This library implements C# classes for building bots using LUIS.</Summary>
|
||||
<PropertyGroup>
|
||||
<Version Condition=" '$(PackageVersion)' == '' ">4.6.0-local</Version>
|
||||
<Version Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</Version>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' == '' ">4.6.0-local</PackageVersion>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</PackageVersion>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AsyncUsageAnalyzers" Version="1.0.0-alpha003" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Bot.Configuration" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Configuration" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
||||
<PackageReference Include="SourceLink.Create.CommandLine" Version="2.8.3" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DocumentationFile>bin\$(Configuration)\netstandard2.0\Microsoft.Bot.Builder.AI.Luis.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<PackageId>Microsoft.Bot.Builder.AI.Luis</PackageId>
|
||||
<Description>LUIS Middleware and Recognizers for the Microsoft Bot Builder SDK</Description>
|
||||
<Summary>This library implements C# classes for building bots using LUIS.</Summary>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="**/*.dialog" />
|
||||
<Content Include="**/*.lg" />
|
||||
<Content Include="**/*.lu" />
|
||||
<Content Include="**/*.schema" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AsyncUsageAnalyzers" Version="1.0.0-alpha003" PrivateAssets="all" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
||||
<PackageReference Include="SourceLink.Create.CommandLine" Version="2.8.3" />
|
||||
<PackageReference Include="Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Bot.Configuration" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Configuration" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Bot.Configuration\Microsoft.Bot.Configuration.csproj" />
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-dotnet/4.Future/schemas/component.schema",
|
||||
"$role": "unionType(Microsoft.IRecognizer)",
|
||||
"title": "LUIS Recognizer",
|
||||
"description": "LUIS recognizer.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"applicationId": {
|
||||
"type": "string"
|
||||
},
|
||||
"endpoint": {
|
||||
"type": "string"
|
||||
},
|
||||
"endpointKey": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"applicationId",
|
||||
"endpoint",
|
||||
"endpointKey"
|
||||
]
|
||||
}
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using LuisV2 = Microsoft.Bot.Builder.AI.Luis;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
namespace Microsoft.Bot.Builder.AI.LuisV3
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines an extension for a list entity.
|
|
@ -2,8 +2,9 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using LuisV2 = Microsoft.Bot.Builder.AI.Luis;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
namespace Microsoft.Bot.Builder.AI.LuisV3
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a user predicted entity that extends an already existing one.
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using LuisV2 = Microsoft.Bot.Builder.AI.Luis;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
namespace Microsoft.Bot.Builder.AI.LuisV3
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a sub-list to append to an existing list entity.
|
|
@ -4,8 +4,9 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using LuisV2 = Microsoft.Bot.Builder.AI.Luis;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
namespace Microsoft.Bot.Builder.AI.LuisV3
|
||||
{
|
||||
/// <summary>
|
||||
/// Data describing a LUIS application.
|
|
@ -2,9 +2,9 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Bot.Builder.AI.LuisV3;
|
||||
using LuisV2 = Microsoft.Bot.Builder.AI.Luis;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
namespace Microsoft.Bot.Builder.AI.LuisV3
|
||||
{
|
||||
/// <summary>
|
||||
/// Optional parameters for a LUIS prediction request.
|
|
@ -12,14 +12,15 @@ using Microsoft.Bot.Schema;
|
|||
using Microsoft.Rest;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using LuisV2 = Microsoft.Bot.Builder.AI.Luis;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
namespace Microsoft.Bot.Builder.AI.LuisV3
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// A LUIS based implementation of <see cref="ITelemetryRecognizer"/> for the V3 endpoint.
|
||||
/// </summary>
|
||||
public class LuisRecognizer : ITelemetryRecognizer
|
||||
public class LuisRecognizer : LuisV2.ITelemetryRecognizer
|
||||
{
|
||||
/// <summary>
|
||||
/// The value type for a LUIS trace activity.
|
||||
|
@ -49,7 +50,7 @@ namespace Microsoft.Bot.Builder.AI.Luis
|
|||
TelemetryClient = recognizerOptions.TelemetryClient;
|
||||
LogPersonalInformation = recognizerOptions.LogPersonalInformation;
|
||||
|
||||
var delegatingHandler = new LuisDelegatingHandler();
|
||||
var delegatingHandler = new LuisV2.LuisDelegatingHandler();
|
||||
var httpClientHandler = recognizerOptions.HttpClient ?? CreateRootHandler();
|
||||
var currentHandler = CreateHttpHandlerPipeline(httpClientHandler, delegatingHandler);
|
||||
|
||||
|
@ -222,7 +223,7 @@ namespace Microsoft.Bot.Builder.AI.Luis
|
|||
var properties = FillLuisEventProperties(recognizerResult, turnContext, telemetryProperties);
|
||||
|
||||
// Track the event
|
||||
TelemetryClient.TrackEvent(LuisTelemetryConstants.LuisResult, properties, telemetryMetrics);
|
||||
TelemetryClient.TrackEvent(LuisV2.LuisTelemetryConstants.LuisResult, properties, telemetryMetrics);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -240,34 +241,34 @@ namespace Microsoft.Bot.Builder.AI.Luis
|
|||
// Add the intent score and conversation id properties
|
||||
var properties = new Dictionary<string, string>()
|
||||
{
|
||||
{ LuisTelemetryConstants.ApplicationIdProperty, _application.ApplicationId },
|
||||
{ LuisTelemetryConstants.IntentProperty, topTwoIntents?[0].Key ?? string.Empty },
|
||||
{ LuisTelemetryConstants.IntentScoreProperty, topTwoIntents?[0].Value.Score?.ToString("N2") ?? "0.00" },
|
||||
{ LuisTelemetryConstants.Intent2Property, (topTwoIntents?.Count() > 1) ? topTwoIntents?[1].Key ?? string.Empty : string.Empty },
|
||||
{ LuisTelemetryConstants.IntentScore2Property, (topTwoIntents?.Count() > 1) ? topTwoIntents?[1].Value.Score?.ToString("N2") ?? "0.00" : "0.00" },
|
||||
{ LuisTelemetryConstants.FromIdProperty, turnContext.Activity.From.Id },
|
||||
{ LuisV2.LuisTelemetryConstants.ApplicationIdProperty, _application.ApplicationId },
|
||||
{ LuisV2.LuisTelemetryConstants.IntentProperty, topTwoIntents?[0].Key ?? string.Empty },
|
||||
{ LuisV2.LuisTelemetryConstants.IntentScoreProperty, topTwoIntents?[0].Value.Score?.ToString("N2") ?? "0.00" },
|
||||
{ LuisV2.LuisTelemetryConstants.Intent2Property, (topTwoIntents?.Count() > 1) ? topTwoIntents?[1].Key ?? string.Empty : string.Empty },
|
||||
{ LuisV2.LuisTelemetryConstants.IntentScore2Property, (topTwoIntents?.Count() > 1) ? topTwoIntents?[1].Value.Score?.ToString("N2") ?? "0.00" : "0.00" },
|
||||
{ LuisV2.LuisTelemetryConstants.FromIdProperty, turnContext.Activity.From.Id },
|
||||
};
|
||||
|
||||
if (recognizerResult.Properties.TryGetValue("sentiment", out var sentiment) && sentiment is JObject)
|
||||
{
|
||||
if (((JObject)sentiment).TryGetValue("label", out var label))
|
||||
{
|
||||
properties.Add(LuisTelemetryConstants.SentimentLabelProperty, label.Value<string>());
|
||||
properties.Add(LuisV2.LuisTelemetryConstants.SentimentLabelProperty, label.Value<string>());
|
||||
}
|
||||
|
||||
if (((JObject)sentiment).TryGetValue("score", out var score))
|
||||
{
|
||||
properties.Add(LuisTelemetryConstants.SentimentScoreProperty, score.Value<string>());
|
||||
properties.Add(LuisV2.LuisTelemetryConstants.SentimentScoreProperty, score.Value<string>());
|
||||
}
|
||||
}
|
||||
|
||||
var entities = recognizerResult.Entities?.ToString();
|
||||
properties.Add(LuisTelemetryConstants.EntitiesProperty, entities);
|
||||
properties.Add(LuisV2.LuisTelemetryConstants.EntitiesProperty, entities);
|
||||
|
||||
// Use the LogPersonalInformation flag to toggle logging PII data, text is a common example
|
||||
if (LogPersonalInformation && !string.IsNullOrEmpty(turnContext.Activity.Text))
|
||||
{
|
||||
properties.Add(LuisTelemetryConstants.QuestionProperty, turnContext.Activity.Text);
|
||||
properties.Add(LuisV2.LuisTelemetryConstants.QuestionProperty, turnContext.Activity.Text);
|
||||
}
|
||||
|
||||
// Additional Properties can override "stock" properties.
|
|
@ -4,8 +4,9 @@
|
|||
using System;
|
||||
using System.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using LuisV2 = Microsoft.Bot.Builder.AI.Luis;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
namespace Microsoft.Bot.Builder.AI.LuisV3
|
||||
{
|
||||
/// <summary>
|
||||
/// Optional parameters for a LUIS recognizer.
|
|
@ -4,8 +4,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using LuisV2 = Microsoft.Bot.Builder.AI.Luis;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
namespace Microsoft.Bot.Builder.AI.LuisV3
|
||||
{
|
||||
// Utility functions used to extract and transform data from Luis SDK
|
||||
internal static class LuisUtil
|
После Ширина: | Высота: | Размер: 1.9 KiB |
|
@ -1,50 +0,0 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
/// Recognizer with Telemetry support.
|
||||
/// </summary>
|
||||
public interface ITelemetryRecognizer : IRecognizer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether determines whether to log personal information that came from the user.
|
||||
/// </summary>
|
||||
/// <value>If true, will log personal information into the IBotTelemetryClient.TrackEvent method; otherwise the properties will be filtered.</value>
|
||||
bool LogPersonalInformation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the currently configured <see cref="IBotTelemetryClient"/> that logs the LuisResult event.
|
||||
/// </summary>
|
||||
/// <value>The <see cref="IBotTelemetryClient"/> being used to log events.</value>
|
||||
IBotTelemetryClient TelemetryClient { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Return results of the analysis (suggested intents and entities) using the turn context.
|
||||
/// </summary>
|
||||
/// <param name="turnContext">Context object containing information for a single turn of conversation with a user.</param>
|
||||
/// <param name="telemetryProperties">Additional properties to be logged to telemetry with the LuisResult event.</param>
|
||||
/// <param name="telemetryMetrics">Additional metrics to be logged to telemetry with the LuisResult event.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>The LUIS results of the analysis of the current message text in the current turn's context activity.</returns>
|
||||
Task<RecognizerResult> RecognizeAsync(ITurnContext turnContext, Dictionary<string, string> telemetryProperties, Dictionary<string, double> telemetryMetrics, CancellationToken cancellationToken = default);
|
||||
|
||||
Task<T> RecognizeAsync<T>(ITurnContext turnContext, Dictionary<string, string> telemetryProperties, Dictionary<string, double> telemetryMetrics, CancellationToken cancellationToken = default)
|
||||
where T : IRecognizerConvert, new();
|
||||
|
||||
/// <summary>
|
||||
/// Runs an utterance through a recognizer and returns a strongly-typed recognizer result.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The recognition result type.</typeparam>
|
||||
/// <param name="turnContext">Turn context.</param>
|
||||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
/// <returns>Analysis of utterance.</returns>
|
||||
new Task<T> RecognizeAsync<T>(ITurnContext turnContext, CancellationToken cancellationToken = default)
|
||||
where T : IRecognizerConvert, new();
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
internal class LuisDelegatingHandler : DelegatingHandler
|
||||
{
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
// Bot Builder Package name and version.
|
||||
var assemblyName = this.GetType().Assembly.GetName();
|
||||
request.Headers.UserAgent.Add(new ProductInfoHeaderValue(assemblyName.Name, assemblyName.Version.ToString()));
|
||||
|
||||
// Platform information: OS and language runtime.
|
||||
var framework = Assembly
|
||||
.GetEntryAssembly()?
|
||||
.GetCustomAttribute<TargetFrameworkAttribute>()?
|
||||
.FrameworkName;
|
||||
var comment = $"({Environment.OSVersion.VersionString};{framework})";
|
||||
request.Headers.UserAgent.Add(new ProductInfoHeaderValue(comment));
|
||||
|
||||
// Forward the call.
|
||||
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
/// The IBotTelemetryClient event and property names that logged by default.
|
||||
/// </summary>
|
||||
public static class LuisTelemetryConstants
|
||||
{
|
||||
public static readonly string LuisResult = "LuisResult"; // Event name
|
||||
public static readonly string ApplicationIdProperty = "applicationId";
|
||||
public static readonly string IntentProperty = "intent";
|
||||
public static readonly string IntentScoreProperty = "intentScore";
|
||||
public static readonly string Intent2Property = "intent2";
|
||||
public static readonly string IntentScore2Property = "intentScore2";
|
||||
public static readonly string EntitiesProperty = "entities";
|
||||
public static readonly string QuestionProperty = "question";
|
||||
public static readonly string ActivityIdProperty = "activityId";
|
||||
public static readonly string SentimentLabelProperty = "sentimentLabel";
|
||||
public static readonly string SentimentScoreProperty = "sentimentScore";
|
||||
public static readonly string FromIdProperty = "fromId";
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<Version>4.0.0-local</Version>
|
||||
<Description>LUIS V3 endpoint Middleware and Recognizers for the Microsoft Bot Builder SDK</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Version="4.5.1" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.ApplicationInsights" Version="4.5.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
/// Strongly typed LUIS builtin_age.
|
||||
/// </summary>
|
||||
public class Age : NumberWithUnits
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Age"/> class.
|
||||
/// </summary>
|
||||
/// <param name="age">Age.</param>
|
||||
/// <param name="units">Units for age.</param>
|
||||
public Age(double age, string units)
|
||||
: base(age, units)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"Age({Number} {Units})";
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the built-in LUIS date-time type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// LUIS recognizes time expressions like "next monday" and converts those to a type and set of timex expressions.
|
||||
/// More information on timex can be found here: http://www.timeml.org/publications/timeMLdocs/timeml_1.2.1.html#timex3.
|
||||
/// More information on the library which does the recognition can be found here: https://github.com/Microsoft/Recognizers-Text.
|
||||
/// </remarks>
|
||||
public class DateTimeSpec
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DateTimeSpec"/> class.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of TIMEX expression.</param>
|
||||
/// <param name="expressions">The TIMEX expression.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="type"/> is null or contains only white space,
|
||||
/// or <paramref name="expressions"/> is null.</exception>
|
||||
public DateTimeSpec(string type, IEnumerable<string> expressions)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(type))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
if (expressions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(expressions));
|
||||
}
|
||||
|
||||
Type = type;
|
||||
Expressions = expressions.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets type of expression.
|
||||
/// </summary>
|
||||
/// <remarks>Example types include:
|
||||
/// <list type="*">
|
||||
/// <item>time -- simple time expression like "3pm".</item>
|
||||
/// <item>date -- simple date like "july 3rd".</item>
|
||||
/// <item>datetime -- combination of date and time like "march 23 2pm".</item>
|
||||
/// <item>timerange -- a range of time like "2pm to 4pm".</item>
|
||||
/// <item>daterange -- a range of dates like "march 23rd to 24th".</item>
|
||||
/// <item>datetimerange -- a range of dates and times like "july 3rd 2pm to 5th 4pm".</item>
|
||||
/// <item>set -- a recurrence like "every monday".</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// The type of expression.
|
||||
/// </value>
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets Timex expressions.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Timex expressions.
|
||||
/// </value>
|
||||
[JsonProperty("timex")]
|
||||
public IReadOnlyList<string> Expressions { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"DateTimeSpec({Type}, [{string.Join(", ", Expressions)}]";
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
/// Strongly typed LUIS builtin_dimension.
|
||||
/// </summary>
|
||||
public class Dimension : NumberWithUnits
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Dimension"/> class.
|
||||
/// </summary>
|
||||
/// <param name="number">Number.</param>
|
||||
/// <param name="units">Units for number.</param>
|
||||
public Dimension(double number, string units)
|
||||
: base(number, units)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"Dimension({Number} {Units})";
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
/// Strongly typed LUIS builtin GeographyV2.
|
||||
/// </summary>
|
||||
public class GeographyV2
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeographyV2"/> class.
|
||||
/// </summary>
|
||||
/// <param name="type">Type of geographic location from <see cref="Types"/>.</param>
|
||||
/// <param name="location">Geographic location.</param>
|
||||
public GeographyV2(string type, string location)
|
||||
{
|
||||
Type = type;
|
||||
Location = location;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets type of geographic location.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Type of geographic location from <see cref="Types"/>.
|
||||
/// </value>
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets geographic location.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Geographic location.
|
||||
/// </value>
|
||||
[JsonProperty("location")]
|
||||
public string Location { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"GeographyV2({Type}, {Location})";
|
||||
|
||||
/// <summary>
|
||||
/// Different types of geographic locations.
|
||||
/// </summary>
|
||||
public static class Types
|
||||
{
|
||||
public const string POI = "poi";
|
||||
public const string City = "city";
|
||||
public const string CountryRegion = "countryRegion";
|
||||
public const string Continent = "continent";
|
||||
public const string State = "state";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
/// Strongly typed information corresponding to LUIS $instance value.
|
||||
/// </summary>
|
||||
public class InstanceData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets 0-based index in the analyzed text for where entity starts.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// 0-based index in the analyzed text for where entity starts.
|
||||
/// </value>
|
||||
[JsonProperty("startIndex")]
|
||||
public int StartIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets 0-based index of the first character beyond the recognized entity.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// 0-based index of the first character beyond the recognized entity.
|
||||
/// </value>
|
||||
[JsonProperty("endIndex")]
|
||||
public int EndIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets word broken and normalized text for the entity.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Word broken and normalized text for the entity.
|
||||
/// </value>
|
||||
[JsonProperty("text")]
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets optional confidence in the recognition.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Optional confidence in the recognition.
|
||||
/// </value>
|
||||
[JsonProperty("score")]
|
||||
public double? Score { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets optional type for the entity.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Optional entity type.
|
||||
/// </value>
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets optional subtype for the entity.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Optional entity subtype.
|
||||
/// </value>
|
||||
[JsonProperty("subtype")]
|
||||
public string Subtype { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets any extra properties.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Any extra properties.
|
||||
/// </value>
|
||||
[JsonExtensionData(ReadData = true, WriteData = true)]
|
||||
public IDictionary<string, object> Properties { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
/// Strongly typed LUIS builtin_money.
|
||||
/// </summary>
|
||||
public class Money : NumberWithUnits
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Money"/> class.
|
||||
/// </summary>
|
||||
/// <param name="money">Money amount.</param>
|
||||
/// <param name="units">Currency units.</param>
|
||||
public Money(double money, string units)
|
||||
: base(money, units)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"Currency({Number} {Units})";
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
/// Strongly typed class for LUIS number and units entity recognition.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Specific subtypes of this class are generated to match the builtin age, currency, dimension and temperature entities.
|
||||
/// </remarks>
|
||||
public class NumberWithUnits
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NumberWithUnits"/> class.
|
||||
/// </summary>
|
||||
/// <param name="number">Number.</param>
|
||||
/// <param name="units">Units for number.</param>
|
||||
public NumberWithUnits(double? number, string units)
|
||||
{
|
||||
Number = number;
|
||||
Units = units;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets recognized number, or null if unit only.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Recognized number, or null if unit only.
|
||||
/// </value>
|
||||
[JsonProperty("number")]
|
||||
public double? Number { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets normalized recognized unit.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Normalized recognized unit.
|
||||
/// </value>
|
||||
[JsonProperty("units")]
|
||||
public string Units { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
/// Strongly typed LUIS builtin OrdinalV2.
|
||||
/// </summary>
|
||||
public class OrdinalV2
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OrdinalV2"/> class.
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset from <see cref="RelativeTo"/>.</param>
|
||||
/// <param name="relativeTo">Position that anchors offset.</param>
|
||||
public OrdinalV2(string relativeTo, long offset)
|
||||
{
|
||||
RelativeTo = relativeTo;
|
||||
Offset = offset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the anchor for the offset.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The base position in a sequence one of <see cref="Anchor"/>.
|
||||
/// </value>
|
||||
[JsonProperty("relativeTo")]
|
||||
public string RelativeTo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the offset in the sequence with respect to <see cref="RelativeTo"/>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Offset in sequence relative to <see cref="RelativeTo"/>.
|
||||
/// </value>
|
||||
[JsonProperty("offset")]
|
||||
public long Offset { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"OrdinalV2({RelativeTo}, {Offset})";
|
||||
|
||||
/// <summary>
|
||||
/// Possible anchors for offsets.
|
||||
/// </summary>
|
||||
public static class Anchor
|
||||
{
|
||||
public const string Current = "current";
|
||||
public const string End = "end";
|
||||
public const string Start = "start";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.Luis
|
||||
{
|
||||
/// <summary>
|
||||
/// Strongly typed LUIS builtin_temperature.
|
||||
/// </summary>
|
||||
public class Temperature : NumberWithUnits
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Temperature"/> class.
|
||||
/// </summary>
|
||||
/// <param name="temperature">Temperature.</param>
|
||||
/// <param name="units">Units.</param>
|
||||
public Temperature(double temperature, string units)
|
||||
: base(temperature, units)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"Temperature({Number} {Units})";
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.QnA
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Version Condition=" '$(PackageVersion)' == '' ">4.0.0-local</Version>
|
||||
<Version Condition=" '$(PackageVersion)' == '' ">4.6.0-local</Version>
|
||||
<Version Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</Version>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' == '' ">4.0.0-local</PackageVersion>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' == '' ">4.6.0-local</PackageVersion>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</PackageVersion>
|
||||
<Configurations>Debug;Release;Debug - NuGet Packages</Configurations>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<DelaySign>true</DelaySign>
|
||||
<AssemblyOriginatorKeyFile>..\..\build\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<DocumentationFile>bin\$(Configuration)\netstandard2.0\Microsoft.Bot.Builder.AI.QnA.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -21,17 +18,27 @@
|
|||
<Summary>This library implements C# classes for building bots using Microsoft Cognitive services.</Summary>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="**/*.dialog" />
|
||||
<Content Include="**/*.lg" />
|
||||
<Content Include="**/*.lu" />
|
||||
<Content Include="**/*.schema" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AsyncUsageAnalyzers" Version="1.0.0-alpha003" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Bot.Configuration" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Configuration" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Configuration" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
<PackageReference Include="SourceLink.Create.CommandLine" Version="2.8.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Bot.Configuration\Microsoft.Bot.Configuration.csproj" />
|
||||
</ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder.Dialogs\Microsoft.Bot.Builder.Dialogs.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Bot.Configuration\Microsoft.Bot.Configuration.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -20,5 +20,14 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
/// </value>
|
||||
[JsonProperty("answers")]
|
||||
public QueryResult[] Answers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether gets or set for the active learning enable flag.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The active learning enable flag.
|
||||
/// </value>
|
||||
[JsonProperty("activeLearningEnabled")]
|
||||
public bool ActiveLearningEnabled { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,6 +153,25 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
QnAMakerOptions options,
|
||||
Dictionary<string, string> telemetryProperties,
|
||||
Dictionary<string, double> telemetryMetrics = null)
|
||||
{
|
||||
var result = await GetAnswersRawAsync(turnContext, options, telemetryProperties, telemetryMetrics).ConfigureAwait(false);
|
||||
|
||||
return result.Answers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates an answer from the knowledge base.
|
||||
/// </summary>
|
||||
/// <param name="turnContext">The Turn Context that contains the user question to be queried against your knowledge base.</param>
|
||||
/// <param name="options">The options for the QnA Maker knowledge base. If null, constructor option is used for this instance.</param>
|
||||
/// <param name="telemetryProperties">Additional properties to be logged to telemetry with the QnaMessage event.</param>
|
||||
/// <param name="telemetryMetrics">Additional metrics to be logged to telemetry with the QnaMessage event.</param>
|
||||
/// <returns>A list of answers for the user query, sorted in decreasing order of ranking score.</returns>
|
||||
public async Task<QueryResults> GetAnswersRawAsync(
|
||||
ITurnContext turnContext,
|
||||
QnAMakerOptions options,
|
||||
Dictionary<string, string> telemetryProperties = null,
|
||||
Dictionary<string, double> telemetryMetrics = null)
|
||||
{
|
||||
if (turnContext == null)
|
||||
{
|
||||
|
@ -175,9 +194,9 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
throw new ArgumentException("Null or empty text");
|
||||
}
|
||||
|
||||
var result = await this.generateAnswerHelper.GetAnswersAsync(turnContext, messageActivity, options).ConfigureAwait(false);
|
||||
var result = await this.generateAnswerHelper.GetAnswersRawAsync(turnContext, messageActivity, options).ConfigureAwait(false);
|
||||
|
||||
await OnQnaResultsAsync(result, turnContext, telemetryProperties, telemetryMetrics, CancellationToken.None).ConfigureAwait(false);
|
||||
await OnQnaResultsAsync(result.Answers, turnContext, telemetryProperties, telemetryMetrics, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.Bot.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.QnA
|
||||
{
|
||||
|
@ -31,6 +32,7 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
/// <value>
|
||||
/// The knowledge base ID.
|
||||
/// </value>
|
||||
[JsonProperty("knowledgeBaseId")]
|
||||
public string KnowledgeBaseId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -39,6 +41,7 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
/// <value>
|
||||
/// The endpoint key for the knowledge base.
|
||||
/// </value>
|
||||
[JsonProperty("endpointKey")]
|
||||
public string EndpointKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -47,6 +50,7 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
/// <value>
|
||||
/// The host path.
|
||||
/// </value>
|
||||
[JsonProperty("host")]
|
||||
public string Host { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.QnA
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
/// <value>
|
||||
/// The minimum score threshold, used to filter returned results.
|
||||
/// </value>
|
||||
[JsonProperty("scoreThreshold")]
|
||||
public float ScoreThreshold { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -43,6 +44,7 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
/// <value>
|
||||
/// The number of ranked results you want in the output.
|
||||
/// </value>
|
||||
[JsonProperty("top")]
|
||||
public int Top { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -63,6 +65,7 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
|
||||
public Metadata[] StrictFilters { get; set; }
|
||||
|
||||
[JsonProperty("metadataBoost")]
|
||||
public Metadata[] MetadataBoost { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Newtonsoft.Json;
|
||||
|
@ -51,7 +49,22 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
/// <param name="messageActivity">Message activity of the turn context.</param>
|
||||
/// <param name="options">The options for the QnA Maker knowledge base. If null, constructor option is used for this instance.</param>
|
||||
/// <returns>A list of answers for the user query, sorted in decreasing order of ranking score.</returns>
|
||||
[Obsolete]
|
||||
public async Task<QueryResult[]> GetAnswersAsync(ITurnContext turnContext, IMessageActivity messageActivity, QnAMakerOptions options)
|
||||
{
|
||||
var result = await this.GetAnswersRawAsync(turnContext, messageActivity, options).ConfigureAwait(false);
|
||||
|
||||
return result.Answers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates an answer from the knowledge base.
|
||||
/// </summary>
|
||||
/// <param name="turnContext">The Turn Context that contains the user question to be queried against your knowledge base.</param>
|
||||
/// <param name="messageActivity">Message activity of the turn context.</param>
|
||||
/// <param name="options">The options for the QnA Maker knowledge base. If null, constructor option is used for this instance.</param>
|
||||
/// <returns>A list of answers for the user query, sorted in decreasing order of ranking score.</returns>
|
||||
public async Task<QueryResults> GetAnswersRawAsync(ITurnContext turnContext, IMessageActivity messageActivity, QnAMakerOptions options)
|
||||
{
|
||||
if (turnContext == null)
|
||||
{
|
||||
|
@ -73,12 +86,12 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
|
||||
var result = await QueryQnaServiceAsync((Activity)messageActivity, hydratedOptions).ConfigureAwait(false);
|
||||
|
||||
await EmitTraceInfoAsync(turnContext, (Activity)messageActivity, result, hydratedOptions).ConfigureAwait(false);
|
||||
await EmitTraceInfoAsync(turnContext, (Activity)messageActivity, result.Answers, hydratedOptions).ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static async Task<QueryResult[]> FormatQnaResultAsync(HttpResponseMessage response, QnAMakerOptions options)
|
||||
private static async Task<QueryResults> FormatQnaResultAsync(HttpResponseMessage response, QnAMakerOptions options)
|
||||
{
|
||||
var jsonResponse = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
|
||||
|
@ -89,9 +102,9 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
answer.Score = answer.Score / 100;
|
||||
}
|
||||
|
||||
var result = results.Answers.Where(answer => answer.Score > options.ScoreThreshold).ToArray();
|
||||
results.Answers = results.Answers.Where(answer => answer.Score > options.ScoreThreshold).ToArray();
|
||||
|
||||
return result;
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void ValidateOptions(QnAMakerOptions options)
|
||||
|
@ -170,7 +183,7 @@ namespace Microsoft.Bot.Builder.AI.QnA
|
|||
return hydratedOptions;
|
||||
}
|
||||
|
||||
private async Task<QueryResult[]> QueryQnaServiceAsync(Activity messageActivity, QnAMakerOptions options)
|
||||
private async Task<QueryResults> QueryQnaServiceAsync(Activity messageActivity, QnAMakerOptions options)
|
||||
{
|
||||
var requestUrl = $"{_endpoint.Host}/knowledgebases/{_endpoint.KnowledgeBaseId}/generateanswer";
|
||||
var jsonRequest = JsonConvert.SerializeObject(
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
|
||||
namespace Microsoft.Bot.Builder.AI.QnA
|
||||
{
|
||||
/// <summary>
|
||||
/// Message activity card builder for QnAMaker dialogs.
|
||||
/// </summary>
|
||||
public static class QnACardBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Get active learning suggestions card.
|
||||
/// </summary>
|
||||
/// <param name="suggestionsList">List of suggested questions.</param>
|
||||
/// <param name="cardTitle">Title of the cards.</param>
|
||||
/// <param name="cardNoMatchText">No match text.</param>
|
||||
/// <returns>IMessageActivity.</returns>
|
||||
public static IMessageActivity GetSuggestionsCard(List<string> suggestionsList, string cardTitle, string cardNoMatchText)
|
||||
{
|
||||
if (suggestionsList == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(suggestionsList));
|
||||
}
|
||||
|
||||
if (cardTitle == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(cardTitle));
|
||||
}
|
||||
|
||||
if (cardNoMatchText == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(cardNoMatchText));
|
||||
}
|
||||
|
||||
var chatActivity = Activity.CreateMessageActivity();
|
||||
var buttonList = new List<CardAction>();
|
||||
|
||||
// Add all suggestions
|
||||
foreach (var suggestion in suggestionsList)
|
||||
{
|
||||
buttonList.Add(
|
||||
new CardAction()
|
||||
{
|
||||
Value = suggestion,
|
||||
Type = "imBack",
|
||||
Title = suggestion,
|
||||
});
|
||||
}
|
||||
|
||||
// Add No match text
|
||||
buttonList.Add(
|
||||
new CardAction()
|
||||
{
|
||||
Value = cardNoMatchText,
|
||||
Type = "imBack",
|
||||
Title = cardNoMatchText
|
||||
});
|
||||
|
||||
var plCard = new HeroCard()
|
||||
{
|
||||
Text = cardTitle,
|
||||
Subtitle = string.Empty,
|
||||
Buttons = buttonList
|
||||
};
|
||||
|
||||
// Create the attachment.
|
||||
var attachment = plCard.ToAttachment();
|
||||
|
||||
chatActivity.Attachments.Add(attachment);
|
||||
|
||||
return chatActivity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get active learning suggestions card.
|
||||
/// </summary>
|
||||
/// <param name="result">Result to be dispalyed as prompts.</param>
|
||||
/// <param name="cardNoMatchText">No match text.</param>
|
||||
/// <returns>IMessageActivity.</returns>
|
||||
public static IMessageActivity GetQnAPromptsCard(QueryResult result, string cardNoMatchText)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(result));
|
||||
}
|
||||
|
||||
if (cardNoMatchText == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(cardNoMatchText));
|
||||
}
|
||||
|
||||
var chatActivity = Activity.CreateMessageActivity();
|
||||
var buttonList = new List<CardAction>();
|
||||
|
||||
// Add all prompt
|
||||
foreach (var prompt in result.Context.Prompts)
|
||||
{
|
||||
buttonList.Add(
|
||||
new CardAction()
|
||||
{
|
||||
Value = prompt.DisplayText,
|
||||
Type = "imBack",
|
||||
Title = prompt.DisplayText,
|
||||
});
|
||||
}
|
||||
|
||||
// Add No match text
|
||||
buttonList.Add(
|
||||
new CardAction()
|
||||
{
|
||||
Value = cardNoMatchText,
|
||||
Type = "imBack",
|
||||
Title = cardNoMatchText
|
||||
});
|
||||
|
||||
var plCard = new HeroCard()
|
||||
{
|
||||
Text = result.Answer,
|
||||
Subtitle = string.Empty,
|
||||
Buttons = buttonList
|
||||
};
|
||||
|
||||
// Create the attachment.
|
||||
var attachment = plCard.ToAttachment();
|
||||
|
||||
chatActivity.Attachments.Add(attachment);
|
||||
|
||||
return chatActivity;
|
||||
}
|
||||
}
|
||||
}
|
После Ширина: | Высота: | Размер: 1.9 KiB |
|
@ -1,33 +1,30 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version Condition=" '$(PackageVersion)' == '' ">4.0.0-local</Version>
|
||||
<Version Condition=" '$(PackageVersion)' == '' ">4.6.0-local</Version>
|
||||
<Version Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</Version>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' == '' ">4.0.0-local</PackageVersion>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' == '' ">4.6.0-local</PackageVersion>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</PackageVersion>
|
||||
<Configurations>Debug;Release;Debug - NuGet Packages</Configurations>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<PackageId>Microsoft.Bot.Builder.ApplicationInsights</PackageId>
|
||||
<Description>This library integrates the Microsoft Bot Builder SDK with Application Insights.</Description>
|
||||
<Summary>This library provides integration between the Microsoft Bot Builder SDK and Application Insights.</Summary>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<DelaySign>true</DelaySign>
|
||||
<AssemblyOriginatorKeyFile>..\..\build\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<DocumentationFile>bin\$(Configuration)\netstandard2.0\Microsoft.Bot.Builder.ApplicationInsights.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.8.1" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
<PackageReference Include="SourceLink.Create.CommandLine" Version="2.8.3" />
|
||||
<PackageReference Include="SourceLink.Create.CommandLine" Version="2.8.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
После Ширина: | Высота: | Размер: 1.9 KiB |
|
@ -85,21 +85,59 @@ namespace Microsoft.Bot.Builder.Azure
|
|||
{
|
||||
BotAssert.ActivityNotNull(activity);
|
||||
|
||||
var blobName = GetBlobName(activity);
|
||||
var blobReference = this.Container.Value.GetBlockBlobReference(blobName);
|
||||
blobReference.Properties.ContentType = "application/json";
|
||||
blobReference.Metadata["FromId"] = activity.From.Id;
|
||||
blobReference.Metadata["RecipientId"] = activity.Recipient.Id;
|
||||
blobReference.Metadata["Timestamp"] = activity.Timestamp.Value.ToString("O");
|
||||
using (var blobStream = await blobReference.OpenWriteAsync().ConfigureAwait(false))
|
||||
switch (activity.Type)
|
||||
{
|
||||
using (var jsonWriter = new JsonTextWriter(new StreamWriter(blobStream)))
|
||||
{
|
||||
_jsonSerializer.Serialize(jsonWriter, activity);
|
||||
}
|
||||
}
|
||||
case ActivityTypes.MessageUpdate:
|
||||
{
|
||||
var blob = await FindActivityBlobAsync(activity).ConfigureAwait(false);
|
||||
if (blob != null)
|
||||
{
|
||||
var originalActivity = JsonConvert.DeserializeObject<Activity>(await blob.DownloadTextAsync().ConfigureAwait(false));
|
||||
var updatedActivity = JsonConvert.DeserializeObject<Activity>(JsonConvert.SerializeObject(activity));
|
||||
updatedActivity.Type = ActivityTypes.Message; // fixup original type (should be Message)
|
||||
updatedActivity.LocalTimestamp = originalActivity.LocalTimestamp;
|
||||
updatedActivity.Timestamp = originalActivity.Timestamp;
|
||||
await LogActivityAsync(updatedActivity, blob).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await blobReference.SetMetadataAsync().ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
case ActivityTypes.MessageDelete:
|
||||
{
|
||||
var blob = await FindActivityBlobAsync(activity).ConfigureAwait(false);
|
||||
if (blob != null)
|
||||
{
|
||||
var originalActivity = JsonConvert.DeserializeObject<Activity>(await blob.DownloadTextAsync().ConfigureAwait(false));
|
||||
|
||||
// tombstone the original message
|
||||
var tombstonedActivity = new Activity()
|
||||
{
|
||||
Type = ActivityTypes.MessageDelete,
|
||||
Id = originalActivity.Id,
|
||||
From = new ChannelAccount(id: "deleted", role: originalActivity.From.Role),
|
||||
Recipient = new ChannelAccount(id: "deleted", role: originalActivity.Recipient.Role),
|
||||
Locale = originalActivity.Locale,
|
||||
LocalTimestamp = originalActivity.Timestamp,
|
||||
Timestamp = originalActivity.Timestamp,
|
||||
ChannelId = originalActivity.ChannelId,
|
||||
Conversation = originalActivity.Conversation,
|
||||
ServiceUrl = originalActivity.ServiceUrl,
|
||||
ReplyToId = originalActivity.ReplyToId,
|
||||
};
|
||||
|
||||
await LogActivityAsync(tombstonedActivity, blob).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
var blobName = GetBlobName(activity);
|
||||
var blobReference = this.Container.Value.GetBlockBlobReference(blobName);
|
||||
await LogActivityAsync(activity, blobReference).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -282,6 +320,24 @@ namespace Microsoft.Bot.Builder.Azure
|
|||
while (token != null);
|
||||
}
|
||||
|
||||
private static async Task LogActivityAsync(IActivity activity, CloudBlockBlob blobReference)
|
||||
{
|
||||
blobReference.Properties.ContentType = "application/json";
|
||||
blobReference.Metadata["Id"] = activity.Id;
|
||||
blobReference.Metadata["FromId"] = activity.From.Id;
|
||||
blobReference.Metadata["RecipientId"] = activity.Recipient.Id;
|
||||
blobReference.Metadata["Timestamp"] = activity.Timestamp.Value.ToString("O");
|
||||
using (var blobStream = await blobReference.OpenWriteAsync().ConfigureAwait(false))
|
||||
{
|
||||
using (var jsonWriter = new JsonTextWriter(new StreamWriter(blobStream)))
|
||||
{
|
||||
_jsonSerializer.Serialize(jsonWriter, activity);
|
||||
}
|
||||
}
|
||||
|
||||
await blobReference.SetMetadataAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static string GetBlobName(IActivity activity)
|
||||
{
|
||||
var blobName = $"{SanitizeKey(activity.ChannelId)}/{SanitizeKey(activity.Conversation.Id)}/{activity.Timestamp.Value.Ticks.ToString("x")}-{SanitizeKey(activity.Id)}.json";
|
||||
|
@ -313,5 +369,49 @@ namespace Microsoft.Bot.Builder.Azure
|
|||
// Blob Name rules: case-sensitive any url char
|
||||
return Uri.EscapeDataString(key);
|
||||
}
|
||||
|
||||
private async Task<CloudBlockBlob> FindActivityBlobAsync(IActivity activity)
|
||||
{
|
||||
var dirName = GetDirName(activity.ChannelId, activity.Conversation.Id);
|
||||
var dir = this.Container.Value.GetDirectoryReference(dirName);
|
||||
BlobContinuationToken token = null;
|
||||
List<CloudBlockBlob> blobs = new List<CloudBlockBlob>();
|
||||
do
|
||||
{
|
||||
var segment = await dir.ListBlobsSegmentedAsync(false, BlobListingDetails.Metadata, 50, token, null, null).ConfigureAwait(false);
|
||||
foreach (var blob in segment.Results.Cast<CloudBlockBlob>())
|
||||
{
|
||||
blob.Metadata.TryGetValue("Id", out string id);
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
if (id == activity.Id)
|
||||
{
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have to read full activity as it's an old blob
|
||||
var entry = JsonConvert.DeserializeObject<Activity>(await blob.DownloadTextAsync().ConfigureAwait(false));
|
||||
blob.Metadata["Id"] = entry.Id;
|
||||
|
||||
// update metadata with Id so we don't have to download again. This effectively "patches" old metadata records
|
||||
await blob.SetMetadataAsync().ConfigureAwait(false);
|
||||
if (entry.Id == activity.Id)
|
||||
{
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (segment.ContinuationToken != null)
|
||||
{
|
||||
token = segment.ContinuationToken;
|
||||
}
|
||||
}
|
||||
while (token != null);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,301 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.Cosmos;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Azure
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements an CosmosDB based storage provider using partitioning for a bot.
|
||||
/// </summary>
|
||||
public class CosmosDbPartitionedStorage : IStorage
|
||||
{
|
||||
private readonly JsonSerializer _jsonSerializer = JsonSerializer.Create(new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
|
||||
|
||||
private Container _container;
|
||||
private readonly CosmosDbPartitionedStorageOptions _cosmosDbStorageOptions;
|
||||
private CosmosClient _client;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CosmosDbPartitionedStorage"/> class.
|
||||
/// using the provided CosmosDB credentials, database ID, and container ID.
|
||||
/// </summary>
|
||||
/// <param name="cosmosDbStorageOptions">Cosmos DB partitioned storage configuration options.</param>
|
||||
public CosmosDbPartitionedStorage(CosmosDbPartitionedStorageOptions cosmosDbStorageOptions)
|
||||
{
|
||||
if (cosmosDbStorageOptions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(cosmosDbStorageOptions));
|
||||
}
|
||||
|
||||
if (cosmosDbStorageOptions.CosmosDbEndpoint == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(cosmosDbStorageOptions.CosmosDbEndpoint), "Service EndPoint for CosmosDB is required.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(cosmosDbStorageOptions.AuthKey))
|
||||
{
|
||||
throw new ArgumentException("AuthKey for CosmosDB is required.", nameof(cosmosDbStorageOptions.AuthKey));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(cosmosDbStorageOptions.DatabaseId))
|
||||
{
|
||||
throw new ArgumentException("DatabaseId is required.", nameof(cosmosDbStorageOptions.DatabaseId));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(cosmosDbStorageOptions.ContainerId))
|
||||
{
|
||||
throw new ArgumentException("ContainerId is required.", nameof(cosmosDbStorageOptions.ContainerId));
|
||||
}
|
||||
|
||||
_cosmosDbStorageOptions = cosmosDbStorageOptions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CosmosDbPartitionedStorage"/> class.
|
||||
/// using the provided CosmosDB credentials, database ID, and collection ID.
|
||||
/// </summary>
|
||||
/// <param name="cosmosDbStorageOptions">Cosmos DB partitioned storage configuration options.</param>
|
||||
/// <param name="jsonSerializer">If passing in a custom JsonSerializer, we recommend the following settings:
|
||||
/// <para>jsonSerializer.TypeNameHandling = TypeNameHandling.All.</para>
|
||||
/// <para>jsonSerializer.NullValueHandling = NullValueHandling.Include.</para>
|
||||
/// <para>jsonSerializer.ContractResolver = new DefaultContractResolver().</para>
|
||||
/// </param>
|
||||
public CosmosDbPartitionedStorage(CosmosDbPartitionedStorageOptions cosmosDbStorageOptions, JsonSerializer jsonSerializer)
|
||||
: this(cosmosDbStorageOptions)
|
||||
{
|
||||
_jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer));
|
||||
}
|
||||
|
||||
public async Task<IDictionary<string, object>> ReadAsync(string[] keys, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (keys == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(keys));
|
||||
}
|
||||
|
||||
if (keys.Length == 0)
|
||||
{
|
||||
// No keys passed in, no result to return.
|
||||
return new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
// Ensure Initialization has been run
|
||||
await InitializeAsync().ConfigureAwait(false);
|
||||
|
||||
var storeItems = new Dictionary<string, object>(keys.Length);
|
||||
|
||||
foreach (var key in keys)
|
||||
{
|
||||
try
|
||||
{
|
||||
var escapedKey = CosmosDbKeyEscape.EscapeKey(key);
|
||||
|
||||
var readItemResponse = await _container.ReadItemAsync<DocumentStoreItem>(
|
||||
escapedKey,
|
||||
new PartitionKey(escapedKey),
|
||||
cancellationToken: cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var documentStoreItem = readItemResponse.Resource;
|
||||
var item = documentStoreItem.Document.ToObject(typeof(object), _jsonSerializer);
|
||||
|
||||
if (item is IStoreItem storeItem)
|
||||
{
|
||||
storeItem.ETag = documentStoreItem.ETag;
|
||||
storeItems.Add(documentStoreItem.RealId, storeItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
storeItems.Add(documentStoreItem.RealId, item);
|
||||
}
|
||||
}
|
||||
catch (CosmosException exception)
|
||||
{
|
||||
// When an item is not found a CosmosException is thrown, but we want to
|
||||
// return an empty collection so in this instance we catch and do not rethrow.
|
||||
// Throw for any other exception.
|
||||
if (exception.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return storeItems;
|
||||
}
|
||||
|
||||
public async Task WriteAsync(IDictionary<string, object> changes, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (changes == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(changes));
|
||||
}
|
||||
|
||||
if (changes.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure Initialization has been run
|
||||
await InitializeAsync().ConfigureAwait(false);
|
||||
|
||||
foreach (var change in changes)
|
||||
{
|
||||
var json = JObject.FromObject(change.Value, _jsonSerializer);
|
||||
|
||||
// Remove etag from JSON object that was copied from IStoreItem.
|
||||
// The ETag information is updated as an _etag attribute in the document metadata.
|
||||
json.Remove("eTag");
|
||||
|
||||
var documentChange = new DocumentStoreItem
|
||||
{
|
||||
Id = CosmosDbKeyEscape.EscapeKey(change.Key),
|
||||
RealId = change.Key,
|
||||
Document = json,
|
||||
};
|
||||
|
||||
var etag = (change.Value as IStoreItem)?.ETag;
|
||||
if (etag == null || etag == "*")
|
||||
{
|
||||
// if new item or * then insert or replace unconditionally
|
||||
await _container.UpsertItemAsync(
|
||||
documentChange,
|
||||
new PartitionKey(documentChange.PartitionKey),
|
||||
cancellationToken: cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
else if (etag.Length > 0)
|
||||
{
|
||||
// if we have an etag, do opt. concurrency replace
|
||||
await _container.UpsertItemAsync(
|
||||
documentChange,
|
||||
new PartitionKey(documentChange.PartitionKey),
|
||||
new ItemRequestOptions() { IfMatchEtag = etag, },
|
||||
cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("etag empty");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(string[] keys, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (keys == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(keys));
|
||||
}
|
||||
|
||||
await InitializeAsync().ConfigureAwait(false);
|
||||
|
||||
foreach (var key in keys)
|
||||
{
|
||||
var escapedKey = CosmosDbKeyEscape.EscapeKey(key);
|
||||
|
||||
try
|
||||
{
|
||||
await _container.DeleteItemAsync<DocumentStoreItem>(
|
||||
partitionKey: new PartitionKey(escapedKey),
|
||||
id: escapedKey,
|
||||
cancellationToken: cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (CosmosException exception)
|
||||
{
|
||||
// If we get a 404 status then the item we tried to delete was not found
|
||||
// To maintain consistency with other storage providers, we ignore this and return.
|
||||
// Any other exceptions are thrown.
|
||||
if (exception.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connects to the CosmosDB database and creates / gets the container.
|
||||
/// </summary>
|
||||
private async Task InitializeAsync()
|
||||
{
|
||||
if (_container == null)
|
||||
{
|
||||
var cosmosClientOptions = _cosmosDbStorageOptions.CosmosClientOptions ?? new CosmosClientOptions();
|
||||
|
||||
if (_client == null)
|
||||
{
|
||||
_client = new CosmosClient(
|
||||
_cosmosDbStorageOptions.CosmosDbEndpoint,
|
||||
_cosmosDbStorageOptions.AuthKey,
|
||||
cosmosClientOptions);
|
||||
}
|
||||
|
||||
if (_container == null)
|
||||
{
|
||||
var containerResponse = await _client
|
||||
.GetDatabase(_cosmosDbStorageOptions.DatabaseId)
|
||||
.DefineContainer(_cosmosDbStorageOptions.ContainerId, DocumentStoreItem.PartitionKeyPath)
|
||||
.WithIndexingPolicy().WithAutomaticIndexing(false).WithIndexingMode(IndexingMode.None).Attach()
|
||||
.CreateIfNotExistsAsync(_cosmosDbStorageOptions.ContainerThroughput)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
_container = containerResponse.Container;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal data structure for storing items in a CosmosDB Collection.
|
||||
/// </summary>
|
||||
private class DocumentStoreItem : IStoreItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the PartitionKey path to be used for this document type.
|
||||
/// </summary>
|
||||
public static string PartitionKeyPath => "/id";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sanitized Id/Key used as PrimaryKey.
|
||||
/// </summary>
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the un-sanitized Id/Key.
|
||||
/// </summary>
|
||||
[JsonProperty("realId")]
|
||||
public string RealId { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the persisted object.
|
||||
/// </summary>
|
||||
[JsonProperty("document")]
|
||||
public JObject Document { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ETag information for handling optimistic concurrency updates.
|
||||
/// </summary>
|
||||
[JsonProperty("_etag")]
|
||||
public string ETag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the PartitionKey value for the document.
|
||||
/// </summary>
|
||||
public string PartitionKey => this.Id;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using Microsoft.Azure.Cosmos;
|
||||
using Microsoft.Azure.Documents;
|
||||
using Microsoft.Azure.Documents.Client;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Azure
|
||||
{
|
||||
/// <summary>
|
||||
/// Cosmos DB Partitioned Storage Options.
|
||||
/// </summary>
|
||||
public class CosmosDbPartitionedStorageOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the CosmosDB endpoint.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The CosmosDB endpoint.
|
||||
/// </value>
|
||||
public string CosmosDbEndpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the authentication key for Cosmos DB.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The authentication key for Cosmos DB.
|
||||
/// </value>
|
||||
public string AuthKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the database identifier for Cosmos DB instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The database identifier for Cosmos DB instance.
|
||||
/// </value>
|
||||
public string DatabaseId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container identifier.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The container identifier.
|
||||
/// </value>
|
||||
public string ContainerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the options for the CosmosClient.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The options for use with the CosmosClient.
|
||||
/// </value>
|
||||
public CosmosClientOptions CosmosClientOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the throughput set when creating the Container. Defaults to 400.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Container throughput. Defaults to 400.
|
||||
/// </value>
|
||||
public int ContainerThroughput { get; set; } = 400;
|
||||
}
|
||||
}
|
|
@ -79,6 +79,7 @@ namespace Microsoft.Bot.Builder.Azure
|
|||
|
||||
// Invoke CollectionPolicy delegate to further customize settings
|
||||
cosmosDbStorageOptions.ConnectionPolicyConfigurator?.Invoke(connectionPolicy);
|
||||
|
||||
_client = new DocumentClient(cosmosDbStorageOptions.CosmosDBEndpoint, cosmosDbStorageOptions.AuthKey, connectionPolicy);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Version Condition=" '$(PackageVersion)' == '' ">4.0.0-local</Version>
|
||||
<Version Condition=" '$(PackageVersion)' == '' ">4.6.0-local</Version>
|
||||
<Version Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</Version>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' == '' ">4.0.0-local</PackageVersion>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' == '' ">4.6.0-local</PackageVersion>
|
||||
<PackageVersion Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</PackageVersion>
|
||||
<Configurations>Debug;Release;Debug - NuGet Packages</Configurations>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<DelaySign>true</DelaySign>
|
||||
<AssemblyOriginatorKeyFile>..\..\build\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<DocumentationFile>bin\$(Configuration)\netstandard2.0\Microsoft.Bot.Builder.Azure.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -21,14 +18,14 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- The KeyVault package, picked up as a transitive dependency of the Azure Storage libraries
|
||||
<!-- The KeyVault package, picked up as a transitive dependency of the Azure Storage libraries
|
||||
doesn't yet support NetStandard20. I confirmed with the Azure Storage team that this warning
|
||||
is fine, and can be supressed.
|
||||
|
||||
is fine, and can be supressed.
|
||||
|
||||
It does appear the Azure SDK team is "in-process" of supporting NetStandard20 as seen in this
|
||||
Commit: https://github.com/Azure/azure-sdk-for-net/commit/b0d42d14bfe92a24996826b2487ba592e644f581
|
||||
|
||||
We cannot apply the no-warn supression directly to the package links below as
|
||||
|
||||
We cannot apply the no-warn supression directly to the package links below as
|
||||
they're not picked up across transitive dependencies. See this GitHub Issue for details:
|
||||
https://github.com/NuGet/Home/issues/5740
|
||||
-->
|
||||
|
@ -36,17 +33,26 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="**/*.dialog" />
|
||||
<Content Include="**/*.lg" />
|
||||
<Content Include="**/*.lu" />
|
||||
<Content Include="**/*.schema" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Rest.ClientRuntime" Version="2.3.20" />
|
||||
<PackageReference Include="AsyncUsageAnalyzers" Version="1.0.0-alpha003" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="2.1.2" />
|
||||
<PackageReference Include="Microsoft.Azure.Storage.Blob" Version="9.4.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
||||
<PackageReference Include="SourceLink.Create.CommandLine" Version="2.8.3" />
|
||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.4.0" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
|
||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.1" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' == '' " Version="4.6.0-local" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
После Ширина: | Высота: | Размер: 1.9 KiB |
|
@ -0,0 +1,31 @@
|
|||
// Licensed under the MIT License.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
||||
{
|
||||
[DebuggerDisplay("{ChangeType}:{Desire}")]
|
||||
public class ActionChangeList
|
||||
{
|
||||
[JsonProperty(PropertyName = "changeType")]
|
||||
public ActionChangeType ChangeType { get; set; } = ActionChangeType.InsertActions;
|
||||
|
||||
[JsonProperty(PropertyName = "actions")]
|
||||
public List<ActionState> Actions { get; set; } = new List<ActionState>();
|
||||
|
||||
[JsonProperty(PropertyName = "tags")]
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets turn state associated with the plan change list (it will be applied to turn state when plan is applied).
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Turn state associated with the plan change list (it will be applied to turn state when plan is applied).
|
||||
/// </value>
|
||||
[JsonProperty(PropertyName = "turn")]
|
||||
public Dictionary<string, object> Turn { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Licensed under the MIT License.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
||||
{
|
||||
/// <summary>
|
||||
/// How to modify an action sequence.
|
||||
/// </summary>
|
||||
public enum ActionChangeType
|
||||
{
|
||||
/// <summary>
|
||||
/// Add the change actions to the head of the sequence.
|
||||
/// </summary>
|
||||
InsertActions,
|
||||
|
||||
/// <summary>
|
||||
/// Add the changeactions to the tail of the sequence.
|
||||
/// </summary>
|
||||
AppendActions,
|
||||
|
||||
/// <summary>
|
||||
/// Terminate the action sequence.
|
||||
/// </summary>
|
||||
EndSequence,
|
||||
|
||||
/// <summary>
|
||||
/// Terminate the action sequence, then add the change actions.
|
||||
/// </summary>
|
||||
ReplaceSequence,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Licensed under the MIT License.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using System.Diagnostics;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive
|
||||
{
|
||||
[DebuggerDisplay("{DialogId}")]
|
||||
public class ActionState : DialogState
|
||||
{
|
||||
public ActionState()
|
||||
{
|
||||
}
|
||||
|
||||
public ActionState(string dialogId = null, object options = null)
|
||||
{
|
||||
DialogId = dialogId;
|
||||
Options = options;
|
||||
}
|
||||
|
||||
[JsonProperty(PropertyName = "dialogId")]
|
||||
public string DialogId { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "options")]
|
||||
public object Options { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
// Licensed under the MIT License.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Bot.Expressions;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Action which calls another dialog.
|
||||
/// </summary>
|
||||
public abstract class BaseInvokeDialog : Dialog, IDialogDependencies
|
||||
{
|
||||
// Expression for dialogId to call (allowing dynamic expression)
|
||||
private string dialogIdToCall;
|
||||
|
||||
public BaseInvokeDialog(string dialogIdToCall = null, IDictionary<string, string> bindingOptions = null)
|
||||
: base()
|
||||
{
|
||||
this.dialogIdToCall = dialogIdToCall;
|
||||
|
||||
if (bindingOptions != null)
|
||||
{
|
||||
this.Options = bindingOptions;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets configurable options for the dialog.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Configurable options for the dialog.
|
||||
/// </value>
|
||||
public object Options { get; set; } = new JObject();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the dialog to call.
|
||||
/// </summary>
|
||||
public Dialog Dialog { get; set; }
|
||||
|
||||
public virtual IEnumerable<Dialog> GetDependencies()
|
||||
{
|
||||
if (Dialog != null)
|
||||
{
|
||||
yield return Dialog;
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
protected override string OnComputeId()
|
||||
{
|
||||
return $"{this.GetType().Name}[{Dialog?.Id ?? this.dialogIdToCall}]";
|
||||
}
|
||||
|
||||
protected Dialog ResolveDialog(DialogContext dc)
|
||||
{
|
||||
if (this.Dialog != null)
|
||||
{
|
||||
return this.Dialog;
|
||||
}
|
||||
|
||||
var dialogId = this.dialogIdToCall ?? throw new Exception($"{this.GetType().Name} requires a dialog to be called.");
|
||||
return dc.FindDialog(dialogId) ?? throw new Exception($"{dialogId} not found.");
|
||||
}
|
||||
|
||||
protected object BindOptions(DialogContext dc, object options)
|
||||
{
|
||||
// binding options are static definition of options with overlay of passed in options);
|
||||
var bindingOptions = (JObject)ObjectPath.Merge(Options, options ?? new JObject());
|
||||
var boundOptions = new JObject();
|
||||
|
||||
foreach (var binding in bindingOptions)
|
||||
{
|
||||
// evalute the value
|
||||
var (result, error) = new ExpressionEngine().Parse(binding.Value.ToString()).TryEvaluate(dc.State);
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
throw new Exception(error);
|
||||
}
|
||||
|
||||
// and store in options as the result
|
||||
boundOptions[binding.Key] = JToken.FromObject(result);
|
||||
}
|
||||
|
||||
return boundOptions;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Licensed under the MIT License.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Action which begins executing another dialog, when it is done, it will return to the caller.
|
||||
/// </summary>
|
||||
public class BeginDialog : BaseInvokeDialog
|
||||
{
|
||||
[JsonConstructor]
|
||||
public BeginDialog(string dialogIdToCall = null, IDictionary<string, string> options = null, [CallerFilePath] string callerPath = "", [CallerLineNumber] int callerLine = 0)
|
||||
: base(dialogIdToCall, options)
|
||||
{
|
||||
this.RegisterSourceLocation(callerPath, callerLine);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the property path to store the dialog result in
|
||||
/// </summary>
|
||||
public string ResultProperty { get; set; }
|
||||
|
||||
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (options is CancellationToken)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
|
||||
}
|
||||
|
||||
var dialog = this.ResolveDialog(dc);
|
||||
|
||||
// use bindingOptions to bind to the bound options
|
||||
var boundOptions = BindOptions(dc, options);
|
||||
|
||||
// start dialog with bound options passed in as the options
|
||||
return await dc.BeginDialogAsync(dialog.Id, options: boundOptions, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public override async Task<DialogTurnResult> ResumeDialogAsync(DialogContext dc, DialogReason reason, object result = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (this.ResultProperty != null)
|
||||
{
|
||||
dc.State.SetValue(this.ResultProperty, result);
|
||||
}
|
||||
|
||||
// By default just end the current dialog and return result to parent.
|
||||
return await dc.EndDialogAsync(result, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// Licensed under the MIT License.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Expressions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Command to cancel all of the current dialogs by emitting an event which must be caught to prevent cancelation from propagating.
|
||||
/// </summary>
|
||||
public class CancelAllDialogs : Dialog
|
||||
{
|
||||
[JsonConstructor]
|
||||
public CancelAllDialogs([CallerFilePath] string callerPath = "", [CallerLineNumber] int callerLine = 0)
|
||||
: base()
|
||||
{
|
||||
this.RegisterSourceLocation(callerPath, callerLine);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets event name.
|
||||
/// </summary>
|
||||
public string EventName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets value expression for EventValue
|
||||
/// </summary>
|
||||
public string EventValue { get; set; }
|
||||
|
||||
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (options is CancellationToken)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
|
||||
}
|
||||
|
||||
object eventValue = null;
|
||||
if (this.EventValue != null)
|
||||
{
|
||||
eventValue = new ExpressionEngine().Parse(this.EventValue).TryEvaluate(dc.State);
|
||||
}
|
||||
|
||||
if (dc.Parent == null)
|
||||
{
|
||||
return await dc.CancelAllDialogsAsync(EventName, eventValue, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
var turnResult = await dc.Parent.CancelAllDialogsAsync(EventName, eventValue, cancellationToken).ConfigureAwait(false);
|
||||
turnResult.ParentEnded = true;
|
||||
return turnResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
// Licensed under the MIT License.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Bot.Expressions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
||||
{
|
||||
public class Case
|
||||
{
|
||||
public Case(string value = null, IEnumerable<Dialog> actions = null)
|
||||
{
|
||||
this.Value = value;
|
||||
this.Actions = actions?.ToList() ?? this.Actions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets value expression to be compared against condition.
|
||||
/// </summary>
|
||||
[JsonProperty("value")]
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets set of actions to be executed given that the condition of the switch matches the value of this case.
|
||||
/// </summary>
|
||||
[JsonProperty("actions")]
|
||||
public List<Dialog> Actions { get; set; } = new List<Dialog>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates an expression that returns the value in its primitive type. Still
|
||||
/// assumes that switch case values are compile time constants and not expressions
|
||||
/// that can be evaluated against state.
|
||||
/// </summary>
|
||||
/// <returns>An expression that reflects the constant case value.</returns>
|
||||
public Expression CreateValueExpression()
|
||||
{
|
||||
Expression expression = null;
|
||||
|
||||
if (long.TryParse(Value, out long i))
|
||||
{
|
||||
expression = Expression.ConstantExpression(i);
|
||||
}
|
||||
else if (float.TryParse(Value, out float f))
|
||||
{
|
||||
expression = Expression.ConstantExpression(f);
|
||||
}
|
||||
else if (bool.TryParse(Value, out bool b))
|
||||
{
|
||||
expression = Expression.ConstantExpression(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
expression = Expression.ConstantExpression(Value);
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// Licensed under the MIT License.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
||||
{
|
||||
using CodeActionHandler = System.Func<Microsoft.Bot.Builder.Dialogs.DialogContext, object, System.Threading.Tasks.Task<Microsoft.Bot.Builder.Dialogs.DialogTurnResult>>;
|
||||
|
||||
public class CodeAction : Dialog
|
||||
{
|
||||
private readonly CodeActionHandler codeHandler;
|
||||
|
||||
public CodeAction(CodeActionHandler codeHandler, [CallerFilePath] string callerPath = "", [CallerLineNumber] int callerLine = 0)
|
||||
: base()
|
||||
{
|
||||
this.RegisterSourceLocation(callerPath, callerLine);
|
||||
this.codeHandler = codeHandler ?? throw new ArgumentNullException(nameof(codeHandler));
|
||||
}
|
||||
|
||||
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (options is CancellationToken)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
|
||||
}
|
||||
|
||||
return await this.codeHandler(dc, options).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected override string OnComputeId()
|
||||
{
|
||||
return $"{this.GetType().Name}({codeHandler.ToString()})";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
||||
{
|
||||
public class DebugBreak : Dialog
|
||||
{
|
||||
public DebugBreak([CallerFilePath] string callerPath = "", [CallerLineNumber] int callerLine = 0)
|
||||
{
|
||||
this.RegisterSourceLocation(callerPath, callerLine);
|
||||
}
|
||||
|
||||
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
DebugDump(dc);
|
||||
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
Debugger.Break();
|
||||
}
|
||||
|
||||
return await dc.EndDialogAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private void DebugDump(DialogContext dc)
|
||||
{
|
||||
// Best effort
|
||||
try
|
||||
{
|
||||
// Compute path
|
||||
var path = string.Empty;
|
||||
var connector = string.Empty;
|
||||
|
||||
var current = dc.Parent;
|
||||
while (current != null)
|
||||
{
|
||||
path = current.ActiveDialog?.Id ?? string.Empty + connector + path;
|
||||
connector = "/";
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
// Get list of actions
|
||||
var stepState = dc is SequenceContext sc ? sc.Actions : new List<ActionState>();
|
||||
var actionsIds = stepState.Select(s => s.DialogId);
|
||||
|
||||
Debug.WriteLine($"{path}: {actionsIds.Count()} actions remaining.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Failed to collect full debug dump. Error: {ex.ToString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
// Licensed under the MIT License.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Deletes a property from memory.
|
||||
/// </summary>
|
||||
public class DeleteProperty : Dialog
|
||||
{
|
||||
[JsonConstructor]
|
||||
public DeleteProperty([CallerFilePath] string callerPath = "", [CallerLineNumber] int callerLine = 0)
|
||||
: base()
|
||||
{
|
||||
this.RegisterSourceLocation(callerPath, callerLine);
|
||||
}
|
||||
|
||||
public DeleteProperty(string property, [CallerFilePath] string callerPath = "", [CallerLineNumber] int callerLine = 0)
|
||||
: base()
|
||||
{
|
||||
this.RegisterSourceLocation(callerPath, callerLine);
|
||||
if (!string.IsNullOrEmpty(property))
|
||||
{
|
||||
this.Property = property;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets property path to remove.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// user.age will remove "age" from "user".
|
||||
/// </example>
|
||||
public string Property { get; set; }
|
||||
|
||||
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (options is CancellationToken)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
|
||||
}
|
||||
|
||||
// Ensure planning context
|
||||
if (dc is SequenceContext planning)
|
||||
{
|
||||
dc.State.RemoveValue(Property);
|
||||
return await dc.EndDialogAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("`ClearProperty` should only be used in the context of an adaptive dialog.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|