mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: Rename workflows projects (#975)
* Renaming Microsoft.Agent.Workflows to Microsoft.Agents.AI.Workflows * Removing local settings. * Removing remining old files from merge.
This commit is contained in:
+55
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class AddConversationMessageExecutor(AddConversationMessage model, WorkflowAgentProvider agentProvider, WorkflowFormulaState state) :
|
||||
DeclarativeActionExecutor<AddConversationMessage>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
|
||||
string conversationId = this.Evaluator.GetValue(this.Model.ConversationId).Value;
|
||||
|
||||
ChatMessage newMessage = new(this.Model.Role.Value.ToChatRole(), [.. this.GetContent()]) { AdditionalProperties = this.GetMetadata() };
|
||||
|
||||
await agentProvider.CreateMessageAsync(conversationId, newMessage, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await this.AssignAsync(this.Model.Message?.Path, newMessage.ToRecord(), context).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
private IEnumerable<AIContent> GetContent()
|
||||
{
|
||||
foreach (AddConversationMessageContent content in this.Model.Content)
|
||||
{
|
||||
AIContent? messageContent = content.Type.Value.ToContent(this.Engine.Format(content.Value));
|
||||
if (messageContent is not null)
|
||||
{
|
||||
yield return messageContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AdditionalPropertiesDictionary? GetMetadata()
|
||||
{
|
||||
if (this.Model.Metadata is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
RecordDataValue? metadataValue = this.Evaluator.GetValue(this.Model.Metadata).Value;
|
||||
|
||||
return metadataValue.ToMetadata();
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Bot.ObjectModel.Abstractions;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class ClearAllVariablesExecutor(ClearAllVariables model, WorkflowFormulaState state)
|
||||
: DeclarativeActionExecutor<ClearAllVariables>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
EvaluationResult<VariablesToClearWrapper> variablesResult = this.Evaluator.GetValue(this.Model.Variables);
|
||||
|
||||
string? scope = variablesResult.Value.Value switch
|
||||
{
|
||||
VariablesToClear.AllGlobalVariables => VariableScopeNames.Global,
|
||||
VariablesToClear.ConversationScopedVariables => WorkflowFormulaState.DefaultScopeName,
|
||||
VariablesToClear.ConversationHistory => null,
|
||||
VariablesToClear.UserScopedVariables => null,
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (scope is not null)
|
||||
{
|
||||
await context.QueueClearScopeAsync(scope).ConfigureAwait(false);
|
||||
Debug.WriteLine(
|
||||
$"""
|
||||
STATE: {this.GetType().Name} [{this.Id}]
|
||||
SCOPE: {scope}
|
||||
""");
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Bot.ObjectModel.Abstractions;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class ConditionGroupExecutor : DeclarativeActionExecutor<ConditionGroup>
|
||||
{
|
||||
public static class Steps
|
||||
{
|
||||
public static string Item(ConditionGroup model, ConditionItem conditionItem)
|
||||
{
|
||||
if (conditionItem.Id is not null)
|
||||
{
|
||||
return conditionItem.Id;
|
||||
}
|
||||
int index = model.Conditions.IndexOf(conditionItem);
|
||||
return $"{model.Id}_Items{index}";
|
||||
}
|
||||
|
||||
public static string Else(ConditionGroup model) => model.ElseActions.Id.Value ?? $"{model.Id}_Else";
|
||||
}
|
||||
|
||||
public ConditionGroupExecutor(ConditionGroup model, WorkflowFormulaState state)
|
||||
: base(model, state)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool IsDiscreteAction => false;
|
||||
|
||||
public bool IsMatch(ConditionItem conditionItem, object? message)
|
||||
{
|
||||
ActionExecutorResult executorMessage = ActionExecutorResult.ThrowIfNot(message);
|
||||
return string.Equals(Steps.Item(this.Model, conditionItem), executorMessage.Result as string, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public bool IsElse(object? message)
|
||||
{
|
||||
ActionExecutorResult executorMessage = ActionExecutorResult.ThrowIfNot(message);
|
||||
return string.Equals(Steps.Else(this.Model), executorMessage.Result as string, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
for (int index = 0; index < this.Model.Conditions.Length; ++index)
|
||||
{
|
||||
ConditionItem conditionItem = this.Model.Conditions[index];
|
||||
if (conditionItem.Condition is null)
|
||||
{
|
||||
continue; // Skip if no condition is defined
|
||||
}
|
||||
|
||||
EvaluationResult<bool> expressionResult = this.Evaluator.GetValue(conditionItem.Condition);
|
||||
if (expressionResult.Value)
|
||||
{
|
||||
return Steps.Item(this.Model, conditionItem);
|
||||
}
|
||||
}
|
||||
|
||||
return Steps.Else(this.Model);
|
||||
}
|
||||
|
||||
public async ValueTask DoneAsync(IWorkflowContext context, ActionExecutorResult _, CancellationToken cancellationToken) =>
|
||||
await context.RaiseCompletionEventAsync(this.Model).ConfigureAwait(false);
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Bot.ObjectModel.Abstractions;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class CopyConversationMessagesExecutor(CopyConversationMessages model, WorkflowAgentProvider agentProvider, WorkflowFormulaState state) :
|
||||
DeclarativeActionExecutor<CopyConversationMessages>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
|
||||
string conversationId = this.Evaluator.GetValue(this.Model.ConversationId).Value;
|
||||
|
||||
IEnumerable<ChatMessage>? inputMessages = this.GetInputMessages();
|
||||
|
||||
if (inputMessages is not null)
|
||||
{
|
||||
foreach (ChatMessage message in inputMessages)
|
||||
{
|
||||
await agentProvider.CreateMessageAsync(conversationId, message, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
private IEnumerable<ChatMessage>? GetInputMessages()
|
||||
{
|
||||
DataValue? messages = null;
|
||||
|
||||
if (this.Model.Messages is not null)
|
||||
{
|
||||
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(this.Model.Messages);
|
||||
messages = expressionResult.Value;
|
||||
}
|
||||
|
||||
return messages?.ToChatMessages();
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.PowerFx.Types;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class CreateConversationExecutor(CreateConversation model, WorkflowAgentProvider agentProvider, WorkflowFormulaState state) :
|
||||
DeclarativeActionExecutor<CreateConversation>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
string conversationId = await agentProvider.CreateConversationAsync(cancellationToken).ConfigureAwait(false);
|
||||
await this.AssignAsync(this.Model.ConversationId?.Path, FormulaValue.New(conversationId), context).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class DefaultActionExecutor(DialogAction model, WorkflowFormulaState state) :
|
||||
DeclarativeActionExecutor(model, state)
|
||||
{
|
||||
protected override ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
// No action needed - the edge will be followed automatically
|
||||
return default;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Bot.ObjectModel.Abstractions;
|
||||
using Microsoft.PowerFx.Types;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class EditTableExecutor(EditTable model, WorkflowFormulaState state) : DeclarativeActionExecutor<EditTable>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
PropertyPath variablePath = Throw.IfNull(this.Model.ItemsVariable?.Path, $"{nameof(this.Model)}.{nameof(this.Model.ItemsVariable)}");
|
||||
|
||||
FormulaValue table = context.ReadState(variablePath);
|
||||
if (table is not TableValue tableValue)
|
||||
{
|
||||
throw this.Exception($"Require '{variablePath}' to be a table, not: '{table.GetType().Name}'.");
|
||||
}
|
||||
|
||||
TableChangeType changeType = this.Model.ChangeType.Value;
|
||||
switch (this.Model.ChangeType.Value)
|
||||
{
|
||||
case TableChangeType.Add:
|
||||
ValueExpression addItemValue = Throw.IfNull(this.Model.Value, $"{nameof(this.Model)}.{nameof(this.Model.Value)}");
|
||||
EvaluationResult<DataValue> addResult = this.Evaluator.GetValue(addItemValue);
|
||||
RecordValue newRecord = BuildRecord(tableValue.Type.ToRecord(), addResult.Value.ToFormula());
|
||||
await tableValue.AppendAsync(newRecord, cancellationToken).ConfigureAwait(false);
|
||||
await this.AssignAsync(variablePath, newRecord, context).ConfigureAwait(false);
|
||||
break;
|
||||
case TableChangeType.Remove:
|
||||
ValueExpression removeItemValue = Throw.IfNull(this.Model.Value, $"{nameof(this.Model)}.{nameof(this.Model.Value)}");
|
||||
EvaluationResult<DataValue> removeResult = this.Evaluator.GetValue(removeItemValue);
|
||||
if (removeResult.Value is TableDataValue removeItemTable)
|
||||
{
|
||||
await tableValue.RemoveAsync(removeItemTable?.Values.Select(row => row.ToRecordValue()), all: true, cancellationToken).ConfigureAwait(false);
|
||||
await this.AssignAsync(variablePath, RecordValue.Empty(), context).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
case TableChangeType.Clear:
|
||||
await tableValue.ClearAsync(cancellationToken).ConfigureAwait(false);
|
||||
await this.AssignAsync(variablePath, FormulaValue.NewBlank(), context).ConfigureAwait(false);
|
||||
break;
|
||||
case TableChangeType.TakeFirst:
|
||||
RecordValue? firstRow = tableValue.Rows.FirstOrDefault()?.Value;
|
||||
if (firstRow is not null)
|
||||
{
|
||||
await tableValue.RemoveAsync([firstRow], all: true, cancellationToken).ConfigureAwait(false);
|
||||
await this.AssignAsync(variablePath, firstRow, context).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
case TableChangeType.TakeLast:
|
||||
RecordValue? lastRow = tableValue.Rows.LastOrDefault()?.Value;
|
||||
if (lastRow is not null)
|
||||
{
|
||||
await tableValue.RemoveAsync([lastRow], all: true, cancellationToken).ConfigureAwait(false);
|
||||
await this.AssignAsync(variablePath, lastRow, context).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return default;
|
||||
|
||||
static RecordValue BuildRecord(RecordType recordType, FormulaValue value)
|
||||
{
|
||||
return FormulaValue.NewRecordFromFields(recordType, GetValues());
|
||||
|
||||
IEnumerable<NamedValue> GetValues()
|
||||
{
|
||||
foreach (NamedFormulaType fieldType in recordType.GetFieldTypes())
|
||||
{
|
||||
if (value is RecordValue recordValue)
|
||||
{
|
||||
yield return new NamedValue(fieldType.Name, recordValue.GetField(fieldType.Name));
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new NamedValue(fieldType.Name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Bot.ObjectModel.Abstractions;
|
||||
using Microsoft.PowerFx.Types;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class EditTableV2Executor(EditTableV2 model, WorkflowFormulaState state) : DeclarativeActionExecutor<EditTableV2>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
PropertyPath variablePath = Throw.IfNull(this.Model.ItemsVariable?.Path, $"{nameof(this.Model)}.{nameof(this.Model.ItemsVariable)}");
|
||||
|
||||
FormulaValue table = context.ReadState(variablePath);
|
||||
if (table is not TableValue tableValue)
|
||||
{
|
||||
throw this.Exception($"Require '{variablePath}' to be a table, not: '{table.GetType().Name}'.");
|
||||
}
|
||||
|
||||
EditTableOperation? changeType = this.Model.ChangeType;
|
||||
if (changeType is AddItemOperation addItemOperation)
|
||||
{
|
||||
ValueExpression addItemValue = Throw.IfNull(addItemOperation.Value, $"{nameof(this.Model)}.{nameof(this.Model.ChangeType)}");
|
||||
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(addItemValue);
|
||||
RecordValue newRecord = BuildRecord(tableValue.Type.ToRecord(), expressionResult.Value.ToFormula());
|
||||
await tableValue.AppendAsync(newRecord, cancellationToken).ConfigureAwait(false);
|
||||
await this.AssignAsync(variablePath, newRecord, context).ConfigureAwait(false);
|
||||
}
|
||||
else if (changeType is ClearItemsOperation)
|
||||
{
|
||||
await tableValue.ClearAsync(cancellationToken).ConfigureAwait(false);
|
||||
await this.AssignAsync(variablePath, FormulaValue.NewBlank(), context).ConfigureAwait(false);
|
||||
}
|
||||
else if (changeType is RemoveItemOperation removeItemOperation)
|
||||
{
|
||||
ValueExpression removeItemValue = Throw.IfNull(removeItemOperation.Value, $"{nameof(this.Model)}.{nameof(this.Model.ChangeType)}");
|
||||
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(removeItemValue);
|
||||
if (expressionResult.Value.ToFormula() is TableValue removeItemTable)
|
||||
{
|
||||
await tableValue.RemoveAsync(removeItemTable?.Rows.Select(row => row.Value), all: true, cancellationToken).ConfigureAwait(false);
|
||||
await this.AssignAsync(variablePath, FormulaValue.NewBlank(), context).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else if (changeType is TakeLastItemOperation)
|
||||
{
|
||||
RecordValue? lastRow = tableValue.Rows.LastOrDefault()?.Value;
|
||||
if (lastRow is not null)
|
||||
{
|
||||
await tableValue.RemoveAsync([lastRow], all: true, cancellationToken).ConfigureAwait(false);
|
||||
await this.AssignAsync(variablePath, lastRow, context).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else if (changeType is TakeFirstItemOperation)
|
||||
{
|
||||
RecordValue? firstRow = tableValue.Rows.FirstOrDefault()?.Value;
|
||||
if (firstRow is not null)
|
||||
{
|
||||
await tableValue.RemoveAsync([firstRow], all: true, cancellationToken).ConfigureAwait(false);
|
||||
await this.AssignAsync(variablePath, firstRow, context).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
|
||||
static RecordValue BuildRecord(RecordType recordType, FormulaValue value)
|
||||
{
|
||||
return FormulaValue.NewRecordFromFields(recordType, GetValues());
|
||||
|
||||
IEnumerable<NamedValue> GetValues()
|
||||
{
|
||||
foreach (NamedFormulaType fieldType in recordType.GetFieldTypes())
|
||||
{
|
||||
if (value is RecordValue recordValue)
|
||||
{
|
||||
yield return new NamedValue(fieldType.Name, recordValue.GetField(fieldType.Name));
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new NamedValue(fieldType.Name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Bot.ObjectModel.Abstractions;
|
||||
using Microsoft.PowerFx.Types;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class ForeachExecutor : DeclarativeActionExecutor<Foreach>
|
||||
{
|
||||
public static class Steps
|
||||
{
|
||||
public static string Start(string id) => $"{id}_{nameof(Start)}";
|
||||
public static string Next(string id) => $"{id}_{nameof(Next)}";
|
||||
public static string End(string id) => $"{id}_{nameof(End)}";
|
||||
}
|
||||
|
||||
private int _index;
|
||||
private FormulaValue[] _values;
|
||||
|
||||
public ForeachExecutor(Foreach model, WorkflowFormulaState state)
|
||||
: base(model, state)
|
||||
{
|
||||
this._values = [];
|
||||
}
|
||||
|
||||
public bool HasValue { get; private set; }
|
||||
|
||||
protected override bool IsDiscreteAction => false;
|
||||
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
this._index = 0;
|
||||
|
||||
if (this.Model.Items is null)
|
||||
{
|
||||
this._values = [];
|
||||
this.HasValue = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(this.Model.Items);
|
||||
if (expressionResult.Value is TableDataValue tableValue)
|
||||
{
|
||||
this._values = [.. tableValue.Values.Select(value => value.Properties.Values.First().ToFormula())];
|
||||
}
|
||||
else
|
||||
{
|
||||
this._values = [expressionResult.Value.ToFormula()];
|
||||
}
|
||||
}
|
||||
|
||||
await this.ResetAsync(context, null, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public async ValueTask TakeNextAsync(IWorkflowContext context, object? _, CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.HasValue = this._index < this._values.Length)
|
||||
{
|
||||
FormulaValue value = this._values[this._index];
|
||||
|
||||
await context.QueueStateUpdateAsync(Throw.IfNull(this.Model.Value), value).ConfigureAwait(false);
|
||||
|
||||
if (this.Model.Index is not null)
|
||||
{
|
||||
await context.QueueStateUpdateAsync(this.Model.Index.Path, FormulaValue.New(this._index)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
this._index++;
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask ResetAsync(IWorkflowContext context, object? _, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
await context.QueueStateResetAsync(Throw.IfNull(this.Model.Value)).ConfigureAwait(false);
|
||||
if (this.Model.Index is not null)
|
||||
{
|
||||
await context.QueueStateResetAsync(this.Model.Index).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
await context.RaiseCompletionEventAsync(this.Model).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Bot.ObjectModel.Abstractions;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class InvokeAzureAgentExecutor(InvokeAzureAgent model, WorkflowAgentProvider agentProvider, WorkflowFormulaState state) :
|
||||
DeclarativeActionExecutor<InvokeAzureAgent>(model, state)
|
||||
{
|
||||
private AzureAgentUsage AgentUsage => Throw.IfNull(this.Model.Agent, $"{nameof(this.Model)}.{nameof(this.Model.Agent)}");
|
||||
private AzureAgentInput? AgentInput => this.Model.Input;
|
||||
private AzureAgentOutput? AgentOutput => this.Model.Output;
|
||||
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
string? conversationId = this.GetConversationId();
|
||||
string agentName = this.GetAgentName();
|
||||
string? additionalInstructions = this.GetAdditionalInstructions();
|
||||
bool autoSend = this.GetAutoSendValue();
|
||||
IEnumerable<ChatMessage>? inputMessages = this.GetInputMessages();
|
||||
|
||||
AgentRunResponse agentResponse = agentProvider.InvokeAgentAsync(this.Id, context, agentName, conversationId, autoSend, additionalInstructions, inputMessages, cancellationToken).ToEnumerable().ToAgentRunResponse();
|
||||
|
||||
if (autoSend)
|
||||
{
|
||||
await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await this.AssignAsync(this.AgentOutput?.Messages?.Path, agentResponse.Messages.ToTable(), context).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
private IEnumerable<ChatMessage>? GetInputMessages()
|
||||
{
|
||||
DataValue? userInput = null;
|
||||
|
||||
if (this.AgentInput?.Messages is not null)
|
||||
{
|
||||
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(this.AgentInput.Messages);
|
||||
userInput = expressionResult.Value;
|
||||
}
|
||||
|
||||
return userInput?.ToChatMessages();
|
||||
}
|
||||
|
||||
private string? GetConversationId()
|
||||
{
|
||||
if (this.Model.ConversationId is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
EvaluationResult<string> conversationIdResult = this.Evaluator.GetValue(this.Model.ConversationId);
|
||||
return conversationIdResult.Value.Length == 0 ? null : conversationIdResult.Value;
|
||||
}
|
||||
|
||||
private string GetAgentName() =>
|
||||
this.Evaluator.GetValue(
|
||||
Throw.IfNull(
|
||||
this.AgentUsage.Name,
|
||||
$"{nameof(this.Model)}.{nameof(this.Model.Agent)}.{nameof(this.Model.Agent.Name)}")).Value;
|
||||
|
||||
private string? GetAdditionalInstructions()
|
||||
{
|
||||
string? additionalInstructions = null;
|
||||
|
||||
if (this.AgentInput?.AdditionalInstructions is not null)
|
||||
{
|
||||
additionalInstructions = this.Engine.Format(this.AgentInput.AdditionalInstructions);
|
||||
}
|
||||
|
||||
return additionalInstructions;
|
||||
}
|
||||
|
||||
private bool GetAutoSendValue()
|
||||
{
|
||||
if (this.AgentOutput?.AutoSend is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
EvaluationResult<bool> autoSendResult = this.Evaluator.GetValue(this.AgentOutput.AutoSend);
|
||||
|
||||
return autoSendResult.Value;
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Bot.ObjectModel.Abstractions;
|
||||
using Microsoft.PowerFx.Types;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class ParseValueExecutor(ParseValue model, WorkflowFormulaState state) :
|
||||
DeclarativeActionExecutor<ParseValue>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
PropertyPath variablePath = Throw.IfNull(this.Model.Variable?.Path, $"{nameof(this.Model)}.{nameof(model.Variable)}");
|
||||
ValueExpression valueExpression = Throw.IfNull(this.Model.Value, $"{nameof(this.Model)}.{nameof(this.Model.Value)}");
|
||||
|
||||
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(valueExpression);
|
||||
|
||||
FormulaValue? parsedResult = null;
|
||||
|
||||
if (expressionResult.Value is RecordDataValue recordValue)
|
||||
{
|
||||
parsedResult = recordValue.ToFormula();
|
||||
}
|
||||
else if (expressionResult.Value is StringDataValue stringValue)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(stringValue.Value))
|
||||
{
|
||||
parsedResult = FormulaValue.NewBlank(expressionResult.Value.GetDataType().ToFormulaType());
|
||||
}
|
||||
else
|
||||
{
|
||||
parsedResult =
|
||||
this.Model.ValueType switch
|
||||
{
|
||||
StringDataType => FormulaValue.New(stringValue.Value),
|
||||
NumberDataType => FormulaValue.New(stringValue.Value),
|
||||
BooleanDataType => FormulaValue.New(stringValue.Value),
|
||||
RecordDataType recordType => ParseRecord(recordType, stringValue.Value),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (parsedResult is null)
|
||||
{
|
||||
throw this.Exception("Unable to parse value.");
|
||||
}
|
||||
|
||||
await this.AssignAsync(variablePath, parsedResult, context).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
|
||||
RecordValue ParseRecord(RecordDataType recordType, string rawText)
|
||||
{
|
||||
string jsonText = rawText.TrimJsonDelimiter();
|
||||
using JsonDocument json = JsonDocument.Parse(jsonText);
|
||||
try
|
||||
{
|
||||
return recordType.ParseRecord(json.RootElement);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw this.Exception("Failed to parse value.", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Entities;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Events;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.PowerFx.Types;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class QuestionExecutor(Question model, WorkflowFormulaState state) :
|
||||
DeclarativeActionExecutor<Question>(model, state)
|
||||
{
|
||||
public static class Steps
|
||||
{
|
||||
public static string Prepare(string id) => $"{id}_{nameof(Prepare)}";
|
||||
public static string Input(string id) => $"{id}_{nameof(Input)}";
|
||||
public static string Capture(string id) => $"{id}_{nameof(Capture)}";
|
||||
}
|
||||
|
||||
private readonly DurableProperty<int> _promptCount = new(nameof(_promptCount));
|
||||
private readonly DurableProperty<bool> _hasExecuted = new(nameof(_hasExecuted));
|
||||
|
||||
protected override bool IsDiscreteAction => false;
|
||||
protected override bool EmitResultEvent => false;
|
||||
|
||||
public static bool IsComplete(object? message) // %%% BASE CLASS ???
|
||||
{
|
||||
ActionExecutorResult executorMessage = ActionExecutorResult.ThrowIfNot(message);
|
||||
return executorMessage.Result is null;
|
||||
}
|
||||
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
await this._promptCount.WriteAsync(context, 0).ConfigureAwait(false);
|
||||
|
||||
InitializablePropertyPath variable = Throw.IfNull(this.Model.Variable);
|
||||
bool hasValue = context.ReadState(variable.Path) is BlankValue;
|
||||
bool alwaysPrompt = this.Evaluator.GetValue(this.Model.AlwaysPrompt).Value;
|
||||
|
||||
bool proceed = !alwaysPrompt || hasValue;
|
||||
if (proceed)
|
||||
{
|
||||
SkipQuestionMode mode = this.Evaluator.GetValue(this.Model.SkipQuestionMode).Value;
|
||||
proceed =
|
||||
mode switch
|
||||
{
|
||||
SkipQuestionMode.SkipOnFirstExecutionIfVariableHasValue => !await this._hasExecuted.ReadAsync(context).ConfigureAwait(false),
|
||||
SkipQuestionMode.AlwaysSkipIfVariableHasValue => hasValue,
|
||||
SkipQuestionMode.AlwaysAsk => true,
|
||||
_ => true,
|
||||
};
|
||||
}
|
||||
|
||||
if (proceed)
|
||||
{
|
||||
await this.PromptAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await context.SendResultMessageAsync(this.Id, result: null, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public async ValueTask PrepareResponseAsync(IWorkflowContext context, ActionExecutorResult message, CancellationToken cancellationToken)
|
||||
{
|
||||
int count = await this._promptCount.ReadAsync(context).ConfigureAwait(false);
|
||||
InputRequest inputRequest = new(this.FormatPrompt(this.Model.Prompt));
|
||||
await context.SendMessageAsync(inputRequest).ConfigureAwait(false);
|
||||
await this._promptCount.WriteAsync(context, count + 1).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async ValueTask CaptureResponseAsync(IWorkflowContext context, InputResponse message, CancellationToken cancellationToken)
|
||||
{
|
||||
FormulaValue? extractedValue = null;
|
||||
if (string.IsNullOrWhiteSpace(message.Value))
|
||||
{
|
||||
string unrecognizedResponse = this.FormatPrompt(this.Model.UnrecognizedPrompt);
|
||||
await context.AddEventAsync(new MessageActivityEvent(unrecognizedResponse.Trim())).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EntityExtractionResult entityResult = EntityExtractor.Parse(this.Model.Entity, message.Value);
|
||||
if (entityResult.IsValid)
|
||||
{
|
||||
extractedValue = entityResult.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
string invalidResponse = this.FormatPrompt(this.Model.InvalidPrompt);
|
||||
await context.AddEventAsync(new MessageActivityEvent(invalidResponse.Trim())).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (extractedValue is null)
|
||||
{
|
||||
await this.PromptAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await this.AssignAsync(this.Model.Variable?.Path, extractedValue, context).ConfigureAwait(false);
|
||||
await this._hasExecuted.WriteAsync(context, true).ConfigureAwait(false);
|
||||
await context.SendResultMessageAsync(this.Id, result: null, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask CompleteAsync(IWorkflowContext context, ActionExecutorResult message, CancellationToken cancellationToken)
|
||||
{
|
||||
await context.RaiseCompletionEventAsync(this.Model).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async ValueTask PromptAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
long repeatCount = this.Evaluator.GetValue(this.Model.RepeatCount).Value;
|
||||
int actualCount = await this._promptCount.ReadAsync(context).ConfigureAwait(false);
|
||||
if (actualCount >= repeatCount)
|
||||
{
|
||||
ValueExpression defaultValueExpression = Throw.IfNull(this.Model.DefaultValue);
|
||||
DataValue defaultValue = this.Evaluator.GetValue(defaultValueExpression).Value;
|
||||
await this.AssignAsync(this.Model.Variable?.Path, defaultValue.ToFormula(), context).ConfigureAwait(false);
|
||||
string defaultValueResponse = this.FormatPrompt(this.Model.DefaultValueResponse);
|
||||
await context.AddEventAsync(new MessageActivityEvent(defaultValueResponse.Trim())).ConfigureAwait(false);
|
||||
await context.SendResultMessageAsync(this.Id, result: null, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await context.SendResultMessageAsync(this.Id, result: true, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private string FormatPrompt(ActivityTemplateBase? promptTemplate)
|
||||
{
|
||||
if (promptTemplate is not MessageActivityTemplate messageActivity)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return this.Engine.Format(messageActivity.Text).Trim();
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class ResetVariableExecutor(ResetVariable model, WorkflowFormulaState state) :
|
||||
DeclarativeActionExecutor<ResetVariable>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
Throw.IfNull(this.Model.Variable, $"{nameof(this.Model)}.{nameof(model.Variable)}");
|
||||
await context.QueueStateResetAsync(this.Model.Variable).ConfigureAwait(false);
|
||||
Debug.WriteLine(
|
||||
$"""
|
||||
STATE: {this.GetType().Name} [{this.Id}]
|
||||
NAME: {this.Model.Variable}
|
||||
""");
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class RetrieveConversationMessageExecutor(RetrieveConversationMessage model, WorkflowAgentProvider agentProvider, WorkflowFormulaState state) :
|
||||
DeclarativeActionExecutor<RetrieveConversationMessage>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
|
||||
string conversationId = this.Evaluator.GetValue(this.Model.ConversationId).Value;
|
||||
string messageId = this.Evaluator.GetValue(Throw.IfNull(this.Model.MessageId, $"{nameof(this.Model)}.{nameof(this.Model.MessageId)}")).Value;
|
||||
|
||||
ChatMessage message = await agentProvider.GetMessageAsync(conversationId, messageId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await this.AssignAsync(this.Model.Message?.Path, message.ToRecord(), context).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class RetrieveConversationMessagesExecutor(RetrieveConversationMessages model, WorkflowAgentProvider agentProvider, WorkflowFormulaState state) :
|
||||
DeclarativeActionExecutor<RetrieveConversationMessages>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
|
||||
string conversationId = this.Evaluator.GetValue(this.Model.ConversationId).Value;
|
||||
|
||||
ChatMessage[] messages = await agentProvider.GetMessagesAsync(
|
||||
conversationId,
|
||||
limit: this.GetLimit(),
|
||||
after: this.GetMessage(this.Model.MessageAfter),
|
||||
before: this.GetMessage(this.Model.MessageBefore),
|
||||
newestFirst: this.IsDescending(),
|
||||
cancellationToken).ToArrayAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await this.AssignAsync(this.Model.Messages?.Path, messages.ToTable(), context).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
private int? GetLimit()
|
||||
{
|
||||
if (this.Model.Limit is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
long limit = this.Evaluator.GetValue(this.Model.Limit).Value;
|
||||
return Convert.ToInt32(Math.Min(limit, 100));
|
||||
}
|
||||
|
||||
private string? GetMessage(StringExpression? messagExpression)
|
||||
{
|
||||
if (messagExpression is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.Evaluator.GetValue(messagExpression).Value;
|
||||
}
|
||||
|
||||
private bool IsDescending()
|
||||
{
|
||||
if (this.Model.SortOrder is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AgentMessageSortOrderWrapper sortOrderWrapper = this.Evaluator.GetValue(this.Model.SortOrder).Value;
|
||||
|
||||
return sortOrderWrapper.Value == AgentMessageSortOrder.NewestFirst;
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class SendActivityExecutor(SendActivity model, WorkflowFormulaState state) :
|
||||
DeclarativeActionExecutor<SendActivity>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.Model.Activity is MessageActivityTemplate messageActivity)
|
||||
{
|
||||
string activityText = this.Engine.Format(messageActivity.Text).Trim();
|
||||
|
||||
await context.AddEventAsync(new MessageActivityEvent(activityText.Trim())).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Bot.ObjectModel.Abstractions;
|
||||
using Microsoft.PowerFx.Types;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class SetMultipleVariablesExecutor(SetMultipleVariables model, WorkflowFormulaState state)
|
||||
: DeclarativeActionExecutor<SetMultipleVariables>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (VariableAssignment assignment in this.Model.Assignments)
|
||||
{
|
||||
if (assignment.Variable is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (assignment.Value is null)
|
||||
{
|
||||
await this.AssignAsync(assignment.Variable, FormulaValue.NewBlank(), context).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(assignment.Value);
|
||||
|
||||
await this.AssignAsync(assignment.Variable, expressionResult.Value.ToFormula(), context).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.PowerFx.Types;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class SetTextVariableExecutor(SetTextVariable model, WorkflowFormulaState state)
|
||||
: DeclarativeActionExecutor<SetTextVariable>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.Model.Value is null)
|
||||
{
|
||||
await this.AssignAsync(this.Model.Variable?.Path, FormulaValue.NewBlank(), context).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
FormulaValue expressionResult = FormulaValue.New(this.Engine.Format(this.Model.Value));
|
||||
|
||||
await this.AssignAsync(this.Model.Variable?.Path, expressionResult, context).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Bot.ObjectModel.Abstractions;
|
||||
using Microsoft.PowerFx.Types;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
|
||||
internal sealed class SetVariableExecutor(SetVariable model, WorkflowFormulaState state)
|
||||
: DeclarativeActionExecutor<SetVariable>(model, state)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
PropertyPath variablePath = Throw.IfNull(this.Model.Variable?.Path, $"{nameof(this.Model)}.{nameof(model.Variable)}");
|
||||
|
||||
if (this.Model.Value is null)
|
||||
{
|
||||
await this.AssignAsync(variablePath, FormulaValue.NewBlank(), context).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(this.Model.Value);
|
||||
|
||||
await this.AssignAsync(variablePath, expressionResult.Value.ToFormula(), context).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user